This commit is contained in:
Andreas Preikschat 2012-03-31 15:59:47 +02:00
commit f6067002c0
241 changed files with 78904 additions and 28744 deletions

View File

@ -21,3 +21,5 @@ openlp/core/resources.py.old
*.qm *.qm
resources/windows/warnOpenLP.txt resources/windows/warnOpenLP.txt
openlp.cfg openlp.cfg
.idea
openlp.pro

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -5,8 +5,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -32,7 +32,7 @@ import logging
import os.path import os.path
import types import types
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui, Qt
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -43,6 +43,26 @@ class MediaType(object):
Audio = 1 Audio = 1
Video = 2 Video = 2
class SlideLimits(object):
"""
Provides an enumeration for behaviour of OpenLP at the end limits of each
service item when pressing the up/down arrow keys
"""
End = 1
Wrap = 2
Next = 3
class ServiceItemAction(object):
"""
Provides an enumeration for the required action moving between service
items by left/right arrow keys
"""
Previous = 1
PreviousLastSlide = 2
Next = 3
def translate(context, text, comment=None, def translate(context, text, comment=None,
encoding=QtCore.QCoreApplication.CodecForTr, n=-1, encoding=QtCore.QCoreApplication.CodecForTr, n=-1,
translate=QtCore.QCoreApplication.translate): translate=QtCore.QCoreApplication.translate):
@ -298,6 +318,34 @@ def check_directory_exists(dir):
except IOError: except IOError:
pass pass
def create_separated_list(stringlist):
"""
Returns a string that represents a join of a list of strings with a
localized separator. This function corresponds to
QLocale::createSeparatedList which was introduced in Qt 4.8 and implements
the algorithm from http://www.unicode.org/reports/tr35/#ListPatterns
``stringlist``
List of unicode strings
"""
if Qt.PYQT_VERSION_STR >= u'4.9' and Qt.qVersion() >= u'4.8':
return unicode(QtCore.QLocale().createSeparatedList(stringlist))
if not stringlist:
return u''
elif len(stringlist) == 1:
return stringlist[0]
elif len(stringlist) == 2:
return unicode(translate('OpenLP.core.lib', '%1 and %2',
'Locale list separator: 2 items').arg(stringlist[0], stringlist[1]))
else:
merged = unicode(translate('OpenLP.core.lib', '%1, and %2',
u'Locale list separator: end').arg(stringlist[-2], stringlist[-1]))
for index in reversed(range(1, len(stringlist) - 2)):
merged = unicode(translate('OpenLP.core.lib', '%1, %2',
u'Locale list separator: middle').arg(stringlist[index], merged))
return unicode(translate('OpenLP.core.lib', '%1, %2',
u'Locale list separator: start').arg(stringlist[0], merged))
from eventreceiver import Receiver from eventreceiver import Receiver
from listwidgetwithdnd import ListWidgetWithDnD from listwidgetwithdnd import ListWidgetWithDnD
from formattingtags import FormattingTags from formattingtags import FormattingTags

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -33,7 +33,8 @@ from urllib import quote_plus as urlquote
from PyQt4 import QtCore from PyQt4 import QtCore
from sqlalchemy import Table, MetaData, Column, types, create_engine from sqlalchemy import Table, MetaData, Column, types, create_engine
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, \
OperationalError
from sqlalchemy.orm import scoped_session, sessionmaker, mapper from sqlalchemy.orm import scoped_session, sessionmaker, mapper
from sqlalchemy.pool import NullPool from sqlalchemy.pool import NullPool
@ -199,6 +200,10 @@ class Manager(object):
urlquote(unicode(settings.value(u'db password').toString())), urlquote(unicode(settings.value(u'db password').toString())),
urlquote(unicode(settings.value(u'db hostname').toString())), urlquote(unicode(settings.value(u'db hostname').toString())),
urlquote(unicode(settings.value(u'db database').toString()))) urlquote(unicode(settings.value(u'db database').toString())))
if db_type == u'mysql':
db_encoding = unicode(
settings.value(u'db encoding', u'utf8').toString())
self.db_url += u'?charset=%s' % urlquote(db_encoding)
settings.endGroup() settings.endGroup()
if upgrade_mod: if upgrade_mod:
db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod) db_ver, up_ver = upgrade_db(self.db_url, upgrade_mod)
@ -239,6 +244,17 @@ class Manager(object):
self.session.commit() self.session.commit()
self.is_dirty = True self.is_dirty = True
return 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: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Object save failed') log.exception(u'Object save failed')
@ -260,6 +276,17 @@ class Manager(object):
self.session.commit() self.session.commit()
self.is_dirty = True self.is_dirty = True
return 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: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Object list save failed') log.exception(u'Object list save failed')
@ -278,6 +305,14 @@ class Manager(object):
if not key: if not key:
return object_class() return object_class()
else: 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) return self.session.query(object_class).get(key)
def get_object_filtered(self, object_class, filter_clause): def get_object_filtered(self, object_class, filter_clause):
@ -290,6 +325,14 @@ class Manager(object):
``filter_clause`` ``filter_clause``
The criteria to select the object by 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() return self.session.query(object_class).filter(filter_clause).first()
def get_all_objects(self, object_class, filter_clause=None, def get_all_objects(self, object_class, filter_clause=None,
@ -311,9 +354,17 @@ class Manager(object):
if filter_clause is not None: if filter_clause is not None:
query = query.filter(filter_clause) query = query.filter(filter_clause)
if isinstance(order_by_ref, list): if isinstance(order_by_ref, list):
return query.order_by(*order_by_ref).all() query = query.order_by(*order_by_ref)
elif order_by_ref is not None: elif order_by_ref is not None:
return query.order_by(order_by_ref).all() 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() return query.all()
def get_object_count(self, object_class, filter_clause=None): def get_object_count(self, object_class, filter_clause=None):
@ -330,6 +381,14 @@ class Manager(object):
query = self.session.query(object_class) query = self.session.query(object_class)
if filter_clause is not None: if filter_clause is not None:
query = query.filter(filter_clause) query = query.filter(filter_clause)
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() return query.count()
def delete_object(self, object_class, key): def delete_object(self, object_class, key):
@ -349,6 +408,16 @@ class Manager(object):
self.session.commit() self.session.commit()
self.is_dirty = True self.is_dirty = True
return 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: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Failed to delete object') log.exception(u'Failed to delete object')
@ -378,6 +447,19 @@ class Manager(object):
self.session.commit() self.session.commit()
self.is_dirty = True self.is_dirty = True
return 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: except InvalidRequestError:
self.session.rollback() self.session.rollback()
log.exception(u'Failed to delete %s records', object_class.__name__) log.exception(u'Failed to delete %s records', object_class.__name__)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -112,6 +112,9 @@ class EventReceiver(QtCore.QObject):
``slidecontroller_live_spin_delay`` ``slidecontroller_live_spin_delay``
Pushes out the loop delay. Pushes out the loop delay.
``slidecontroller_update_slide_limits``
Updates the slide_limits variable from the saved settings.
``slidecontroller_live_stop_loop`` ``slidecontroller_live_stop_loop``
Stop the loop on the main display. Stop the loop on the main display.
@ -214,6 +217,9 @@ class EventReceiver(QtCore.QObject):
Ask the plugin to process an individual service item after it has been Ask the plugin to process an individual service item after it has been
loaded. loaded.
``{plugin}_config_updated``
The config has changed so tell the plugin about it.
``alerts_text`` ``alerts_text``
Displays an alert message. Displays an alert message.

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -45,6 +45,7 @@ HTMLSRC = u"""
padding: 0; padding: 0;
border: 0; border: 0;
overflow: hidden; overflow: hidden;
-webkit-user-select: none;
} }
body { body {
%s; %s;
@ -288,6 +289,9 @@ def build_background_css(item, width, height):
background = u'background-color: black' background = u'background-color: black'
if theme: if theme:
if theme.background_type == \ if theme.background_type == \
BackgroundType.to_string(BackgroundType.Transparent):
background = u''
elif theme.background_type == \
BackgroundType.to_string(BackgroundType.Solid): BackgroundType.to_string(BackgroundType.Solid):
background = u'background-color: %s' % theme.background_color background = u'background-color: %s' % theme.background_color
else: else:
@ -454,13 +458,18 @@ def build_lyrics_format_css(theme, width, height):
# fix tag incompatibilities # fix tag incompatibilities
if theme.display_horizontal_align == HorizontalType.Justify: if theme.display_horizontal_align == HorizontalType.Justify:
justify = u'' justify = u''
if theme.display_vertical_align == VerticalType.Bottom:
padding_bottom = u'0.5em'
else:
padding_bottom = u'0'
lyrics = u'%s word-wrap: break-word; ' \ lyrics = u'%s word-wrap: break-word; ' \
'text-align: %s; vertical-align: %s; font-family: %s; ' \ 'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \ 'font-size: %spt; color: %s; line-height: %d%%; margin: 0;' \
'padding: 0; padding-left: %spx; width: %spx; height: %spx; ' % \ 'padding: 0; padding-bottom: %s; padding-left: %spx; width: %spx;' \
'height: %spx; ' % \
(justify, align, valign, theme.font_main_name, theme.font_main_size, (justify, align, valign, theme.font_main_name, theme.font_main_size,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment), theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
left_margin, width, height) padding_bottom, left_margin, width, height)
if theme.font_main_outline: if theme.font_main_outline:
if webkit_version() <= 534.3: if webkit_version() <= 534.3:
lyrics += u' letter-spacing: 1px;' lyrics += u' letter-spacing: 1px;'

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -166,7 +166,7 @@ class ImageManager(QtCore.QObject):
self.height = current_screen[u'size'].height() self.height = current_screen[u'size'].height()
# Mark the images as dirty for a rebuild by setting the image and byte # Mark the images as dirty for a rebuild by setting the image and byte
# stream to None. # stream to None.
for key, image in self._cache.iteritems(): for image in self._cache.values():
self._reset_image(image) self._reset_image(image)
def update_images(self, image_type, background): def update_images(self, image_type, background):
@ -176,7 +176,7 @@ class ImageManager(QtCore.QObject):
log.debug(u'update_images') log.debug(u'update_images')
# Mark the images as dirty for a rebuild by setting the image and byte # Mark the images as dirty for a rebuild by setting the image and byte
# stream to None. # stream to None.
for key, image in self._cache.iteritems(): for image in self._cache.values():
if image.source == image_type: if image.source == image_type:
image.background = background image.background = background
self._reset_image(image) self._reset_image(image)
@ -188,7 +188,7 @@ class ImageManager(QtCore.QObject):
log.debug(u'update_images') log.debug(u'update_images')
# Mark the images as dirty for a rebuild by setting the image and byte # Mark the images as dirty for a rebuild by setting the image and byte
# stream to None. # stream to None.
for key, image in self._cache.iteritems(): for image in self._cache.values():
if image.source == image_type and image.name == name: if image.source == image_type and image.name == name:
image.background = background image.background = background
self._reset_image(image) self._reset_image(image)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -35,8 +35,9 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \ from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, \
StringContent, build_icon, translate, Receiver, ListWidgetWithDnD StringContent, build_icon, translate, Receiver, ListWidgetWithDnD
from openlp.core.lib.ui import UiStrings, context_menu_action, \ from openlp.core.lib.searchedit import SearchEdit
context_menu_separator, critical_error_message_box from openlp.core.lib.ui import UiStrings, create_widget_action, \
critical_error_message_box
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -146,43 +147,6 @@ class MediaManagerItem(QtGui.QWidget):
self.toolbar = OpenLPToolbar(self) self.toolbar = OpenLPToolbar(self)
self.pageLayout.addWidget(self.toolbar) self.pageLayout.addWidget(self.toolbar)
def addToolbarButton(
self, title, tooltip, icon, slot=None, checkable=False):
"""
A method to help developers easily add a button to the toolbar.
``title``
The title of the button.
``tooltip``
The tooltip to be displayed when the mouse hovers over the
button.
``icon``
The icon of the button. This can be an instance of QIcon, or a
string containing either the absolute path to the image, or an
internal resource path starting with ':/'.
``slot``
The method to call when the button is clicked.
``checkable``
If *True* the button has two, *off* and *on*, states. Default is
*False*, which means the buttons has only one state.
"""
# NB different order (when I broke this out, I didn't want to
# break compatability), but it makes sense for the icon to
# come before the tooltip (as you have to have an icon, but
# not neccesarily a tooltip)
return self.toolbar.addToolbarButton(title, icon, tooltip, slot,
checkable)
def addToolbarSeparator(self):
"""
A very simple method to add a separator to the toolbar.
"""
self.toolbar.addSeparator()
def setupUi(self): def setupUi(self):
""" """
This method sets up the interface on the button. Plugin This method sets up the interface on the button. Plugin
@ -207,40 +171,41 @@ class MediaManagerItem(QtGui.QWidget):
toolbar_actions = [] toolbar_actions = []
## Import Button ## ## Import Button ##
if self.hasImportIcon: if self.hasImportIcon:
toolbar_actions.append([StringContent.Import, toolbar_actions.append([u'Import', StringContent.Import,
u':/general/general_import.png', self.onImportClick]) u':/general/general_import.png', self.onImportClick])
## Load Button ## ## Load Button ##
if self.hasFileIcon: if self.hasFileIcon:
toolbar_actions.append([StringContent.Load, toolbar_actions.append([u'Load', StringContent.Load,
u':/general/general_open.png', self.onFileClick]) u':/general/general_open.png', self.onFileClick])
## New Button ## ## New Button ##
if self.hasNewIcon: if self.hasNewIcon:
toolbar_actions.append([StringContent.New, toolbar_actions.append([u'New', StringContent.New,
u':/general/general_new.png', self.onNewClick]) u':/general/general_new.png', self.onNewClick])
## Edit Button ## ## Edit Button ##
if self.hasEditIcon: if self.hasEditIcon:
toolbar_actions.append([StringContent.Edit, toolbar_actions.append([u'Edit', StringContent.Edit,
u':/general/general_edit.png', self.onEditClick]) u':/general/general_edit.png', self.onEditClick])
## Delete Button ## ## Delete Button ##
if self.hasDeleteIcon: if self.hasDeleteIcon:
toolbar_actions.append([StringContent.Delete, toolbar_actions.append([u'Delete', StringContent.Delete,
u':/general/general_delete.png', self.onDeleteClick]) u':/general/general_delete.png', self.onDeleteClick])
## Preview ## ## Preview ##
toolbar_actions.append([StringContent.Preview, toolbar_actions.append([u'Preview', StringContent.Preview,
u':/general/general_preview.png', self.onPreviewClick]) u':/general/general_preview.png', self.onPreviewClick])
## Live Button ## ## Live Button ##
toolbar_actions.append([StringContent.Live, toolbar_actions.append([u'Live', StringContent.Live,
u':/general/general_live.png', self.onLiveClick]) u':/general/general_live.png', self.onLiveClick])
## Add to service Button ## ## Add to service Button ##
toolbar_actions.append([StringContent.Service, toolbar_actions.append([u'Service', StringContent.Service,
u':/general/general_add.png', self.onAddClick]) u':/general/general_add.png', self.onAddClick])
for action in toolbar_actions: for action in toolbar_actions:
if action[0] == StringContent.Preview: if action[0] == StringContent.Preview:
self.addToolbarSeparator() self.toolbar.addSeparator()
self.addToolbarButton( self.toolbar.addToolbarAction(
self.plugin.getString(action[0])[u'title'], u'%s%sAction' % (self.plugin.name, action[0]),
self.plugin.getString(action[0])[u'tooltip'], text=self.plugin.getString(action[1])[u'title'], icon=action[2],
action[1], action[2]) tooltip=self.plugin.getString(action[1])[u'tooltip'],
triggers=action[3])
def addListViewToToolBar(self): def addListViewToToolBar(self):
""" """
@ -258,35 +223,37 @@ class MediaManagerItem(QtGui.QWidget):
# define and add the context menu # define and add the context menu
self.listView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.listView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
if self.hasEditIcon: if self.hasEditIcon:
context_menu_action( create_widget_action(self.listView,
self.listView, u':/general/general_edit.png', text=self.plugin.getString(StringContent.Edit)[u'title'],
self.plugin.getString(StringContent.Edit)[u'title'], icon=u':/general/general_edit.png',
self.onEditClick) triggers=self.onEditClick)
context_menu_separator(self.listView) create_widget_action(self.listView, separator=True)
if self.hasDeleteIcon: if self.hasDeleteIcon:
context_menu_action( create_widget_action(self.listView,
self.listView, u':/general/general_delete.png', text=self.plugin.getString(StringContent.Delete)[u'title'],
self.plugin.getString(StringContent.Delete)[u'title'], icon=u':/general/general_delete.png',
self.onDeleteClick, [QtCore.Qt.Key_Delete]) shortcuts=[QtCore.Qt.Key_Delete], triggers=self.onDeleteClick)
context_menu_separator(self.listView) create_widget_action(self.listView, separator=True)
context_menu_action( create_widget_action(self.listView,
self.listView, u':/general/general_preview.png', text=self.plugin.getString(StringContent.Preview)[u'title'],
self.plugin.getString(StringContent.Preview)[u'title'], icon=u':/general/general_preview.png',
self.onPreviewClick, [QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]) shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return],
context_menu_action( triggers=self.onPreviewClick)
self.listView, u':/general/general_live.png', create_widget_action(self.listView,
self.plugin.getString(StringContent.Live)[u'title'], text=self.plugin.getString(StringContent.Live)[u'title'],
self.onLiveClick, [QtCore.Qt.ShiftModifier + QtCore.Qt.Key_Enter, icon=u':/general/general_live.png',
QtCore.Qt.ShiftModifier + QtCore.Qt.Key_Return]) shortcuts=[QtCore.Qt.ShiftModifier | QtCore.Qt.Key_Enter,
context_menu_action( QtCore.Qt.ShiftModifier | QtCore.Qt.Key_Return],
self.listView, u':/general/general_add.png', triggers=self.onLiveClick)
self.plugin.getString(StringContent.Service)[u'title'], create_widget_action(self.listView,
self.onAddClick, [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal]) text=self.plugin.getString(StringContent.Service)[u'title'],
icon=u':/general/general_add.png',
shortcuts=[QtCore.Qt.Key_Plus, QtCore.Qt.Key_Equal],
triggers=self.onAddClick)
if self.addToServiceItem: if self.addToServiceItem:
context_menu_action( create_widget_action(self.listView, text=translate(
self.listView, u':/general/general_add.png', 'OpenLP.MediaManagerItem', '&Add to selected Service Item'),
translate('OpenLP.MediaManagerItem', icon=u':/general/general_add.png', triggers=self.onAddEditClick)
'&Add to selected Service Item'), self.onAddEditClick)
self.addCustomContextActions() self.addCustomContextActions()
# Create the context menu and add all actions from the listView. # Create the context menu and add all actions from the listView.
self.menu = QtGui.QMenu() self.menu = QtGui.QMenu()
@ -301,6 +268,40 @@ class MediaManagerItem(QtGui.QWidget):
QtCore.SIGNAL('customContextMenuRequested(QPoint)'), QtCore.SIGNAL('customContextMenuRequested(QPoint)'),
self.contextMenu) self.contextMenu)
def addSearchToToolBar(self):
"""
Creates a search field with button and related signal handling.
"""
self.searchWidget = QtGui.QWidget(self)
self.searchWidget.setObjectName(u'searchWidget')
self.searchLayout = QtGui.QVBoxLayout(self.searchWidget)
self.searchLayout.setObjectName(u'searchLayout')
self.searchTextLayout = QtGui.QFormLayout()
self.searchTextLayout.setObjectName(u'searchTextLayout')
self.searchTextLabel = QtGui.QLabel(self.searchWidget)
self.searchTextLabel.setObjectName(u'searchTextLabel')
self.searchTextEdit = SearchEdit(self.searchWidget)
self.searchTextEdit.setObjectName(u'searchTextEdit')
self.searchTextLabel.setBuddy(self.searchTextEdit)
self.searchTextLayout.addRow(self.searchTextLabel, self.searchTextEdit)
self.searchLayout.addLayout(self.searchTextLayout)
self.searchButtonLayout = QtGui.QHBoxLayout()
self.searchButtonLayout.setObjectName(u'searchButtonLayout')
self.searchButtonLayout.addStretch()
self.searchTextButton = QtGui.QPushButton(self.searchWidget)
self.searchTextButton.setObjectName(u'searchTextButton')
self.searchButtonLayout.addWidget(self.searchTextButton)
self.searchLayout.addLayout(self.searchButtonLayout)
self.pageLayout.addWidget(self.searchWidget)
# Signals and slots
QtCore.QObject.connect(self.searchTextEdit,
QtCore.SIGNAL(u'returnPressed()'), self.onSearchTextButtonClick)
QtCore.QObject.connect(self.searchTextButton,
QtCore.SIGNAL(u'pressed()'), self.onSearchTextButtonClick)
QtCore.QObject.connect(self.searchTextEdit,
QtCore.SIGNAL(u'textChanged(const QString&)'),
self.onSearchTextEditChanged)
def addCustomContextActions(self): def addCustomContextActions(self):
""" """
Implement this method in your descendent media manager item to Implement this method in your descendent media manager item to
@ -640,7 +641,7 @@ class MediaManagerItem(QtGui.QWidget):
if item: if item:
self.autoSelectId = item.data(QtCore.Qt.UserRole).toInt()[0] self.autoSelectId = item.data(QtCore.Qt.UserRole).toInt()[0]
def search(self, string): def search(self, string, showError=True):
""" """
Performs a plugin specific search for items containing ``string`` Performs a plugin specific search for items containing ``string``
""" """

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -173,6 +173,9 @@ class Plugin(QtCore.QObject):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_add_service_item' % self.name), QtCore.SIGNAL(u'%s_add_service_item' % self.name),
self.processAddServiceEvent) self.processAddServiceEvent)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_config_updated' % self.name),
self.configUpdated)
def checkPreConditions(self): def checkPreConditions(self):
""" """
@ -395,3 +398,9 @@ class Plugin(QtCore.QObject):
Add html code to htmlbuilder. Add html code to htmlbuilder.
""" """
return u'' return u''
def configUpdated(self):
"""
The plugin's config has changed
"""
pass

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -289,7 +289,7 @@ class Renderer(object):
def _calculate_default(self): def _calculate_default(self):
""" """
Calculate the default dimentions of the screen. Calculate the default dimensions of the screen.
""" """
screen_size = self.screens.current[u'size'] screen_size = self.screens.current[u'size']
self.width = screen_size.width() self.width = screen_size.width()
@ -380,6 +380,7 @@ class Renderer(object):
(build_lyrics_format_css(self.theme_data, self.page_width, (build_lyrics_format_css(self.theme_data, self.page_width,
self.page_height), build_lyrics_outline_css(self.theme_data)) self.page_height), build_lyrics_outline_css(self.theme_data))
self.web.setHtml(html) self.web.setHtml(html)
self.empty_height = self.web_frame.contentsSize().height()
def _paginate_slide(self, lines, line_end): def _paginate_slide(self, lines, line_end):
""" """
@ -600,7 +601,7 @@ class Renderer(object):
""" """
self.web_frame.evaluateJavaScript(u'show_text("%s")' % self.web_frame.evaluateJavaScript(u'show_text("%s")' %
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"')) text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
return self.web_frame.contentsSize().height() <= self.page_height return self.web_frame.contentsSize().height() <= self.empty_height
def _words_split(self, line): def _words_split(self, line):
""" """

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -30,7 +30,7 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon from openlp.core.lib import build_icon
from openlp.core.lib.ui import icon_action from openlp.core.lib.ui import create_widget_action
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -122,6 +122,13 @@ class SearchEdit(QtGui.QLineEdit):
menu = self.menuButton.menu() menu = self.menuButton.menu()
for action in menu.actions(): for action in menu.actions():
if identifier == action.data().toInt()[0]: if identifier == action.data().toInt()[0]:
# setPlaceholderText has been implemented in Qt 4.7 and in at
# least PyQt 4.9 (I am not sure, if it was implemented in
# PyQt 4.8).
try:
self.setPlaceholderText(action.placeholderText)
except AttributeError:
pass
self.menuButton.setDefaultAction(action) self.menuButton.setDefaultAction(action)
self._currentSearchType = identifier self._currentSearchType = identifier
self.emit(QtCore.SIGNAL(u'searchTypeChanged(int)'), identifier) self.emit(QtCore.SIGNAL(u'searchTypeChanged(int)'), identifier)
@ -137,25 +144,22 @@ class SearchEdit(QtGui.QLineEdit):
identifier, an icon (QIcon instance or string) and a title for the identifier, an icon (QIcon instance or string) and a title for the
item in the menu. In short, they should look like this:: item in the menu. In short, they should look like this::
(<identifier>, <icon>, <title>) (<identifier>, <icon>, <title>, <place holder text>)
For instance:: For instance::
(1, <QIcon instance>, "Titles") (1, <QIcon instance>, "Titles", "Search Song Titles...")
Or:: Or::
(2, ":/songs/authors.png", "Authors") (2, ":/songs/authors.png", "Authors", "Search Authors...")
""" """
menu = QtGui.QMenu(self) menu = QtGui.QMenu(self)
first = None first = None
for identifier, icon, title in items: for identifier, icon, title, placeholder in items:
action = icon_action(menu, u'', icon) action = create_widget_action(menu, text=title, icon=icon,
action.setText(title) data=identifier, triggers=self._onMenuActionTriggered)
action.setData(QtCore.QVariant(identifier)) action.placeholderText = placeholder
menu.addAction(action)
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'),
self._onMenuActionTriggered)
if first is None: if first is None:
first = action first = action
self._currentSearchType = identifier self._currentSearchType = identifier
@ -206,5 +210,12 @@ class SearchEdit(QtGui.QLineEdit):
action.setChecked(False) action.setChecked(False)
self.menuButton.setDefaultAction(sender) self.menuButton.setDefaultAction(sender)
self._currentSearchType = sender.data().toInt()[0] self._currentSearchType = sender.data().toInt()[0]
# setPlaceholderText has been implemented in Qt 4.7 and in at least
# PyQt 4.9 (I am not sure, if it was implemented in PyQt 4.8).
try:
self.setPlaceholderText(
self.menuButton.defaultAction().placeholderText)
except AttributeError:
pass
self.emit(QtCore.SIGNAL(u'searchTypeChanged(int)'), self.emit(QtCore.SIGNAL(u'searchTypeChanged(int)'),
self._currentSearchType) self._currentSearchType)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -300,6 +300,7 @@ class ServiceItem(object):
``path`` ``path``
Defaults to *None*. Any path data, usually for images. Defaults to *None*. Any path data, usually for images.
""" """
log.debug(u'set_from_service called with path %s' % path)
header = serviceitem[u'serviceitem'][u'header'] header = serviceitem[u'serviceitem'][u'header']
self.title = header[u'title'] self.title = header[u'title']
self.name = header[u'name'] self.name = header[u'name']
@ -325,7 +326,10 @@ class ServiceItem(object):
if u'media_length' in header: if u'media_length' in header:
self.media_length = header[u'media_length'] self.media_length = header[u'media_length']
if u'background_audio' in header: if u'background_audio' in header:
self.background_audio = header[u'background_audio'] self.background_audio = []
for filename in header[u'background_audio']:
# Give them real file paths
self.background_audio.append(os.path.join(path, filename))
self.theme_overwritten = header.get(u'theme_overwritten', False) self.theme_overwritten = header.get(u'theme_overwritten', False)
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
for slide in serviceitem[u'serviceitem'][u'data']: for slide in serviceitem[u'serviceitem'][u'data']:

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -40,7 +40,7 @@ except ImportError:
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, FormattingTags from openlp.core.lib import translate, FormattingTags
from openlp.core.lib.ui import checkable_action from openlp.core.lib.ui import create_action
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -90,9 +90,8 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
lang_menu = QtGui.QMenu( lang_menu = QtGui.QMenu(
translate('OpenLP.SpellTextEdit', 'Language:')) translate('OpenLP.SpellTextEdit', 'Language:'))
for lang in enchant.list_languages(): for lang in enchant.list_languages():
action = checkable_action( action = create_action(lang_menu, lang, text=lang,
lang_menu, lang, lang == self.dictionary.tag) checked=lang == self.dictionary.tag)
action.setText(lang)
lang_menu.addAction(action) lang_menu.addAction(action)
popupMenu.insertSeparator(popupMenu.actions()[0]) popupMenu.insertSeparator(popupMenu.actions()[0])
popupMenu.insertMenu(popupMenu.actions()[0], lang_menu) popupMenu.insertMenu(popupMenu.actions()[0], lang_menu)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -100,6 +100,7 @@ class BackgroundType(object):
Solid = 0 Solid = 0
Gradient = 1 Gradient = 1
Image = 2 Image = 2
Transparent = 3
@staticmethod @staticmethod
def to_string(background_type): def to_string(background_type):
@ -112,6 +113,8 @@ class BackgroundType(object):
return u'gradient' return u'gradient'
elif background_type == BackgroundType.Image: elif background_type == BackgroundType.Image:
return u'image' return u'image'
elif background_type == BackgroundType.Transparent:
return u'transparent'
@staticmethod @staticmethod
def from_string(type_string): def from_string(type_string):
@ -124,6 +127,8 @@ class BackgroundType(object):
return BackgroundType.Gradient return BackgroundType.Gradient
elif type_string == u'image': elif type_string == u'image':
return BackgroundType.Image return BackgroundType.Image
elif type_string == u'transparent':
return BackgroundType.Transparent
class BackgroundGradientType(object): class BackgroundGradientType(object):
@ -246,7 +251,7 @@ class ThemeXML(object):
Add a transparent background. Add a transparent background.
""" """
background = self.theme_xml.createElement(u'background') background = self.theme_xml.createElement(u'background')
background.setAttribute(u'mode', u'transparent') background.setAttribute(u'type', u'transparent')
self.theme.appendChild(background) self.theme.appendChild(background)
def add_background_solid(self, bkcolor): def add_background_solid(self, bkcolor):
@ -487,25 +492,25 @@ class ThemeXML(object):
return return
xml_iter = theme_xml.getiterator() xml_iter = theme_xml.getiterator()
for element in xml_iter: for element in xml_iter:
parent = element.getparent()
master = u'' master = u''
if element.tag == u'background':
if element.attrib:
for attr in element.attrib:
self._create_attr(element.tag, attr, \
element.attrib[attr])
parent = element.getparent()
if parent is not None: if parent is not None:
if element.getparent().tag == u'font': if parent.tag == u'font':
master = element.getparent().tag + u'_' + \ master = parent.tag + u'_' + parent.attrib[u'type']
element.getparent().attrib[u'type']
# set up Outline and Shadow Tags and move to font_main # set up Outline and Shadow Tags and move to font_main
if element.getparent().tag == u'display': if parent.tag == u'display':
if element.tag.startswith(u'shadow') or \ if element.tag.startswith(u'shadow') or \
element.tag.startswith(u'outline'): element.tag.startswith(u'outline'):
self._create_attr(u'font_main', element.tag, self._create_attr(u'font_main', element.tag,
element.text) element.text)
master = element.getparent().tag master = parent.tag
if element.getparent().tag == u'background': if parent.tag == u'background':
master = element.getparent().tag master = parent.tag
if element.getparent().attrib:
for attr in element.getparent().attrib:
self._create_attr(master, attr, \
element.getparent().attrib[attr])
if master: if master:
self._create_attr(master, element.tag, element.text) self._create_attr(master, element.tag, element.text)
if element.attrib: if element.attrib:
@ -599,9 +604,13 @@ class ThemeXML(object):
self.background_start_color, self.background_start_color,
self.background_end_color, self.background_end_color,
self.background_direction) self.background_direction)
else: elif self.background_type == \
BackgroundType.to_string(BackgroundType.Image):
filename = os.path.split(self.background_filename)[1] filename = os.path.split(self.background_filename)[1]
self.add_background_image(filename, self.background_border_color) self.add_background_image(filename, self.background_border_color)
elif self.background_type == \
BackgroundType.to_string(BackgroundType.Transparent):
self.add_background_transparent()
self.add_font(self.font_main_name, self.add_font(self.font_main_name,
self.font_main_color, self.font_main_color,
self.font_main_size, self.font_main_size,

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -31,7 +31,7 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon from openlp.core.lib.ui import create_widget_action
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -46,122 +46,41 @@ class OpenLPToolbar(QtGui.QToolBar):
""" """
QtGui.QToolBar.__init__(self, parent) QtGui.QToolBar.__init__(self, parent)
# useful to be able to reuse button icons... # useful to be able to reuse button icons...
self.icons = {}
self.setIconSize(QtCore.QSize(20, 20)) self.setIconSize(QtCore.QSize(20, 20))
self.actions = {} self.actions = {}
log.debug(u'Init done for %s' % parent.__class__.__name__) log.debug(u'Init done for %s' % parent.__class__.__name__)
def addToolbarButton(self, title, icon, tooltip=None, slot=None, def addToolbarAction(self, name, **kwargs):
checkable=False, shortcuts=None, context=QtCore.Qt.WidgetShortcut):
""" """
A method to help developers easily add a button to the toolbar. A method to help developers easily add a button to the toolbar.
A new QAction is created by calling ``create_action()``. The action is
``title`` added to the toolbar and the toolbar is set as parent.
The title of the button. For more details please look at openlp.core.lib.ui.create_action()
``icon``
The icon of the button. This can be an instance of QIcon, or a
string containing either the absolute path to the image, or an
internal resource path starting with ':/'.
``tooltip``
A hint or tooltip for this button.
``slot``
The method to run when this button is clicked.
``checkable``
If *True* the button has two, *off* and *on*, states. Default is
*False*, which means the buttons has only one state.
``shortcuts``
The list of shortcuts for this action
``context``
Specify the context in which this shortcut is valid
""" """
if icon: action = create_widget_action(self, name, **kwargs)
actionIcon = build_icon(icon) self.actions[name] = action
if slot and not checkable: return action
newAction = self.addAction(actionIcon, title, slot)
else:
newAction = self.addAction(actionIcon, title)
self.icons[title] = actionIcon
else:
newAction = QtGui.QAction(title, self)
self.addAction(newAction)
QtCore.QObject.connect(newAction,
QtCore.SIGNAL(u'triggered()'), slot)
if tooltip:
newAction.setToolTip(tooltip)
if checkable:
newAction.setCheckable(True)
QtCore.QObject.connect(newAction,
QtCore.SIGNAL(u'toggled(bool)'), slot)
self.actions[title] = newAction
if shortcuts is not None:
newAction.setShortcuts(shortcuts)
newAction.setShortcutContext(context)
return newAction
def addToolbarSeparator(self, handle): def addToolbarWidget(self, widget):
""" """
Add a Separator bar to the toolbar and store it's Handle Add a widget and store it's handle under the widgets object name.
"""
action = self.addSeparator()
self.actions[handle] = action
def addToolbarWidget(self, handle, widget):
"""
Add a Widget to the toolbar and store it's Handle
""" """
action = self.addWidget(widget) action = self.addWidget(widget)
self.actions[handle] = action self.actions[unicode(widget.objectName())] = action
def getIconFromTitle(self, title): def setWidgetVisible(self, widgets, visible=True):
""" """
Search through the list of icons for an icon with a particular title, Set the visibitity for a widget or a list of widgets.
and return that icon.
``title`` ``widget``
The title of the icon to search for. A list of string with widget object names.
"""
title = QtCore.QString(title)
try:
if self.icons[title]:
return self.icons[title]
except KeyError:
log.exception(u'getIconFromTitle - no icon for %s' % title)
return QtGui.QIcon()
def makeWidgetsInvisible(self, widgets): ``visible``
The new state as bool.
""" """
Hide a set of widgets. for handle in widgets:
if handle in self.actions:
self.actions[handle].setVisible(visible)
else:
log.warn(u'No handle "%s" in actions list.', unicode(handle))
``widgets``
The list of names of widgets to be hidden.
"""
for widget in widgets:
self.actions[widget].setVisible(False)
def makeWidgetsVisible(self, widgets):
"""
Show a set of widgets.
``widgets``
The list of names of widgets to be shown.
"""
for widget in widgets:
self.actions[widget].setVisible(True)
def addPushButton(self, image_file=None, text=u''):
"""
Adds a push button to the toolbar.
Returns the push button
"""
push_button = QtGui.QPushButton(build_icon(image_file), text)
push_button.setCheckable(True)
push_button.setFlat(True)
self.addWidget(push_button)
return push_button

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -93,6 +93,7 @@ class UiStrings(object):
self.New = translate('OpenLP.Ui', 'New') self.New = translate('OpenLP.Ui', 'New')
self.NewService = translate('OpenLP.Ui', 'New Service') self.NewService = translate('OpenLP.Ui', 'New Service')
self.NewTheme = translate('OpenLP.Ui', 'New Theme') self.NewTheme = translate('OpenLP.Ui', 'New Theme')
self.NextTrack = translate('OpenLP.Ui', 'Next Track')
self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular') self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural') self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular') self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
@ -114,6 +115,8 @@ class UiStrings(object):
'The abbreviated unit for seconds') 'The abbreviated unit for seconds')
self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview') self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
self.Search = translate('OpenLP.Ui', 'Search') self.Search = translate('OpenLP.Ui', 'Search')
self.SearchThemes = translate(
'OpenLP.Ui', 'Search Themes...', 'Search bar place holder text ')
self.SelectDelete = translate('OpenLP.Ui', 'You must select an item ' self.SelectDelete = translate('OpenLP.Ui', 'You must select an item '
'to delete.') 'to delete.')
self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to ' self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to '
@ -280,100 +283,102 @@ def create_up_down_push_button_set(parent):
QtCore.SIGNAL(u'clicked()'), parent.onDownButtonClicked) QtCore.SIGNAL(u'clicked()'), parent.onDownButtonClicked)
return up_button, down_button return up_button, down_button
def base_action(parent, name, category=None): def create_action(parent, name, **kwargs):
""" """
Return the most basic action with the object name set. Return an action with the object name set and the given parameters.
``category`` ``parent``
The category the action should be listed in the shortcut dialog. If you A QtCore.QObject for the actions parent (required).
not wish, that this action is added to the shortcut dialog, then do not
state any.
"""
action = QtGui.QAction(parent)
action.setObjectName(name)
if category is not None:
action_list = ActionList.get_instance()
action_list.add_action(action, category)
return action
def checkable_action(parent, name, checked=None, category=None): ``name``
""" A string which is set as object name (required).
Return a standard action with the checkable attribute set.
"""
action = base_action(parent, name, category)
action.setCheckable(True)
if checked is not None:
action.setChecked(checked)
return action
def icon_action(parent, name, icon, checked=None, category=None):
"""
Return a standard action with an icon.
"""
if checked is not None:
action = checkable_action(parent, name, checked, category)
else:
action = base_action(parent, name, category)
action.setIcon(build_icon(icon))
return action
def shortcut_action(parent, name, shortcuts, function, icon=None, checked=None,
category=None, context=QtCore.Qt.WindowShortcut):
"""
Return a shortcut enabled action.
"""
action = QtGui.QAction(parent)
action.setObjectName(name)
if icon is not None:
action.setIcon(build_icon(icon))
if checked is not None:
action.setCheckable(True)
action.setChecked(checked)
if shortcuts:
action.setShortcuts(shortcuts)
action.setShortcutContext(context)
action_list = ActionList.get_instance()
action_list.add_action(action, category)
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), function)
return action
def context_menu_action(base, icon, text, slot, shortcuts=None, category=None,
context=QtCore.Qt.WidgetShortcut):
"""
Utility method to help build context menus.
``base``
The parent menu to add this menu item to
``icon``
An icon for this action
``text`` ``text``
The text to display for this action A string for the action text.
``slot`` ``icon``
The code to run when this action is triggered Either a QIcon, a resource string, or a file location string for the
action icon.
``tooltip``
A string for the action tool tip.
``statustip``
A string for the action status tip.
``checked``
A bool for the state. If ``None`` the Action is not checkable.
``enabled``
False in case the action should be disabled.
``visible``
False in case the action should be hidden.
``separator``
True in case the action will be considered a separator.
``data``
Data which is set as QVariant type.
``shortcuts`` ``shortcuts``
The action's shortcuts. A QList<QKeySequence> (or a list of strings) which are set as shortcuts.
``category``
The category the shortcut should be listed in the shortcut dialog. If
left to ``None``, then the action will be hidden in the shortcut dialog.
``context`` ``context``
The context the shortcut is valid. A context for the shortcut execution.
``category``
A category the action should be listed in the shortcut dialog.
``triggers``
A slot which is connected to the actions ``triggered()`` slot.
""" """
action = QtGui.QAction(text, base) action = QtGui.QAction(parent)
if icon: action.setObjectName(name)
action.setIcon(build_icon(icon)) if kwargs.get(u'text'):
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), slot) action.setText(kwargs.pop(u'text'))
if shortcuts is not None: if kwargs.get(u'icon'):
action.setShortcuts(shortcuts) action.setIcon(build_icon(kwargs.pop(u'icon')))
action.setShortcutContext(context) if kwargs.get(u'tooltip'):
action.setToolTip(kwargs.pop(u'tooltip'))
if kwargs.get(u'statustip'):
action.setStatusTip(kwargs.pop(u'statustip'))
if kwargs.get(u'checked') is not None:
action.setCheckable(True)
action.setChecked(kwargs.pop(u'checked'))
if not kwargs.pop(u'enabled', True):
action.setEnabled(False)
if not kwargs.pop(u'visible', True):
action.setVisible(False)
if kwargs.pop(u'separator', False):
action.setSeparator(True)
if u'data' in kwargs:
action.setData(QtCore.QVariant(kwargs.pop(u'data')))
if kwargs.get(u'shortcuts'):
action.setShortcuts(kwargs.pop(u'shortcuts'))
if u'context' in kwargs:
action.setShortcutContext(kwargs.pop(u'context'))
if kwargs.get(u'category'):
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(action) action_list.add_action(action, unicode(kwargs.pop(u'category')))
base.addAction(action) if kwargs.get(u'triggers'):
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'),
kwargs.pop(u'triggers'))
for key in kwargs.keys():
if key not in [u'text', u'icon', u'tooltip', u'statustip', u'checked',
u'shortcuts', u'category', u'triggers']:
log.warn(u'Parameter %s was not consumed in create_action().', key)
return action
def create_widget_action(parent, name=u'', **kwargs):
"""
Return a new QAction by calling ``create_action(parent, name, **kwargs)``.
The shortcut context defaults to ``QtCore.Qt.WidgetShortcut`` and the action
is added to the parents action list.
"""
kwargs.setdefault(u'context', QtCore.Qt.WidgetShortcut)
action = create_action(parent, name, **kwargs)
parent.addAction(action)
return action return action
def context_menu(base, icon, text): def context_menu(base, icon, text):
@ -393,18 +398,6 @@ def context_menu(base, icon, text):
action.setIcon(build_icon(icon)) action.setIcon(build_icon(icon))
return action return action
def context_menu_separator(base):
"""
Add a separator to a context menu
``base``
The menu object to add the separator to
"""
action = QtGui.QAction(u'', base)
action.setSeparator(True)
base.addAction(action)
return action
def add_widget_completer(cache, widget): def add_widget_completer(cache, widget):
""" """
Adds a text autocompleter to a widget. Adds a text autocompleter to a widget.

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -126,7 +126,8 @@ class Ui_AboutDialog(object):
u'Tim "TRB143" Bentley (Fedora and Android)', u'Tim "TRB143" Bentley (Fedora and Android)',
u'Matthias "matthub" Hub (Mac OS X)', u'Matthias "matthub" Hub (Mac OS X)',
u'Stevan "ElderP" Pettit (Windows)', u'Stevan "ElderP" Pettit (Windows)',
u'Raoul "superfly" Snyman (Ubuntu)'] u'Raoul "superfly" Snyman (Ubuntu)',
u'Garrett "floft" Wilson (Arch Linux)']
translators = { translators = {
u'af': [u'Johan "nuvolari" Mynhardt'], u'af': [u'Johan "nuvolari" Mynhardt'],
u'de': [u'Patrick "madmuffin" Br\xfcckner', u'de': [u'Patrick "madmuffin" Br\xfcckner',
@ -226,8 +227,8 @@ class Ui_AboutDialog(object):
self.aboutNotebook.indexOf(self.creditsTab), self.aboutNotebook.indexOf(self.creditsTab),
translate('OpenLP.AboutForm', 'Credits')) translate('OpenLP.AboutForm', 'Credits'))
copyright = unicode(translate('OpenLP.AboutForm', copyright = unicode(translate('OpenLP.AboutForm',
'Copyright \xa9 2004-2011 %s\n' 'Copyright \xa9 2004-2012 %s\n'
'Portions copyright \xa9 2004-2011 %s')) % (u'Raoul Snyman', 'Portions copyright \xa9 2004-2012 %s')) % (u'Raoul Snyman',
u'Tim Bentley, Jonathan Corwin, Michael Gorven, Gerald Britton, ' u'Tim Bentley, Jonathan Corwin, Michael Gorven, Gerald Britton, '
u'Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin K\xf6hler, ' u'Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin K\xf6hler, '
u'Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias ' u'Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias '

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -27,10 +27,13 @@
""" """
The :mod:`advancedtab` provides an advanced settings facility. The :mod:`advancedtab` provides an advanced settings facility.
""" """
from datetime import datetime, timedelta
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate, build_icon from openlp.core.lib import SettingsTab, translate, build_icon, Receiver
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.lib import SlideLimits
from openlp.core.utils import get_images_filter from openlp.core.utils import get_images_filter
class AdvancedTab(SettingsTab): class AdvancedTab(SettingsTab):
@ -42,11 +45,23 @@ class AdvancedTab(SettingsTab):
""" """
Initialise the settings tab Initialise the settings tab
""" """
advancedTranslated = translate('OpenLP.AdvancedTab', 'Advanced') self.displayChanged = False
self.default_image = u':/graphics/openlp-splash-screen.png' # 7 stands for now, 0 to 6 is Monday to Sunday.
self.default_color = u'#ffffff' self.defaultServiceDay = 7
# 11 o'clock is the most popular time for morning service.
self.defaultServiceHour = 11
self.defaultServiceMinute = 0
self.defaultServiceName = unicode(translate('OpenLP.AdvancedTab',
'Service %Y-%m-%d %H-%M',
'This may not contain any of the following characters: '
'/\\?*|<>\[\]":+\n'
'See http://docs.python.org/library/datetime.html'
'#strftime-strptime-behavior for more information.'))
self.defaultImage = u':/graphics/openlp-splash-screen.png'
self.defaultColor = u'#ffffff'
self.icon_path = u':/system/system_settings.png' self.icon_path = u':/system/system_settings.png'
SettingsTab.__init__(self, parent, u'Advanced', advancedTranslated) advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced')
SettingsTab.__init__(self, parent, u'Advanced', advanced_translated)
def setupUi(self): def setupUi(self):
""" """
@ -83,7 +98,61 @@ class AdvancedTab(SettingsTab):
u'enableAutoCloseCheckBox') u'enableAutoCloseCheckBox')
self.uiLayout.addRow(self.enableAutoCloseCheckBox) self.uiLayout.addRow(self.enableAutoCloseCheckBox)
self.leftLayout.addWidget(self.uiGroupBox) self.leftLayout.addWidget(self.uiGroupBox)
# Default service name
self.serviceNameGroupBox = QtGui.QGroupBox(self.leftColumn)
self.serviceNameGroupBox.setObjectName(u'serviceNameGroupBox')
self.serviceNameLayout = QtGui.QFormLayout(
self.serviceNameGroupBox)
self.serviceNameCheckBox = QtGui.QCheckBox(
self.serviceNameGroupBox)
self.serviceNameCheckBox.setObjectName(u'serviceNameCheckBox')
self.serviceNameLayout.setObjectName(u'serviceNameLayout')
self.serviceNameLayout.addRow(self.serviceNameCheckBox)
self.serviceNameTimeLabel = QtGui.QLabel(self.serviceNameGroupBox)
self.serviceNameTimeLabel.setObjectName(u'serviceNameTimeLabel')
self.serviceNameDay = QtGui.QComboBox(
self.serviceNameGroupBox)
self.serviceNameDay.addItems(
[u'', u'', u'', u'', u'', u'', u'', u''])
self.serviceNameDay.setObjectName(
u'serviceNameDay')
self.serviceNameTime = QtGui.QTimeEdit(self.serviceNameGroupBox)
self.serviceNameTime.setObjectName(u'serviceNameTime')
self.serviceNameTimeHBox = QtGui.QHBoxLayout()
self.serviceNameTimeHBox.setObjectName(u'serviceNameTimeHBox')
self.serviceNameTimeHBox.addWidget(self.serviceNameDay)
self.serviceNameTimeHBox.addWidget(self.serviceNameTime)
self.serviceNameLayout.addRow(self.serviceNameTimeLabel,
self.serviceNameTimeHBox)
self.serviceNameLabel = QtGui.QLabel(self.serviceNameGroupBox)
self.serviceNameLabel.setObjectName(u'serviceNameLabel')
self.serviceNameEdit = QtGui.QLineEdit(self.serviceNameGroupBox)
self.serviceNameEdit.setObjectName(u'serviceNameEdit')
self.serviceNameEdit.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self))
self.serviceNameRevertButton = QtGui.QToolButton(
self.serviceNameGroupBox)
self.serviceNameRevertButton.setObjectName(
u'serviceNameRevertButton')
self.serviceNameRevertButton.setIcon(
build_icon(u':/general/general_revert.png'))
self.serviceNameHBox = QtGui.QHBoxLayout()
self.serviceNameHBox.setObjectName(u'serviceNameHBox')
self.serviceNameHBox.addWidget(self.serviceNameEdit)
self.serviceNameHBox.addWidget(self.serviceNameRevertButton)
self.serviceNameLayout.addRow(self.serviceNameLabel,
self.serviceNameHBox)
self.serviceNameExampleLabel = QtGui.QLabel(
self.serviceNameGroupBox)
self.serviceNameExampleLabel.setObjectName(
u'serviceNameExampleLabel')
self.serviceNameExample = QtGui.QLabel(self.serviceNameGroupBox)
self.serviceNameExample.setObjectName(u'serviceNameExample')
self.serviceNameLayout.addRow(self.serviceNameExampleLabel,
self.serviceNameExample)
self.leftLayout.addWidget(self.serviceNameGroupBox)
self.leftLayout.addStretch() self.leftLayout.addStretch()
# Default Image
self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn)
self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox') self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox')
self.defaultImageLayout = QtGui.QFormLayout(self.defaultImageGroupBox) self.defaultImageLayout = QtGui.QFormLayout(self.defaultImageGroupBox)
@ -114,7 +183,8 @@ class AdvancedTab(SettingsTab):
self.defaultImageLayout.addRow(self.defaultFileLabel, self.defaultImageLayout.addRow(self.defaultFileLabel,
self.defaultFileLayout) self.defaultFileLayout)
self.rightLayout.addWidget(self.defaultImageGroupBox) self.rightLayout.addWidget(self.defaultImageGroupBox)
self.hideMouseGroupBox = QtGui.QGroupBox(self.leftColumn) # Hide mouse
self.hideMouseGroupBox = QtGui.QGroupBox(self.rightColumn)
self.hideMouseGroupBox.setObjectName(u'hideMouseGroupBox') self.hideMouseGroupBox.setObjectName(u'hideMouseGroupBox')
self.hideMouseLayout = QtGui.QVBoxLayout(self.hideMouseGroupBox) self.hideMouseLayout = QtGui.QVBoxLayout(self.hideMouseGroupBox)
self.hideMouseLayout.setObjectName(u'hideMouseLayout') self.hideMouseLayout.setObjectName(u'hideMouseLayout')
@ -122,14 +192,76 @@ class AdvancedTab(SettingsTab):
self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox') self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox')
self.hideMouseLayout.addWidget(self.hideMouseCheckBox) self.hideMouseLayout.addWidget(self.hideMouseCheckBox)
self.rightLayout.addWidget(self.hideMouseGroupBox) self.rightLayout.addWidget(self.hideMouseGroupBox)
# Service Item Slide Limits
self.slideGroupBox = QtGui.QGroupBox(self.rightColumn)
self.slideGroupBox.setObjectName(u'slideGroupBox')
self.slideLayout = QtGui.QFormLayout(self.slideGroupBox)
self.slideLayout.setLabelAlignment(
QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.slideLayout.setFormAlignment(
QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.slideLayout.setObjectName(u'slideLayout')
self.endSlideRadioButton = QtGui.QRadioButton(self.slideGroupBox)
self.endSlideRadioButton.setObjectName(u'endSlideRadioButton')
self.endSlideLabel = QtGui.QLabel(self.slideGroupBox)
self.endSlideLabel.setWordWrap(True)
self.endSlideLabel.setObjectName(u'endSlideLabel')
self.slideLayout.addRow(self.endSlideRadioButton, self.endSlideLabel)
self.wrapSlideRadioButton = QtGui.QRadioButton(self.slideGroupBox)
self.wrapSlideRadioButton.setObjectName(u'wrapSlideRadioButton')
self.wrapSlideLabel = QtGui.QLabel(self.slideGroupBox)
self.wrapSlideLabel.setWordWrap(True)
self.wrapSlideLabel.setObjectName(u'wrapSlideLabel')
self.slideLayout.addRow(self.wrapSlideRadioButton,
self.wrapSlideLabel)
self.nextItemRadioButton = QtGui.QRadioButton(self.slideGroupBox)
self.nextItemRadioButton.setChecked(True)
self.nextItemRadioButton.setObjectName(u'nextItemRadioButton')
self.nextItemLabel = QtGui.QLabel(self.slideGroupBox)
self.nextItemLabel.setWordWrap(True)
self.nextItemLabel.setObjectName(u'nextItemLabel')
self.slideLayout.addRow(self.nextItemRadioButton,
self.nextItemLabel)
self.rightLayout.addWidget(self.slideGroupBox)
self.x11GroupBox = QtGui.QGroupBox(self.leftColumn)
self.x11GroupBox.setObjectName(u'x11GroupBox')
self.x11Layout = QtGui.QVBoxLayout(self.x11GroupBox)
self.x11Layout.setObjectName(u'x11Layout')
self.x11BypassCheckBox = QtGui.QCheckBox(self.x11GroupBox)
self.x11BypassCheckBox.setObjectName(u'x11BypassCheckBox')
self.x11Layout.addWidget(self.x11BypassCheckBox)
self.rightLayout.addWidget(self.x11GroupBox)
self.rightLayout.addStretch() self.rightLayout.addStretch()
self.shouldUpdateServiceNameExample = False
QtCore.QObject.connect(self.serviceNameCheckBox,
QtCore.SIGNAL(u'toggled(bool)'), self.serviceNameCheckBoxToggled)
QtCore.QObject.connect(self.serviceNameDay,
QtCore.SIGNAL(u'currentIndexChanged(int)'),
self.onServiceNameDayChanged)
QtCore.QObject.connect(self.serviceNameTime,
QtCore.SIGNAL(u'timeChanged(QTime)'),
self.updateServiceNameExample)
QtCore.QObject.connect(self.serviceNameEdit,
QtCore.SIGNAL(u'textChanged(QString)'),
self.updateServiceNameExample)
QtCore.QObject.connect(self.serviceNameRevertButton,
QtCore.SIGNAL(u'pressed()'),
self.onServiceNameRevertButtonPressed)
QtCore.QObject.connect(self.defaultColorButton, QtCore.QObject.connect(self.defaultColorButton,
QtCore.SIGNAL(u'pressed()'), self.onDefaultColorButtonPressed) QtCore.SIGNAL(u'pressed()'), self.onDefaultColorButtonPressed)
QtCore.QObject.connect(self.defaultBrowseButton, QtCore.QObject.connect(self.defaultBrowseButton,
QtCore.SIGNAL(u'pressed()'), self.onDefaultBrowseButtonPressed) QtCore.SIGNAL(u'pressed()'), self.onDefaultBrowseButtonPressed)
QtCore.QObject.connect(self.defaultRevertButton, QtCore.QObject.connect(self.defaultRevertButton,
QtCore.SIGNAL(u'pressed()'), self.onDefaultRevertButtonPressed) QtCore.SIGNAL(u'pressed()'), self.onDefaultRevertButtonPressed)
QtCore.QObject.connect(self.x11BypassCheckBox,
QtCore.SIGNAL(u'toggled(bool)'), self.onX11BypassCheckBoxToggled)
QtCore.QObject.connect(self.endSlideRadioButton,
QtCore.SIGNAL(u'pressed()'), self.onEndSlideButtonPressed)
QtCore.QObject.connect(self.wrapSlideRadioButton,
QtCore.SIGNAL(u'pressed()'), self.onWrapSlideButtonPressed)
QtCore.QObject.connect(self.nextItemRadioButton,
QtCore.SIGNAL(u'pressed()'), self.onnextItemButtonPressed)
def retranslateUi(self): def retranslateUi(self):
""" """
@ -151,6 +283,40 @@ class AdvancedTab(SettingsTab):
'Expand new service items on creation')) 'Expand new service items on creation'))
self.enableAutoCloseCheckBox.setText(translate('OpenLP.AdvancedTab', self.enableAutoCloseCheckBox.setText(translate('OpenLP.AdvancedTab',
'Enable application exit confirmation')) 'Enable application exit confirmation'))
self.serviceNameGroupBox.setTitle(
translate('OpenLP.AdvancedTab', 'Default Service Name'))
self.serviceNameCheckBox.setText(
translate('OpenLP.AdvancedTab', 'Enable default service name'))
self.serviceNameTimeLabel.setText(
translate('OpenLP.AdvancedTab', 'Date and Time:'))
self.serviceNameDay.setItemText(0,
translate('OpenLP.AdvancedTab', 'Monday'))
self.serviceNameDay.setItemText(1,
translate('OpenLP.AdvancedTab', 'Tuesday'))
self.serviceNameDay.setItemText(2,
translate('OpenLP.AdvancedTab', 'Wednesday'))
self.serviceNameDay.setItemText(3,
translate('OpenLP.AdvancedTab', 'Thurdsday'))
self.serviceNameDay.setItemText(4,
translate('OpenLP.AdvancedTab', 'Friday'))
self.serviceNameDay.setItemText(5,
translate('OpenLP.AdvancedTab', 'Saturday'))
self.serviceNameDay.setItemText(6,
translate('OpenLP.AdvancedTab', 'Sunday'))
self.serviceNameDay.setItemText(7,
translate('OpenLP.AdvancedTab', 'Now'))
self.serviceNameTime.setToolTip(translate('OpenLP.AdvancedTab',
'Time when usual service starts.'))
self.serviceNameLabel.setText(
translate('OpenLP.AdvancedTab', 'Name:'))
self.serviceNameEdit.setToolTip(translate('OpenLP.AdvancedTab',
'Consult the OpenLP manual for usage.'))
self.serviceNameRevertButton.setToolTip(unicode(
translate('OpenLP.AdvancedTab',
'Revert to the default service name "%s".')) %
self.defaultServiceName)
self.serviceNameExampleLabel.setText(translate('OpenLP.AdvancedTab',
'Example:'))
self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab', self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab',
'Mouse Cursor')) 'Mouse Cursor'))
self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab', self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab',
@ -167,6 +333,29 @@ class AdvancedTab(SettingsTab):
'Browse for an image file to display.')) 'Browse for an image file to display.'))
self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab', self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab',
'Revert to the default OpenLP logo.')) 'Revert to the default OpenLP logo.'))
self.x11GroupBox.setTitle(translate('OpenLP.AdvancedTab',
'X11'))
self.x11BypassCheckBox.setText(translate('OpenLP.AdvancedTab',
'Bypass X11 Window Manager'))
# Slide Limits
self.slideGroupBox.setTitle(
translate('OpenLP.GeneralTab', 'Service Item Slide Limits'))
self.endSlideRadioButton.setText(
translate('OpenLP.GeneralTab', '&End Slide'))
self.endSlideLabel.setText(
translate('OpenLP.GeneralTab', 'Up and down arrow keys '
'stop at the top and bottom slides of each Service Item.'))
self.wrapSlideRadioButton.setText(
translate('OpenLP.GeneralTab', '&Wrap Slide'))
self.wrapSlideLabel.setText(
translate('OpenLP.GeneralTab', 'Up and down arrow keys '
'wrap around at the top and bottom slides of each Service Item.'))
self.nextItemRadioButton.setText(
translate('OpenLP.GeneralTab', '&Next Item'))
self.nextItemLabel.setText(
translate('OpenLP.GeneralTab', 'Up and down arrow keys '
'advance to the next or previous Service Item from the '
'top and bottom slides of each Service Item.'))
def load(self): def load(self):
""" """
@ -198,14 +387,39 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(True)).toBool()) QtCore.QVariant(True)).toBool())
self.hideMouseCheckBox.setChecked( self.hideMouseCheckBox.setChecked(
settings.value(u'hide mouse', QtCore.QVariant(False)).toBool()) settings.value(u'hide mouse', QtCore.QVariant(False)).toBool())
self.default_color = settings.value(u'default color', self.serviceNameDay.setCurrentIndex(
settings.value(u'default service day',
QtCore.QVariant(self.defaultServiceDay)).toInt()[0])
self.serviceNameTime.setTime(QtCore.QTime(
settings.value(u'default service hour',
self.defaultServiceHour).toInt()[0],
settings.value(u'default service minute',
self.defaultServiceMinute).toInt()[0]))
self.shouldUpdateServiceNameExample = True
self.serviceNameEdit.setText(settings.value(u'default service name',
self.defaultServiceName).toString())
default_service_enabled = settings.value(u'default service enabled',
QtCore.QVariant(True)).toBool()
self.serviceNameCheckBox.setChecked(default_service_enabled)
self.serviceNameCheckBoxToggled(default_service_enabled)
self.x11BypassCheckBox.setChecked(
settings.value(u'x11 bypass wm', QtCore.QVariant(True)).toBool())
self.defaultColor = settings.value(u'default color',
QtCore.QVariant(u'#ffffff')).toString() QtCore.QVariant(u'#ffffff')).toString()
self.defaultFileEdit.setText(settings.value(u'default image', self.defaultFileEdit.setText(settings.value(u'default image',
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\ QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
.toString()) .toString())
self.slide_limits = settings.value(
u'slide limits', QtCore.QVariant(SlideLimits.End)).toInt()[0]
if self.slide_limits == SlideLimits.End:
self.endSlideRadioButton.setChecked(True)
elif self.slide_limits == SlideLimits.Wrap:
self.wrapSlideRadioButton.setChecked(True)
else:
self.nextItemRadioButton.setChecked(True)
settings.endGroup() settings.endGroup()
self.defaultColorButton.setStyleSheet( self.defaultColorButton.setStyleSheet(
u'background-color: %s' % self.default_color) u'background-color: %s' % self.defaultColor)
def save(self): def save(self):
""" """
@ -213,6 +427,21 @@ class AdvancedTab(SettingsTab):
""" """
settings = QtCore.QSettings() settings = QtCore.QSettings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
settings.setValue(u'default service enabled',
self.serviceNameCheckBox.isChecked())
service_name = unicode(self.serviceNameEdit.text())
preset_is_valid = self.generateServiceNameExample()[0]
if service_name == self.defaultServiceName or not preset_is_valid:
settings.remove(u'default service name')
self.serviceNameEdit.setText(service_name)
else:
settings.setValue(u'default service name', service_name)
settings.setValue(u'default service day',
self.serviceNameDay.currentIndex())
settings.setValue(u'default service hour',
self.serviceNameTime.time().hour())
settings.setValue(u'default service minute',
self.serviceNameTime.time().minute())
settings.setValue(u'recent file count', settings.setValue(u'recent file count',
QtCore.QVariant(self.recentSpinBox.value())) QtCore.QVariant(self.recentSpinBox.value()))
settings.setValue(u'save current plugin', settings.setValue(u'save current plugin',
@ -227,17 +456,67 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked())) QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked()))
settings.setValue(u'hide mouse', settings.setValue(u'hide mouse',
QtCore.QVariant(self.hideMouseCheckBox.isChecked())) QtCore.QVariant(self.hideMouseCheckBox.isChecked()))
settings.setValue(u'default color', self.default_color) settings.setValue(u'x11 bypass wm',
QtCore.QVariant(self.x11BypassCheckBox.isChecked()))
settings.setValue(u'default color', self.defaultColor)
settings.setValue(u'default image', self.defaultFileEdit.text()) settings.setValue(u'default image', self.defaultFileEdit.text())
settings.setValue(u'slide limits', QtCore.QVariant(self.slide_limits))
settings.endGroup() settings.endGroup()
if self.displayChanged:
Receiver.send_message(u'config_screen_changed')
self.displayChanged = False
Receiver.send_message(u'slidecontroller_update_slide_limits')
def serviceNameCheckBoxToggled(self, default_service_enabled):
self.serviceNameDay.setEnabled(default_service_enabled)
time_enabled = default_service_enabled and \
self.serviceNameDay.currentIndex() is not 7
self.serviceNameTime.setEnabled(time_enabled)
self.serviceNameEdit.setEnabled(default_service_enabled)
self.serviceNameRevertButton.setEnabled(default_service_enabled)
def generateServiceNameExample(self):
preset_is_valid = True
if self.serviceNameDay.currentIndex() == 7:
time = datetime.now()
else:
now = datetime.now()
day_delta = self.serviceNameDay.currentIndex() - now.weekday()
if day_delta < 0:
day_delta += 7
time = now + timedelta(days=day_delta)
time = time.replace(hour = self.serviceNameTime.time().hour(),
minute = self.serviceNameTime.time().minute())
try:
service_name_example = time.strftime(unicode(
self.serviceNameEdit.text()))
except ValueError:
preset_is_valid = False
service_name_example = translate('OpenLP.AdvancedTab',
'Syntax error.')
return preset_is_valid, service_name_example
def updateServiceNameExample(self, returned_value):
if not self.shouldUpdateServiceNameExample:
return
name_example = self.generateServiceNameExample()[1]
self.serviceNameExample.setText(name_example)
def onServiceNameDayChanged(self, service_day):
self.serviceNameTime.setEnabled(service_day is not 7)
self.updateServiceNameExample(None)
def onServiceNameRevertButtonPressed(self):
self.serviceNameEdit.setText(self.defaultServiceName)
self.serviceNameEdit.setFocus()
def onDefaultColorButtonPressed(self): def onDefaultColorButtonPressed(self):
new_color = QtGui.QColorDialog.getColor( new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.default_color), self) QtGui.QColor(self.defaultColor), self)
if new_color.isValid(): if new_color.isValid():
self.default_color = new_color.name() self.defaultColor = new_color.name()
self.defaultColorButton.setStyleSheet( self.defaultColorButton.setStyleSheet(
u'background-color: %s' % self.default_color) u'background-color: %s' % self.defaultColor)
def onDefaultBrowseButtonPressed(self): def onDefaultBrowseButtonPressed(self):
file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(), file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(),
@ -252,3 +531,21 @@ class AdvancedTab(SettingsTab):
def onDefaultRevertButtonPressed(self): def onDefaultRevertButtonPressed(self):
self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png') self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png')
self.defaultFileEdit.setFocus() self.defaultFileEdit.setFocus()
def onX11BypassCheckBoxToggled(self, checked):
"""
Toggle X11 bypass flag on maindisplay depending on check box state.
``checked``
The state of the check box (boolean).
"""
self.displayChanged = True
def onEndSlideButtonPressed(self):
self.slide_limits = SlideLimits.End
def onWrapSlideButtonPressed(self):
self.slide_limits = SlideLimits.Wrap
def onnextItemButtonPressed(self):
self.slide_limits = SlideLimits.Next

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -32,7 +32,7 @@ import platform
import sqlalchemy import sqlalchemy
import BeautifulSoup import BeautifulSoup
from lxml import etree from lxml import etree
from PyQt4 import Qt, QtCore, QtGui from PyQt4 import Qt, QtCore, QtGui, QtWebKit
try: try:
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
@ -77,6 +77,11 @@ try:
UNO_VERSION = node.getByName(u'ooSetupVersion') UNO_VERSION = node.getByName(u'ooSetupVersion')
except ImportError: except ImportError:
UNO_VERSION = u'-' UNO_VERSION = u'-'
try:
WEBKIT_VERSION = QtWebKit.qWebKitVersion()
except AttributeError:
WEBKIT_VERSION = u'-'
from openlp.core.lib import translate, SettingsManager from openlp.core.lib import translate, SettingsManager
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
@ -111,6 +116,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
u'Qt4: %s\n' % Qt.qVersion() + \ u'Qt4: %s\n' % Qt.qVersion() + \
u'Phonon: %s\n' % PHONON_VERSION + \ u'Phonon: %s\n' % PHONON_VERSION + \
u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \ u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \
u'QtWebkit: %s\n' % WEBKIT_VERSION + \
u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \ u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \
u'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \ u'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \
u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \ u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \
@ -144,7 +150,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
translate('OpenLP.ExceptionForm', translate('OpenLP.ExceptionForm',
'Text files (*.txt *.log *.text)')) 'Text files (*.txt *.log *.text)'))
if filename: if filename:
filename = unicode(QtCore.QDir.toNativeSeparators(filename)) filename = unicode(filename).replace(u'/', os.path.sep)
SettingsManager.set_last_dir(self.settingsSection, os.path.dirname( SettingsManager.set_last_dir(self.settingsSection, os.path.dirname(
filename)) filename))
report_text = report_text % self._createReport() report_text = report_text % self._createReport()

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -41,7 +41,7 @@ class Ui_FileRenameDialog(object):
self.dialogLayout.addWidget(self.fileNameLabel, 0, 0) self.dialogLayout.addWidget(self.fileNameLabel, 0, 0)
self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog) self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog)
self.fileNameEdit.setValidator(QtGui.QRegExpValidator( self.fileNameEdit.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp(r'[^/\\?*|<>\[\]":<>+%]+'), self)) QtCore.QRegExp(r'[^/\\?*|<>\[\]":+%]+'), self))
self.fileNameEdit.setObjectName(u'fileNameEdit') self.fileNameEdit.setObjectName(u'fileNameEdit')
self.dialogLayout.addWidget(self.fileNameEdit, 0, 1) self.dialogLayout.addWidget(self.fileNameEdit, 0, 1)
self.buttonBox = create_accept_reject_button_box(fileRenameDialog, True) self.buttonBox = create_accept_reject_button_box(fileRenameDialog, True)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -29,6 +29,7 @@ import io
import logging import logging
import os import os
import sys import sys
import time
import urllib import urllib
import urllib2 import urllib2
from tempfile import gettempdir from tempfile import gettempdir
@ -43,6 +44,29 @@ from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class ThemeScreenshotThread(QtCore.QThread):
"""
This thread downloads the theme screenshots.
"""
def __init__(self, parent):
QtCore.QThread.__init__(self, parent)
def run(self):
themes = self.parent().config.get(u'themes', u'files')
themes = themes.split(u',')
config = self.parent().config
for theme in themes:
title = config.get(u'theme_%s' % theme, u'title')
filename = config.get(u'theme_%s' % theme, u'filename')
screenshot = config.get(u'theme_%s' % theme, u'screenshot')
urllib.urlretrieve(u'%s%s' % (self.parent().web, screenshot),
os.path.join(gettempdir(), u'openlp', screenshot))
item = QtGui.QListWidgetItem(title, self.parent().themesListWidget)
item.setData(QtCore.Qt.UserRole, QtCore.QVariant(filename))
item.setCheckState(QtCore.Qt.Unchecked)
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard): class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
""" """
This is the Theme Import Wizard, which allows easy creation and editing of This is the Theme Import Wizard, which allows easy creation and editing of
@ -125,21 +149,9 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
item.setCheckState(0, QtCore.Qt.Unchecked) item.setCheckState(0, QtCore.Qt.Unchecked)
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable) item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
self.biblesTreeWidget.expandAll() self.biblesTreeWidget.expandAll()
themes = self.config.get(u'themes', u'files') # Download the theme screenshots.
themes = themes.split(u',') self.themeScreenshotThread = ThemeScreenshotThread(self)
for theme in themes: self.themeScreenshotThread.start()
title = self.config.get(u'theme_%s' % theme, u'title')
filename = self.config.get(u'theme_%s' % theme, u'filename')
screenshot = self.config.get(u'theme_%s' % theme, u'screenshot')
urllib.urlretrieve(u'%s%s' % (self.web, screenshot),
os.path.join(gettempdir(), u'openlp', screenshot))
item = QtGui.QListWidgetItem(title, self.themesListWidget)
item.setData(QtCore.Qt.UserRole,
QtCore.QVariant(filename))
item.setIcon(build_icon(
os.path.join(gettempdir(), u'openlp', screenshot)))
item.setCheckState(QtCore.Qt.Unchecked)
item.setFlags(item.flags() | QtCore.Qt.ItemIsUserCheckable)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
def nextId(self): def nextId(self):
@ -156,6 +168,14 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
return -1 return -1
elif self.currentId() == FirstTimePage.NoInternet: elif self.currentId() == FirstTimePage.NoInternet:
return FirstTimePage.Progress return FirstTimePage.Progress
elif self.currentId() == FirstTimePage.Themes:
Receiver.send_message(u'cursor_busy')
while not self.themeScreenshotThread.isFinished():
time.sleep(0.1)
# Build the screenshot icons, as this can not be done in the thread.
self._buildThemeScreenshots()
Receiver.send_message(u'cursor_normal')
return FirstTimePage.Defaults
else: else:
return self.currentId() + 1 return self.currentId() + 1
@ -264,6 +284,23 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
if self.downloadCanceled: if self.downloadCanceled:
os.remove(fpath) os.remove(fpath)
def _buildThemeScreenshots(self):
"""
This method builds the theme screenshots' icons for all items in the
``self.themesListWidget``.
"""
themes = self.config.get(u'themes', u'files')
themes = themes.split(u',')
for theme in themes:
filename = self.config.get(u'theme_%s' % theme, u'filename')
screenshot = self.config.get(u'theme_%s' % theme, u'screenshot')
for index in xrange(self.themesListWidget.count()):
item = self.themesListWidget.item(index)
if item.data(QtCore.Qt.UserRole) == QtCore.QVariant(filename):
break
item.setIcon(build_icon(
os.path.join(gettempdir(), u'openlp', screenshot)))
def _getFileSize(self, url): def _getFileSize(self, url):
site = urllib.urlopen(url) site = urllib.urlopen(url)
meta = site.info() meta = site.info()
@ -421,6 +458,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
if self.displayComboBox.currentIndex() != -1: if self.displayComboBox.currentIndex() != -1:
QtCore.QSettings().setValue(u'General/monitor', QtCore.QSettings().setValue(u'General/monitor',
QtCore.QVariant(self.displayComboBox.currentIndex())) QtCore.QVariant(self.displayComboBox.currentIndex()))
self.screens.set_current_display(
self.displayComboBox.currentIndex())
# Set Global Theme # Set Global Theme
if self.themeComboBox.currentIndex() != -1: if self.themeComboBox.currentIndex() != -1:
QtCore.QSettings().setValue(u'themes/global theme', QtCore.QSettings().setValue(u'themes/global theme',

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -27,6 +27,7 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib.ui import create_action
from openlp.core.utils import LanguageManager from openlp.core.utils import LanguageManager
from firsttimelanguagedialog import Ui_FirstTimeLanguageDialog from firsttimelanguagedialog import Ui_FirstTimeLanguageDialog
@ -55,8 +56,7 @@ class FirstTimeLanguageForm(QtGui.QDialog, Ui_FirstTimeLanguageDialog):
LanguageManager.set_language(False, False) LanguageManager.set_language(False, False)
else: else:
LanguageManager.auto_language = False LanguageManager.auto_language = False
action = QtGui.QAction(None) action = create_action(None, self.languageComboBox.currentText())
action.setObjectName(unicode(self.languageComboBox.currentText()))
LanguageManager.set_language(action, False) LanguageManager.set_language(action, False)
return QtGui.QDialog.accept(self) return QtGui.QDialog.accept(self)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -53,63 +53,64 @@ class GeneralTab(SettingsTab):
""" """
self.setObjectName(u'GeneralTab') self.setObjectName(u'GeneralTab')
SettingsTab.setupUi(self) SettingsTab.setupUi(self)
self.tabLayout.setStretch(1, 1)
# Monitors
self.monitorGroupBox = QtGui.QGroupBox(self.leftColumn) self.monitorGroupBox = QtGui.QGroupBox(self.leftColumn)
self.monitorGroupBox.setObjectName(u'monitorGroupBox') self.monitorGroupBox.setObjectName(u'monitorGroupBox')
self.monitorLayout = QtGui.QFormLayout(self.monitorGroupBox) self.monitorLayout = QtGui.QGridLayout(self.monitorGroupBox)
self.monitorLayout.setObjectName(u'monitorLayout') self.monitorLayout.setObjectName(u'monitorLayout')
self.monitorLabel = QtGui.QLabel(self.monitorGroupBox) self.monitorRadioButton = QtGui.QRadioButton(self.monitorGroupBox)
self.monitorLabel.setObjectName(u'monitorLabel') self.monitorRadioButton.setObjectName(u'monitorRadioButton')
self.monitorLayout.addRow(self.monitorLabel) self.monitorLayout.addWidget(self.monitorRadioButton, 0, 0, 1, 5)
self.monitorComboBox = QtGui.QComboBox(self.monitorGroupBox) self.monitorComboBox = QtGui.QComboBox(self.monitorGroupBox)
self.monitorComboBox.setObjectName(u'monitorComboBox') self.monitorComboBox.setObjectName(u'monitorComboBox')
self.monitorLayout.addRow(self.monitorComboBox) self.monitorLayout.addWidget(self.monitorComboBox, 1, 1, 1, 4)
self.displayOnMonitorCheck = QtGui.QCheckBox(self.monitorGroupBox) self.displayOnMonitorCheck = QtGui.QCheckBox(self.monitorGroupBox)
self.displayOnMonitorCheck.setObjectName(u'monitorComboBox') self.displayOnMonitorCheck.setObjectName(u'monitorComboBox')
self.monitorLayout.addRow(self.displayOnMonitorCheck) self.monitorLayout.addWidget(self.displayOnMonitorCheck, 2, 1, 1, 4)
# Display Position
self.overrideRadioButton = QtGui.QRadioButton(self.monitorGroupBox)
self.overrideRadioButton.setObjectName(u'overrideRadioButton')
self.monitorLayout.addWidget(self.overrideRadioButton, 3, 0, 1, 5)
# Custom position
self.customXLabel = QtGui.QLabel(self.monitorGroupBox)
self.customXLabel.setObjectName(u'customXLabel')
self.monitorLayout.addWidget(self.customXLabel, 4, 1)
self.customXValueEdit = QtGui.QSpinBox(self.monitorGroupBox)
self.customXValueEdit.setObjectName(u'customXValueEdit')
self.customXValueEdit.setRange(-9999, 9999)
self.monitorLayout.addWidget(self.customXValueEdit, 5, 1)
self.customYLabel = QtGui.QLabel(self.monitorGroupBox)
self.customYLabel.setObjectName(u'customYLabel')
self.monitorLayout.addWidget(self.customYLabel, 4, 2)
self.customYValueEdit = QtGui.QSpinBox(self.monitorGroupBox)
self.customYValueEdit.setObjectName(u'customYValueEdit')
self.customYValueEdit.setRange(-9999, 9999)
self.monitorLayout.addWidget(self.customYValueEdit, 5, 2)
self.customWidthLabel = QtGui.QLabel(self.monitorGroupBox)
self.customWidthLabel.setObjectName(u'customWidthLabel')
self.monitorLayout.addWidget(self.customWidthLabel, 4, 3)
self.customWidthValueEdit = QtGui.QSpinBox(self.monitorGroupBox)
self.customWidthValueEdit.setObjectName(u'customWidthValueEdit')
self.customWidthValueEdit.setMaximum(9999)
self.monitorLayout.addWidget(self.customWidthValueEdit, 5, 3)
self.customHeightLabel = QtGui.QLabel(self.monitorGroupBox)
self.customHeightLabel.setObjectName(u'customHeightLabel')
self.monitorLayout.addWidget(self.customHeightLabel, 4, 4)
self.customHeightValueEdit = QtGui.QSpinBox(self.monitorGroupBox)
self.customHeightValueEdit.setObjectName(u'customHeightValueEdit')
self.customHeightValueEdit.setMaximum(9999)
self.monitorLayout.addWidget(self.customHeightValueEdit, 5, 4)
# Set up the stretchiness of each column, so that the first column
# less stretchy (and therefore smaller) than the others
self.monitorLayout.setColumnStretch(0, 1)
self.monitorLayout.setColumnStretch(1, 3)
self.monitorLayout.setColumnStretch(2, 3)
self.monitorLayout.setColumnStretch(3, 3)
self.monitorLayout.setColumnStretch(4, 3)
self.leftLayout.addWidget(self.monitorGroupBox) self.leftLayout.addWidget(self.monitorGroupBox)
self.startupGroupBox = QtGui.QGroupBox(self.leftColumn) # CCLI Details
self.startupGroupBox.setObjectName(u'startupGroupBox') self.ccliGroupBox = QtGui.QGroupBox(self.leftColumn)
self.startupLayout = QtGui.QVBoxLayout(self.startupGroupBox)
self.startupLayout.setObjectName(u'startupLayout')
self.warningCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.warningCheckBox.setObjectName(u'warningCheckBox')
self.startupLayout.addWidget(self.warningCheckBox)
self.autoOpenCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.autoOpenCheckBox.setObjectName(u'autoOpenCheckBox')
self.startupLayout.addWidget(self.autoOpenCheckBox)
self.showSplashCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.showSplashCheckBox.setObjectName(u'showSplashCheckBox')
self.startupLayout.addWidget(self.showSplashCheckBox)
self.checkForUpdatesCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.checkForUpdatesCheckBox.setObjectName(u'checkForUpdatesCheckBox')
self.startupLayout.addWidget(self.checkForUpdatesCheckBox)
self.leftLayout.addWidget(self.startupGroupBox)
self.settingsGroupBox = QtGui.QGroupBox(self.leftColumn)
self.settingsGroupBox.setObjectName(u'settingsGroupBox')
self.settingsLayout = QtGui.QFormLayout(self.settingsGroupBox)
self.settingsLayout.setObjectName(u'settingsLayout')
self.saveCheckServiceCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.saveCheckServiceCheckBox.setObjectName(u'saveCheckServiceCheckBox')
self.settingsLayout.addRow(self.saveCheckServiceCheckBox)
self.autoUnblankCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.autoUnblankCheckBox.setObjectName(u'autoUnblankCheckBox')
self.settingsLayout.addRow(self.autoUnblankCheckBox)
self.autoPreviewCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.autoPreviewCheckBox.setObjectName(u'autoPreviewCheckBox')
self.settingsLayout.addRow(self.autoPreviewCheckBox)
self.enableLoopCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.enableLoopCheckBox.setObjectName(u'enableLoopCheckBox')
self.settingsLayout.addRow(self.enableLoopCheckBox)
# Moved here from image tab
self.timeoutLabel = QtGui.QLabel(self.settingsGroupBox)
self.timeoutLabel.setObjectName(u'timeoutLabel')
self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox)
self.timeoutSpinBox.setObjectName(u'timeoutSpinBox')
self.timeoutSpinBox.setRange(1, 180)
self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox)
self.leftLayout.addWidget(self.settingsGroupBox)
self.leftLayout.addStretch()
self.ccliGroupBox = QtGui.QGroupBox(self.rightColumn)
self.ccliGroupBox.setObjectName(u'ccliGroupBox') self.ccliGroupBox.setObjectName(u'ccliGroupBox')
self.ccliLayout = QtGui.QFormLayout(self.ccliGroupBox) self.ccliLayout = QtGui.QFormLayout(self.ccliGroupBox)
self.ccliLayout.setObjectName(u'ccliLayout') self.ccliLayout.setObjectName(u'ccliLayout')
@ -130,59 +131,64 @@ class GeneralTab(SettingsTab):
self.passwordEdit.setEchoMode(QtGui.QLineEdit.Password) self.passwordEdit.setEchoMode(QtGui.QLineEdit.Password)
self.passwordEdit.setObjectName(u'passwordEdit') self.passwordEdit.setObjectName(u'passwordEdit')
self.ccliLayout.addRow(self.passwordLabel, self.passwordEdit) self.ccliLayout.addRow(self.passwordLabel, self.passwordEdit)
self.rightLayout.addWidget(self.ccliGroupBox) self.leftLayout.addWidget(self.ccliGroupBox)
# Moved here from display tab
self.displayGroupBox = QtGui.QGroupBox(self.rightColumn)
self.displayGroupBox.setObjectName(u'displayGroupBox')
self.displayLayout = QtGui.QGridLayout(self.displayGroupBox)
self.displayLayout.setObjectName(u'displayLayout')
self.overrideCheckBox = QtGui.QCheckBox(self.displayGroupBox)
self.overrideCheckBox.setObjectName(u'overrideCheckBox')
self.displayLayout.addWidget(self.overrideCheckBox, 2, 0, 1, 4)
self.rightLayout.addWidget(self.displayGroupBox)
# Custom position
self.customXLabel = QtGui.QLabel(self.displayGroupBox)
self.customXLabel.setObjectName(u'customXLabel')
self.displayLayout.addWidget(self.customXLabel, 3, 0)
self.customXValueEdit = QtGui.QSpinBox(self.displayGroupBox)
self.customXValueEdit.setObjectName(u'customXValueEdit')
self.customXValueEdit.setRange(-9999, 9999)
self.displayLayout.addWidget(self.customXValueEdit, 4, 0)
self.customYLabel = QtGui.QLabel(self.displayGroupBox)
self.customYLabel.setObjectName(u'customYLabel')
self.displayLayout.addWidget(self.customYLabel, 3, 1)
self.customYValueEdit = QtGui.QSpinBox(self.displayGroupBox)
self.customYValueEdit.setObjectName(u'customYValueEdit')
self.customYValueEdit.setRange(-9999, 9999)
self.displayLayout.addWidget(self.customYValueEdit, 4, 1)
self.customWidthLabel = QtGui.QLabel(self.displayGroupBox)
self.customWidthLabel.setObjectName(u'customWidthLabel')
self.displayLayout.addWidget(self.customWidthLabel, 3, 2)
self.customWidthValueEdit = QtGui.QSpinBox(self.displayGroupBox)
self.customWidthValueEdit.setObjectName(u'customWidthValueEdit')
self.customWidthValueEdit.setMaximum(9999)
self.displayLayout.addWidget(self.customWidthValueEdit, 4, 2)
self.customHeightLabel = QtGui.QLabel(self.displayGroupBox)
self.customHeightLabel.setObjectName(u'customHeightLabel')
self.displayLayout.addWidget(self.customHeightLabel, 3, 3)
self.customHeightValueEdit = QtGui.QSpinBox(self.displayGroupBox)
self.customHeightValueEdit.setObjectName(u'customHeightValueEdit')
self.customHeightValueEdit.setMaximum(9999)
self.displayLayout.addWidget(self.customHeightValueEdit, 4, 3)
self.rightLayout.addWidget(self.displayGroupBox)
# Background audio # Background audio
self.audioGroupBox = QtGui.QGroupBox(self.rightColumn) self.audioGroupBox = QtGui.QGroupBox(self.leftColumn)
self.audioGroupBox.setObjectName(u'audioGroupBox') self.audioGroupBox.setObjectName(u'audioGroupBox')
self.audioLayout = QtGui.QVBoxLayout(self.audioGroupBox) self.audioLayout = QtGui.QVBoxLayout(self.audioGroupBox)
self.audioLayout.setObjectName(u'audioLayout') self.audioLayout.setObjectName(u'audioLayout')
self.startPausedCheckBox = QtGui.QCheckBox(self.audioGroupBox) self.startPausedCheckBox = QtGui.QCheckBox(self.audioGroupBox)
self.startPausedCheckBox.setObjectName(u'startPausedCheckBox') self.startPausedCheckBox.setObjectName(u'startPausedCheckBox')
self.audioLayout.addWidget(self.startPausedCheckBox) self.audioLayout.addWidget(self.startPausedCheckBox)
self.rightLayout.addWidget(self.audioGroupBox) self.repeatListCheckBox = QtGui.QCheckBox(self.audioGroupBox)
self.repeatListCheckBox.setObjectName(u'repeatListCheckBox')
self.audioLayout.addWidget(self.repeatListCheckBox)
self.leftLayout.addWidget(self.audioGroupBox)
self.leftLayout.addStretch()
# Application Startup
self.startupGroupBox = QtGui.QGroupBox(self.rightColumn)
self.startupGroupBox.setObjectName(u'startupGroupBox')
self.startupLayout = QtGui.QVBoxLayout(self.startupGroupBox)
self.startupLayout.setObjectName(u'startupLayout')
self.warningCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.warningCheckBox.setObjectName(u'warningCheckBox')
self.startupLayout.addWidget(self.warningCheckBox)
self.autoOpenCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.autoOpenCheckBox.setObjectName(u'autoOpenCheckBox')
self.startupLayout.addWidget(self.autoOpenCheckBox)
self.showSplashCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.showSplashCheckBox.setObjectName(u'showSplashCheckBox')
self.startupLayout.addWidget(self.showSplashCheckBox)
self.checkForUpdatesCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.checkForUpdatesCheckBox.setObjectName(u'checkForUpdatesCheckBox')
self.startupLayout.addWidget(self.checkForUpdatesCheckBox)
self.rightLayout.addWidget(self.startupGroupBox)
# Application Settings
self.settingsGroupBox = QtGui.QGroupBox(self.rightColumn)
self.settingsGroupBox.setObjectName(u'settingsGroupBox')
self.settingsLayout = QtGui.QFormLayout(self.settingsGroupBox)
self.settingsLayout.setObjectName(u'settingsLayout')
self.saveCheckServiceCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.saveCheckServiceCheckBox.setObjectName(u'saveCheckServiceCheckBox')
self.settingsLayout.addRow(self.saveCheckServiceCheckBox)
self.autoUnblankCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.autoUnblankCheckBox.setObjectName(u'autoUnblankCheckBox')
self.settingsLayout.addRow(self.autoUnblankCheckBox)
self.autoPreviewCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.autoPreviewCheckBox.setObjectName(u'autoPreviewCheckBox')
self.settingsLayout.addRow(self.autoPreviewCheckBox)
# Moved here from image tab
self.timeoutLabel = QtGui.QLabel(self.settingsGroupBox)
self.timeoutLabel.setObjectName(u'timeoutLabel')
self.timeoutSpinBox = QtGui.QSpinBox(self.settingsGroupBox)
self.timeoutSpinBox.setObjectName(u'timeoutSpinBox')
self.timeoutSpinBox.setRange(1, 180)
self.settingsLayout.addRow(self.timeoutLabel, self.timeoutSpinBox)
self.rightLayout.addWidget(self.settingsGroupBox)
self.rightLayout.addStretch() self.rightLayout.addStretch()
# Signals and slots # Signals and slots
QtCore.QObject.connect(self.overrideCheckBox, QtCore.QObject.connect(self.overrideRadioButton,
QtCore.SIGNAL(u'toggled(bool)'), self.onOverrideCheckBoxToggled) QtCore.SIGNAL(u'toggled(bool)'), self.onOverrideRadioButtonPressed)
QtCore.QObject.connect(self.customHeightValueEdit, QtCore.QObject.connect(self.customHeightValueEdit,
QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged) QtCore.SIGNAL(u'valueChanged(int)'), self.onDisplayChanged)
QtCore.QObject.connect(self.customWidthValueEdit, QtCore.QObject.connect(self.customWidthValueEdit,
@ -209,7 +215,7 @@ class GeneralTab(SettingsTab):
self.tabTitleVisible = translate('OpenLP.GeneralTab', 'General') self.tabTitleVisible = translate('OpenLP.GeneralTab', 'General')
self.monitorGroupBox.setTitle(translate('OpenLP.GeneralTab', self.monitorGroupBox.setTitle(translate('OpenLP.GeneralTab',
'Monitors')) 'Monitors'))
self.monitorLabel.setText(translate('OpenLP.GeneralTab', self.monitorRadioButton.setText(translate('OpenLP.GeneralTab',
'Select monitor for output display:')) 'Select monitor for output display:'))
self.displayOnMonitorCheck.setText( self.displayOnMonitorCheck.setText(
translate('OpenLP.GeneralTab', 'Display if a single screen')) translate('OpenLP.GeneralTab', 'Display if a single screen'))
@ -231,8 +237,6 @@ class GeneralTab(SettingsTab):
'Unblank display when adding new live item')) 'Unblank display when adding new live item'))
self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab', self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab',
'Automatically preview next item in service')) 'Automatically preview next item in service'))
self.enableLoopCheckBox.setText(translate('OpenLP.GeneralTab',
'Enable slide wrap-around'))
self.timeoutLabel.setText(translate('OpenLP.GeneralTab', self.timeoutLabel.setText(translate('OpenLP.GeneralTab',
'Timed slide interval:')) 'Timed slide interval:'))
self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec')) self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec'))
@ -244,10 +248,8 @@ class GeneralTab(SettingsTab):
self.passwordLabel.setText( self.passwordLabel.setText(
translate('OpenLP.GeneralTab', 'SongSelect password:')) translate('OpenLP.GeneralTab', 'SongSelect password:'))
# Moved from display tab # Moved from display tab
self.displayGroupBox.setTitle( self.overrideRadioButton.setText(translate('OpenLP.GeneralTab',
translate('OpenLP.GeneralTab', 'Display Position')) 'Override display position:'))
self.overrideCheckBox.setText(translate('OpenLP.GeneralTab',
'Override display position'))
self.customXLabel.setText(translate('OpenLP.GeneralTab', 'X')) self.customXLabel.setText(translate('OpenLP.GeneralTab', 'X'))
self.customYLabel.setText(translate('OpenLP.GeneralTab', 'Y')) self.customYLabel.setText(translate('OpenLP.GeneralTab', 'Y'))
self.customHeightLabel.setText(translate('OpenLP.GeneralTab', 'Height')) self.customHeightLabel.setText(translate('OpenLP.GeneralTab', 'Height'))
@ -256,6 +258,8 @@ class GeneralTab(SettingsTab):
translate('OpenLP.GeneralTab', 'Background Audio')) translate('OpenLP.GeneralTab', 'Background Audio'))
self.startPausedCheckBox.setText( self.startPausedCheckBox.setText(
translate('OpenLP.GeneralTab', 'Start background audio paused')) translate('OpenLP.GeneralTab', 'Start background audio paused'))
self.repeatListCheckBox.setText(
translate('OpenLP.GeneralTab', 'Repeat track list'))
def load(self): def load(self):
""" """
@ -289,11 +293,12 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(True)).toBool()) QtCore.QVariant(True)).toBool())
self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview', self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview',
QtCore.QVariant(False)).toBool()) QtCore.QVariant(False)).toBool())
self.enableLoopCheckBox.setChecked(settings.value(u'enable slide loop',
QtCore.QVariant(True)).toBool())
self.timeoutSpinBox.setValue(settings.value(u'loop delay', self.timeoutSpinBox.setValue(settings.value(u'loop delay',
QtCore.QVariant(5)).toInt()[0]) QtCore.QVariant(5)).toInt()[0])
self.overrideCheckBox.setChecked(settings.value(u'override position', self.monitorRadioButton.setChecked(
not settings.value(u'override position',
QtCore.QVariant(False)).toBool())
self.overrideRadioButton.setChecked(settings.value(u'override position',
QtCore.QVariant(False)).toBool()) QtCore.QVariant(False)).toBool())
self.customXValueEdit.setValue(settings.value(u'x position', self.customXValueEdit.setValue(settings.value(u'x position',
QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0]) QtCore.QVariant(self.screens.current[u'size'].x())).toInt()[0])
@ -305,12 +310,20 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(self.screens.current[u'size'].width())).toInt()[0]) QtCore.QVariant(self.screens.current[u'size'].width())).toInt()[0])
self.startPausedCheckBox.setChecked(settings.value( self.startPausedCheckBox.setChecked(settings.value(
u'audio start paused', QtCore.QVariant(True)).toBool()) u'audio start paused', QtCore.QVariant(True)).toBool())
self.repeatListCheckBox.setChecked(settings.value(
u'audio repeat list', QtCore.QVariant(False)).toBool())
settings.endGroup() settings.endGroup()
self.customXValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.monitorComboBox.setDisabled(self.overrideRadioButton.isChecked())
self.customYValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.displayOnMonitorCheck.setDisabled(
self.customHeightValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.overrideRadioButton.isChecked())
self.customWidthValueEdit.setEnabled(self.overrideCheckBox.isChecked()) self.customXValueEdit.setEnabled(self.overrideRadioButton.isChecked())
self.customYValueEdit.setEnabled(self.overrideRadioButton.isChecked())
self.customHeightValueEdit.setEnabled(
self.overrideRadioButton.isChecked())
self.customWidthValueEdit.setEnabled(
self.overrideRadioButton.isChecked())
self.display_changed = False self.display_changed = False
settings.beginGroup(self.settingsSection)
def save(self): def save(self):
""" """
@ -336,8 +349,6 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(self.autoUnblankCheckBox.isChecked())) QtCore.QVariant(self.autoUnblankCheckBox.isChecked()))
settings.setValue(u'auto preview', settings.setValue(u'auto preview',
QtCore.QVariant(self.autoPreviewCheckBox.isChecked())) QtCore.QVariant(self.autoPreviewCheckBox.isChecked()))
settings.setValue(u'enable slide loop',
QtCore.QVariant(self.enableLoopCheckBox.isChecked()))
settings.setValue(u'loop delay', settings.setValue(u'loop delay',
QtCore.QVariant(self.timeoutSpinBox.value())) QtCore.QVariant(self.timeoutSpinBox.value()))
settings.setValue(u'ccli number', settings.setValue(u'ccli number',
@ -355,9 +366,11 @@ class GeneralTab(SettingsTab):
settings.setValue(u'width', settings.setValue(u'width',
QtCore.QVariant(self.customWidthValueEdit.value())) QtCore.QVariant(self.customWidthValueEdit.value()))
settings.setValue(u'override position', settings.setValue(u'override position',
QtCore.QVariant(self.overrideCheckBox.isChecked())) QtCore.QVariant(self.overrideRadioButton.isChecked()))
settings.setValue(u'audio start paused', settings.setValue(u'audio start paused',
QtCore.QVariant(self.startPausedCheckBox.isChecked())) QtCore.QVariant(self.startPausedCheckBox.isChecked()))
settings.setValue(u'audio repeat list',
QtCore.QVariant(self.repeatListCheckBox.isChecked()))
settings.endGroup() settings.endGroup()
# On save update the screens as well # On save update the screens as well
self.postSetUp(True) self.postSetUp(True)
@ -379,7 +392,7 @@ class GeneralTab(SettingsTab):
self.customYValueEdit.value(), self.customYValueEdit.value(),
self.customWidthValueEdit.value(), self.customWidthValueEdit.value(),
self.customHeightValueEdit.value()) self.customHeightValueEdit.value())
if self.overrideCheckBox.isChecked(): if self.overrideRadioButton.isChecked():
self.screens.set_override_display() self.screens.set_override_display()
else: else:
self.screens.reset_current_display() self.screens.reset_current_display()
@ -387,13 +400,15 @@ class GeneralTab(SettingsTab):
Receiver.send_message(u'config_screen_changed') Receiver.send_message(u'config_screen_changed')
self.display_changed = False self.display_changed = False
def onOverrideCheckBoxToggled(self, checked): def onOverrideRadioButtonPressed(self, checked):
""" """
Toggle screen state depending on check box state. Toggle screen state depending on check box state.
``checked`` ``checked``
The state of the check box (boolean). The state of the check box (boolean).
""" """
self.monitorComboBox.setDisabled(checked)
self.displayOnMonitorCheck.setDisabled(checked)
self.customXValueEdit.setEnabled(checked) self.customXValueEdit.setEnabled(checked)
self.customYValueEdit.setEnabled(checked) self.customYValueEdit.setEnabled(checked)
self.customHeightValueEdit.setEnabled(checked) self.customHeightValueEdit.setEnabled(checked)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -28,13 +28,16 @@
The :mod:`maindisplay` module provides the functionality to display screens The :mod:`maindisplay` module provides the functionality to display screens
and play multimedia within OpenLP. and play multimedia within OpenLP.
""" """
import cgi
import logging import logging
import sys
from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
translate, PluginManager translate, PluginManager, expand_tags
from openlp.core.lib.theme import BackgroundType
from openlp.core.ui import HideMode, ScreenList, AlertLocation from openlp.core.ui import HideMode, ScreenList, AlertLocation
@ -60,6 +63,11 @@ class Display(QtGui.QGraphicsView):
self.controller = controller self.controller = controller
self.screen = {} self.screen = {}
self.plugins = PluginManager.get_instance().plugins self.plugins = PluginManager.get_instance().plugins
# FIXME: On Mac OS X (tested on 10.7) the display screen is corrupt with
# OpenGL. Only white blank screen is shown on the 2nd monitor all the
# time. We need to investigate more how to use OpenGL properly on Mac OS
# X.
if sys.platform != 'darwin':
self.setViewport(QtOpenGL.QGLWidget()) self.setViewport(QtOpenGL.QGLWidget())
def setup(self): def setup(self):
@ -74,6 +82,10 @@ class Display(QtGui.QGraphicsView):
self.screen[u'size'].width(), self.screen[u'size'].height()) self.screen[u'size'].width(), self.screen[u'size'].height())
self.webView.settings().setAttribute( self.webView.settings().setAttribute(
QtWebKit.QWebSettings.PluginsEnabled, True) QtWebKit.QWebSettings.PluginsEnabled, True)
palette = self.webView.palette()
palette.setBrush(QtGui.QPalette.Base, QtCore.Qt.transparent)
self.webView.page().setPalette(palette)
self.webView.setAttribute(QtCore.Qt.WA_OpaquePaintEvent, False)
self.page = self.webView.page() self.page = self.webView.page()
self.frame = self.page.mainFrame() self.frame = self.page.mainFrame()
if self.isLive and log.getEffectiveLevel() == logging.DEBUG: if self.isLive and log.getEffectiveLevel() == logging.DEBUG:
@ -120,10 +132,19 @@ class MainDisplay(Display):
self.audioPlayer = None self.audioPlayer = None
self.firstTime = True self.firstTime = True
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \
QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.WindowStaysOnTopHint
QtCore.Qt.X11BypassWindowManagerHint) if QtCore.QSettings().value(u'advanced/x11 bypass wm',
QtCore.QVariant(True)).toBool():
windowFlags |= QtCore.Qt.X11BypassWindowManagerHint
# FIXME: QtCore.Qt.SplashScreen is workaround to make display screen
# stay always on top on Mac OS X. For details see bug 906926.
# It needs more investigation to fix it properly.
if sys.platform == 'darwin':
windowFlags |= QtCore.Qt.SplashScreen
self.setWindowFlags(windowFlags)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose) self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setTransparency(False)
if self.isLive: if self.isLive:
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_display_hide'), self.hideDisplay) QtCore.SIGNAL(u'live_display_hide'), self.hideDisplay)
@ -134,6 +155,14 @@ class MainDisplay(Display):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.configChanged) QtCore.SIGNAL(u'config_updated'), self.configChanged)
def setTransparency(self, enabled):
if enabled:
self.setAutoFillBackground(False)
else:
self.setAttribute(QtCore.Qt.WA_NoSystemBackground, False)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground, enabled)
self.repaint()
def cssChanged(self): def cssChanged(self):
""" """
We may need to rebuild the CSS on the live display. We may need to rebuild the CSS on the live display.
@ -222,16 +251,17 @@ class MainDisplay(Display):
The text to be displayed. The text to be displayed.
""" """
log.debug(u'alert to display') log.debug(u'alert to display')
# First we convert <>& marks to html variants, then apply
# formattingtags, finally we double all backslashes for JavaScript.
text_prepared = expand_tags(cgi.escape(text)) \
.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"')
if self.height() != self.screen[u'size'].height() or \ if self.height() != self.screen[u'size'].height() or \
not self.isVisible(): not self.isVisible():
shrink = True shrink = True
js = u'show_alert("%s", "%s")' % ( js = u'show_alert("%s", "%s")' % (text_prepared, u'top')
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'),
u'top')
else: else:
shrink = False shrink = False
js = u'show_alert("%s", "")' % ( js = u'show_alert("%s", "")' % text_prepared
text.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
height = self.frame.evaluateJavaScript(js) height = self.frame.evaluateJavaScript(js)
if shrink: if shrink:
if text: if text:
@ -332,13 +362,7 @@ class MainDisplay(Display):
self.setVisible(True) self.setVisible(True)
else: else:
self.setVisible(True) self.setVisible(True)
preview = QtGui.QPixmap(self.screen[u'size'].width(), return QtGui.QPixmap.grabWidget(self)
self.screen[u'size'].height())
painter = QtGui.QPainter(preview)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
self.frame.render(painter)
painter.end()
return preview
def buildHtml(self, serviceItem, image=None): def buildHtml(self, serviceItem, image=None):
""" """
@ -364,6 +388,8 @@ class MainDisplay(Display):
# replace the background # replace the background
background = self.imageManager. \ background = self.imageManager. \
get_image_bytes(self.override[u'image']) get_image_bytes(self.override[u'image'])
self.setTransparency(self.serviceItem.themedata.background_type ==
BackgroundType.to_string(BackgroundType.Transparent))
if self.serviceItem.themedata.background_filename: if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.imageManager. \ self.serviceItem.bg_image_bytes = self.imageManager. \
get_image_bytes(self.serviceItem.themedata.theme_name) get_image_bytes(self.serviceItem.themedata.theme_name)
@ -402,6 +428,11 @@ class MainDisplay(Display):
Store the images so they can be replaced when required Store the images so they can be replaced when required
""" """
log.debug(u'hideDisplay mode = %d', mode) 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',
QtCore.QVariant(True)).toBool():
return
if mode == HideMode.Screen: if mode == HideMode.Screen:
self.frame.evaluateJavaScript(u'show_blank("desktop");') self.frame.evaluateJavaScript(u'show_blank("desktop");')
self.setVisible(False) self.setVisible(False)
@ -422,6 +453,11 @@ class MainDisplay(Display):
Make the stored images None to release memory. Make the stored images None to release memory.
""" """
log.debug(u'showDisplay') 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',
QtCore.QVariant(True)).toBool():
return
self.frame.evaluateJavaScript('show_blank("show");') self.frame.evaluateJavaScript('show_blank("show");')
if self.isHidden(): if self.isHidden():
self.setVisible(True) self.setVisible(True)
@ -459,11 +495,15 @@ class AudioPlayer(QtCore.QObject):
QtCore.QObject.__init__(self, parent) QtCore.QObject.__init__(self, parent)
self.currentIndex = -1 self.currentIndex = -1
self.playlist = [] self.playlist = []
self.repeat = False
self.mediaObject = Phonon.MediaObject() self.mediaObject = Phonon.MediaObject()
self.mediaObject.setTickInterval(100)
self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory) self.audioObject = Phonon.AudioOutput(Phonon.VideoCategory)
Phonon.createPath(self.mediaObject, self.audioObject) Phonon.createPath(self.mediaObject, self.audioObject)
QtCore.QObject.connect(self.mediaObject, QtCore.QObject.connect(self.mediaObject,
QtCore.SIGNAL(u'aboutToFinish()'), self.onAboutToFinish) QtCore.SIGNAL(u'aboutToFinish()'), self.onAboutToFinish)
QtCore.QObject.connect(self.mediaObject,
QtCore.SIGNAL(u'finished()'), self.onFinished)
def __del__(self): def __del__(self):
""" """
@ -482,6 +522,14 @@ class AudioPlayer(QtCore.QObject):
if len(self.playlist) > self.currentIndex: if len(self.playlist) > self.currentIndex:
self.mediaObject.enqueue(self.playlist[self.currentIndex]) self.mediaObject.enqueue(self.playlist[self.currentIndex])
def onFinished(self):
if self.repeat:
log.debug(u'Repeat is enabled... here we go again!')
self.mediaObject.clearQueue()
self.mediaObject.clear()
self.currentIndex = -1
self.play()
def connectVolumeSlider(self, slider): def connectVolumeSlider(self, slider):
slider.setAudioOutput(self.audioObject) slider.setAudioOutput(self.audioObject)
@ -529,3 +577,27 @@ class AudioPlayer(QtCore.QObject):
for filename in filenames: for filename in filenames:
self.playlist.append(Phonon.MediaSource(filename)) self.playlist.append(Phonon.MediaSource(filename))
def next(self):
if not self.repeat and self.currentIndex + 1 == len(self.playlist):
return
isPlaying = self.mediaObject.state() == Phonon.PlayingState
self.currentIndex += 1
if self.repeat and self.currentIndex == len(self.playlist):
self.currentIndex = 0
self.mediaObject.clearQueue()
self.mediaObject.clear()
self.mediaObject.enqueue(self.playlist[self.currentIndex])
if isPlaying:
self.mediaObject.play()
def goTo(self, index):
isPlaying = self.mediaObject.state() == Phonon.PlayingState
self.mediaObject.clearQueue()
self.mediaObject.clear()
self.currentIndex = index
self.mediaObject.enqueue(self.playlist[self.currentIndex])
if isPlaying:
self.mediaObject.play()
def connectSlot(self, signal, slot):
QtCore.QObject.connect(self.mediaObject, signal, slot)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -36,8 +36,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \ from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
PluginManager, Receiver, translate, ImageManager, PluginStatus PluginManager, Receiver, translate, ImageManager, PluginStatus
from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \ from openlp.core.lib.ui import UiStrings, create_action
icon_action, shortcut_action from openlp.core.lib import SlideLimits
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
ThemeManager, SlideController, PluginForm, MediaDockManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \
ShortcutListForm, FormattingTagForm ShortcutListForm, FormattingTagForm
@ -178,75 +178,78 @@ class Ui_MainWindow(object):
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_category(unicode(UiStrings().File), action_list.add_category(unicode(UiStrings().File),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.fileNewItem = shortcut_action(mainWindow, u'fileNewItem', self.fileNewItem = create_action(mainWindow, u'fileNewItem',
[QtGui.QKeySequence(u'Ctrl+N')], icon=u':/general/general_new.png',
self.serviceManagerContents.onNewServiceClicked, shortcuts=[QtGui.QKeySequence(u'Ctrl+N')],
u':/general/general_new.png', category=unicode(UiStrings().File)) category=UiStrings().File,
self.fileOpenItem = shortcut_action(mainWindow, u'fileOpenItem', triggers=self.serviceManagerContents.onNewServiceClicked)
[QtGui.QKeySequence(u'Ctrl+O')], self.fileOpenItem = create_action(mainWindow, u'fileOpenItem',
self.serviceManagerContents.onLoadServiceClicked, icon=u':/general/general_open.png',
u':/general/general_open.png', category=unicode(UiStrings().File)) shortcuts=[QtGui.QKeySequence(u'Ctrl+O')],
self.fileSaveItem = shortcut_action(mainWindow, u'fileSaveItem', category=UiStrings().File,
[QtGui.QKeySequence(u'Ctrl+S')], triggers=self.serviceManagerContents.onLoadServiceClicked)
self.serviceManagerContents.saveFile, self.fileSaveItem = create_action(mainWindow, u'fileSaveItem',
u':/general/general_save.png', category=unicode(UiStrings().File)) icon=u':/general/general_save.png',
self.fileSaveAsItem = shortcut_action(mainWindow, u'fileSaveAsItem', shortcuts=[QtGui.QKeySequence(u'Ctrl+S')],
[QtGui.QKeySequence(u'Ctrl+Shift+S')], category=UiStrings().File,
self.serviceManagerContents.saveFileAs, triggers=self.serviceManagerContents.saveFile)
category=unicode(UiStrings().File)) self.fileSaveAsItem = create_action(mainWindow, u'fileSaveAsItem',
self.printServiceOrderItem = shortcut_action(mainWindow, shortcuts=[QtGui.QKeySequence(u'Ctrl+Shift+S')],
u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')], category=UiStrings().File,
self.serviceManagerContents.printServiceOrder, triggers=self.serviceManagerContents.saveFileAs)
category=unicode(UiStrings().File)) self.printServiceOrderItem = create_action(mainWindow,
self.fileExitItem = shortcut_action(mainWindow, u'fileExitItem', u'printServiceItem', shortcuts=[QtGui.QKeySequence(u'Ctrl+P')],
[QtGui.QKeySequence(u'Alt+F4')], mainWindow.close, category=UiStrings().File,
u':/system/system_exit.png', category=unicode(UiStrings().File)) triggers=self.serviceManagerContents.printServiceOrder)
self.fileExitItem = create_action(mainWindow, u'fileExitItem',
icon=u':/system/system_exit.png',
shortcuts=[QtGui.QKeySequence(u'Alt+F4')],
category=UiStrings().File, triggers=mainWindow.close)
action_list.add_category(unicode(UiStrings().Import), action_list.add_category(unicode(UiStrings().Import),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.importThemeItem = base_action( self.importThemeItem = create_action(mainWindow,
mainWindow, u'importThemeItem', unicode(UiStrings().Import)) u'importThemeItem', category=UiStrings().Import)
self.importLanguageItem = base_action( self.importLanguageItem = create_action(mainWindow,
mainWindow, u'importLanguageItem')#, unicode(UiStrings().Import)) u'importLanguageItem')#, category=UiStrings().Import)
action_list.add_category(unicode(UiStrings().Export), action_list.add_category(unicode(UiStrings().Export),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.exportThemeItem = base_action( self.exportThemeItem = create_action(mainWindow,
mainWindow, u'exportThemeItem', unicode(UiStrings().Export)) u'exportThemeItem', category=UiStrings().Export)
self.exportLanguageItem = base_action( self.exportLanguageItem = create_action(mainWindow,
mainWindow, u'exportLanguageItem')#, unicode(UiStrings().Export)) u'exportLanguageItem')#, category=UiStrings().Export)
action_list.add_category(unicode(UiStrings().View), action_list.add_category(unicode(UiStrings().View),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.viewMediaManagerItem = shortcut_action(mainWindow, self.viewMediaManagerItem = create_action(mainWindow,
u'viewMediaManagerItem', [QtGui.QKeySequence(u'F8')], u'viewMediaManagerItem', shortcuts=[QtGui.QKeySequence(u'F8')],
self.toggleMediaManager, u':/system/system_mediamanager.png', icon=u':/system/system_mediamanager.png',
self.mediaManagerDock.isVisible(), unicode(UiStrings().View)) checked=self.mediaManagerDock.isVisible(),
self.viewThemeManagerItem = shortcut_action(mainWindow, category=UiStrings().View, triggers=self.toggleMediaManager)
u'viewThemeManagerItem', [QtGui.QKeySequence(u'F10')], self.viewThemeManagerItem = create_action(mainWindow,
self.toggleThemeManager, u':/system/system_thememanager.png', u'viewThemeManagerItem', shortcuts=[QtGui.QKeySequence(u'F10')],
self.themeManagerDock.isVisible(), unicode(UiStrings().View)) icon=u':/system/system_thememanager.png',
self.viewServiceManagerItem = shortcut_action(mainWindow, checked=self.themeManagerDock.isVisible(),
u'viewServiceManagerItem', [QtGui.QKeySequence(u'F9')], category=UiStrings().View, triggers=self.toggleThemeManager)
self.toggleServiceManager, u':/system/system_servicemanager.png', self.viewServiceManagerItem = create_action(mainWindow,
self.serviceManagerDock.isVisible(), unicode(UiStrings().View)) u'viewServiceManagerItem', shortcuts=[QtGui.QKeySequence(u'F9')],
self.viewPreviewPanel = shortcut_action(mainWindow, icon=u':/system/system_servicemanager.png',
u'viewPreviewPanel', [QtGui.QKeySequence(u'F11')], checked=self.serviceManagerDock.isVisible(),
self.setPreviewPanelVisibility, checked=previewVisible, category=UiStrings().View, triggers=self.toggleServiceManager)
category=unicode(UiStrings().View)) self.viewPreviewPanel = create_action(mainWindow, u'viewPreviewPanel',
self.viewLivePanel = shortcut_action(mainWindow, u'viewLivePanel', shortcuts=[QtGui.QKeySequence(u'F11')], checked=previewVisible,
[QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility, category=UiStrings().View, triggers=self.setPreviewPanelVisibility)
checked=liveVisible, category=unicode(UiStrings().View)) self.viewLivePanel = create_action(mainWindow, u'viewLivePanel',
self.lockPanel = shortcut_action(mainWindow, u'lockPanel', shortcuts=[QtGui.QKeySequence(u'F12')], checked=liveVisible,
None, self.setLockPanel, category=UiStrings().View, triggers=self.setLivePanelVisibility)
checked=panelLocked, category=None) self.lockPanel = create_action(mainWindow, u'lockPanel',
checked=panelLocked, triggers=self.setLockPanel)
action_list.add_category(unicode(UiStrings().ViewMode), action_list.add_category(unicode(UiStrings().ViewMode),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.modeDefaultItem = checkable_action( self.modeDefaultItem = create_action(mainWindow, u'modeDefaultItem',
mainWindow, u'modeDefaultItem', checked=False, category=UiStrings().ViewMode)
category=unicode(UiStrings().ViewMode)) self.modeSetupItem = create_action(mainWindow, u'modeSetupItem',
self.modeSetupItem = checkable_action( checked=False, category=UiStrings().ViewMode)
mainWindow, u'modeSetupItem', self.modeLiveItem = create_action(mainWindow, u'modeLiveItem',
category=unicode(UiStrings().ViewMode)) checked=True, category=UiStrings().ViewMode)
self.modeLiveItem = checkable_action(
mainWindow, u'modeLiveItem', True, unicode(UiStrings().ViewMode))
self.modeGroup = QtGui.QActionGroup(mainWindow) self.modeGroup = QtGui.QActionGroup(mainWindow)
self.modeGroup.addAction(self.modeDefaultItem) self.modeGroup.addAction(self.modeDefaultItem)
self.modeGroup.addAction(self.modeSetupItem) self.modeGroup.addAction(self.modeSetupItem)
@ -254,25 +257,27 @@ class Ui_MainWindow(object):
self.modeDefaultItem.setChecked(True) self.modeDefaultItem.setChecked(True)
action_list.add_category(unicode(UiStrings().Tools), action_list.add_category(unicode(UiStrings().Tools),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.toolsAddToolItem = icon_action(mainWindow, u'toolsAddToolItem', self.toolsAddToolItem = create_action(mainWindow,
u':/tools/tools_add.png', category=unicode(UiStrings().Tools)) u'toolsAddToolItem', icon=u':/tools/tools_add.png',
self.toolsOpenDataFolder = icon_action(mainWindow, category=UiStrings().Tools)
u'toolsOpenDataFolder', u':/general/general_open.png', self.toolsOpenDataFolder = create_action(mainWindow,
category=unicode(UiStrings().Tools)) u'toolsOpenDataFolder', icon=u':/general/general_open.png',
self.toolsFirstTimeWizard = icon_action(mainWindow, category=UiStrings().Tools)
u'toolsFirstTimeWizard', u':/general/general_revert.png', self.toolsFirstTimeWizard = create_action(mainWindow,
category=unicode(UiStrings().Tools)) u'toolsFirstTimeWizard', icon=u':/general/general_revert.png',
self.updateThemeImages = base_action(mainWindow, category=UiStrings().Tools)
u'updateThemeImages', category=unicode(UiStrings().Tools)) self.updateThemeImages = create_action(mainWindow,
u'updateThemeImages', category=UiStrings().Tools)
action_list.add_category(unicode(UiStrings().Settings), action_list.add_category(unicode(UiStrings().Settings),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.settingsPluginListItem = shortcut_action(mainWindow, self.settingsPluginListItem = create_action(mainWindow,
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')], u'settingsPluginListItem',
self.onPluginItemClicked, u':/system/settings_plugin_list.png', icon=u':/system/settings_plugin_list.png',
category=unicode(UiStrings().Settings)) shortcuts=[QtGui.QKeySequence(u'Alt+F7')],
category=UiStrings().Settings, triggers=self.onPluginItemClicked)
# i18n Language Items # i18n Language Items
self.autoLanguageItem = checkable_action(mainWindow, self.autoLanguageItem = create_action(mainWindow, u'autoLanguageItem',
u'autoLanguageItem', LanguageManager.auto_language) checked=LanguageManager.auto_language)
self.languageGroup = QtGui.QActionGroup(mainWindow) self.languageGroup = QtGui.QActionGroup(mainWindow)
self.languageGroup.setExclusive(True) self.languageGroup.setExclusive(True)
self.languageGroup.setObjectName(u'languageGroup') self.languageGroup.setObjectName(u'languageGroup')
@ -280,44 +285,43 @@ class Ui_MainWindow(object):
qmList = LanguageManager.get_qm_list() qmList = LanguageManager.get_qm_list()
savedLanguage = LanguageManager.get_language() savedLanguage = LanguageManager.get_language()
for key in sorted(qmList.keys()): for key in sorted(qmList.keys()):
languageItem = checkable_action( languageItem = create_action(mainWindow, key,
mainWindow, key, qmList[key] == savedLanguage) checked=qmList[key] == savedLanguage)
add_actions(self.languageGroup, [languageItem]) add_actions(self.languageGroup, [languageItem])
self.settingsShortcutsItem = icon_action(mainWindow, self.settingsShortcutsItem = create_action(mainWindow,
u'settingsShortcutsItem', u'settingsShortcutsItem',
u':/system/system_configure_shortcuts.png', icon=u':/system/system_configure_shortcuts.png',
category=unicode(UiStrings().Settings)) category=UiStrings().Settings)
# Formatting Tags were also known as display tags. # Formatting Tags were also known as display tags.
self.formattingTagItem = icon_action(mainWindow, self.formattingTagItem = create_action(mainWindow,
u'displayTagItem', u':/system/tag_editor.png', u'displayTagItem', icon=u':/system/tag_editor.png',
category=unicode(UiStrings().Settings)) category=UiStrings().Settings)
self.settingsConfigureItem = icon_action(mainWindow, self.settingsConfigureItem = create_action(mainWindow,
u'settingsConfigureItem', u':/system/system_settings.png', u'settingsConfigureItem', icon=u':/system/system_settings.png',
category=unicode(UiStrings().Settings)) category=UiStrings().Settings)
self.settingsImportItem = base_action(mainWindow, self.settingsImportItem = create_action(mainWindow,
u'settingsImportItem', category=unicode(UiStrings().Settings)) u'settingsImportItem', category=UiStrings().Settings)
self.settingsExportItem = base_action(mainWindow, self.settingsExportItem = create_action(mainWindow,
u'settingsExportItem', category=unicode(UiStrings().Settings)) u'settingsExportItem', category=UiStrings().Settings)
action_list.add_category(unicode(UiStrings().Help), action_list.add_category(unicode(UiStrings().Help),
CategoryOrder.standardMenu) CategoryOrder.standardMenu)
self.aboutItem = shortcut_action(mainWindow, u'aboutItem', self.aboutItem = create_action(mainWindow, u'aboutItem',
[QtGui.QKeySequence(u'Ctrl+F1')], self.onAboutItemClicked, icon=u':/system/system_about.png',
u':/system/system_about.png', category=unicode(UiStrings().Help)) shortcuts=[QtGui.QKeySequence(u'Ctrl+F1')],
category=UiStrings().Help, triggers=self.onAboutItemClicked)
if os.name == u'nt': if os.name == u'nt':
self.localHelpFile = os.path.join( self.localHelpFile = os.path.join(
AppLocation.get_directory(AppLocation.AppDir), 'OpenLP.chm') AppLocation.get_directory(AppLocation.AppDir), 'OpenLP.chm')
self.offlineHelpItem = shortcut_action( self.offlineHelpItem = create_action(mainWindow, u'offlineHelpItem',
mainWindow, u'offlineHelpItem', [QtGui.QKeySequence(u'F1')], icon=u':/system/system_help_contents.png',
self.onOfflineHelpClicked, shortcuts=[QtGui.QKeySequence(u'F1')],
u':/system/system_help_contents.png', category=UiStrings().Help, triggers=self.onOfflineHelpClicked)
category=unicode(UiStrings().Help)) self.onlineHelpItem = create_action(mainWindow, u'onlineHelpItem',
self.onlineHelpItem = shortcut_action( icon=u':/system/system_online_help.png',
mainWindow, u'onlineHelpItem', shortcuts=[QtGui.QKeySequence(u'Alt+F1')],
[QtGui.QKeySequence(u'Alt+F1')], self.onOnlineHelpClicked, category=UiStrings().Help, triggers=self.onOnlineHelpClicked)
u':/system/system_online_help.png', self.webSiteItem = create_action(mainWindow,
category=unicode(UiStrings().Help)) u'webSiteItem', category=UiStrings().Help)
self.webSiteItem = base_action(
mainWindow, u'webSiteItem', category=unicode(UiStrings().Help))
add_actions(self.fileImportMenu, (self.settingsImportItem, None, add_actions(self.fileImportMenu, (self.settingsImportItem, None,
self.importThemeItem, self.importLanguageItem)) self.importThemeItem, self.importLanguageItem))
add_actions(self.fileExportMenu, (self.settingsExportItem, None, add_actions(self.fileExportMenu, (self.settingsExportItem, None,
@ -1059,7 +1063,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
export_settings.endGroup() export_settings.endGroup()
# Write all the sections and keys. # Write all the sections and keys.
for section_key in keys: for section_key in keys:
section, key = section_key.split(u'/')
key_value = settings.value(section_key) key_value = settings.value(section_key)
export_settings.setValue(section_key, key_value) export_settings.setValue(section_key, key_value)
export_settings.sync() export_settings.sync()
@ -1307,6 +1310,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Load the main window settings. Load the main window settings.
""" """
log.debug(u'Loading QSettings') log.debug(u'Loading QSettings')
# Migrate Wrap Settings to Slide Limits Settings
if QtCore.QSettings().contains(self.generalSettingsSection +
u'/enable slide loop'):
if QtCore.QSettings().value(self.generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool():
QtCore.QSettings().setValue(self.advancedlSettingsSection +
u'/slide limits', QtCore.QVariant(SlideLimits.Wrap))
else:
QtCore.QSettings().setValue(self.advancedlSettingsSection +
u'/slide limits', QtCore.QVariant(SlideLimits.End))
QtCore.QSettings().remove(self.generalSettingsSection +
u'/enable slide loop')
Receiver.send_message(u'slidecontroller_update_slide_limits')
settings = QtCore.QSettings() settings = QtCore.QSettings()
# Remove obsolete entries. # Remove obsolete entries.
settings.remove(u'custom slide') settings.remove(u'custom slide')
@ -1365,27 +1381,24 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
recentFileCount = QtCore.QSettings().value( recentFileCount = QtCore.QSettings().value(
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0] u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
existingRecentFiles = [recentFile for recentFile in self.recentFiles existingRecentFiles = [recentFile for recentFile in self.recentFiles
if QtCore.QFile.exists(recentFile)] if os.path.isfile(unicode(recentFile))]
recentFilesToDisplay = existingRecentFiles[0:recentFileCount] recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
self.recentFilesMenu.clear() self.recentFilesMenu.clear()
for fileId, filename in enumerate(recentFilesToDisplay): for fileId, filename in enumerate(recentFilesToDisplay):
log.debug('Recent file name: %s', filename) log.debug('Recent file name: %s', filename)
action = base_action(self, u'') action = create_action(self, u'',
action.setText(u'&%d %s' % text=u'&%d %s' % (fileId + 1, os.path.splitext(os.path.basename(
(fileId + 1, QtCore.QFileInfo(filename).fileName())) unicode(filename)))[0]), data=filename,
action.setData(QtCore.QVariant(filename)) triggers=self.serviceManagerContents.onRecentServiceClicked)
self.connect(action, QtCore.SIGNAL(u'triggered()'),
self.serviceManagerContents.onRecentServiceClicked)
self.recentFilesMenu.addAction(action) self.recentFilesMenu.addAction(action)
clearRecentFilesAction = base_action(self, u'') clearRecentFilesAction = create_action(self, u'',
clearRecentFilesAction.setText( text=translate('OpenLP.MainWindow', 'Clear List',
translate('OpenLP.MainWindow', 'Clear List', 'Clear List of recent files'),
'Clear List of recent files')) statustip=translate('OpenLP.MainWindow',
clearRecentFilesAction.setStatusTip( 'Clear the list of recent files.'),
translate('OpenLP.MainWindow', 'Clear the list of recent files.')) enabled=not self.recentFiles.isEmpty(),
triggers=self.recentFiles.clear)
add_actions(self.recentFilesMenu, (None, clearRecentFilesAction)) add_actions(self.recentFilesMenu, (None, clearRecentFilesAction))
self.connect(clearRecentFilesAction, QtCore.SIGNAL(u'triggered()'),
self.recentFiles.clear)
clearRecentFilesAction.setEnabled(not self.recentFiles.isEmpty()) clearRecentFilesAction.setEnabled(not self.recentFiles.isEmpty())
def addRecentFile(self, filename): def addRecentFile(self, filename):

View File

@ -24,17 +24,21 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
import logging
from PyQt4 import QtCore
log = logging.getLogger(__name__)
class MediaState(object): class MediaState(object):
""" """
An enumeration for possible States of the Media Player (copied partially An enumeration for possible States of the Media Player
from Phonon::State)
""" """
Loading = 0 Off = 0
Stopped = 1 Loaded = 1
Playing = 2 Playing = 2
Paused = 4 Paused = 3
Off = 6 Stopped = 4
class MediaType(object): class MediaType(object):
@ -62,4 +66,48 @@ class MediaInfo(object):
end_time = 0 end_time = 0
media_type = MediaType() media_type = MediaType()
def get_media_players():
"""
This method extract the configured media players and overridden player from
the settings
``players_list``
this is a python list with all active media players
``overridden_player``
here an special media player is choosen for all media actions
"""
log.debug(u'get_media_players')
players = unicode(QtCore.QSettings().value(u'media/players').toString())
if not players:
players = u'webkit'
reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
if QtCore.QSettings().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)
else:
overridden_player = u'auto'
else:
overridden_player = u''
players_list = players.replace(u'[', u'').replace(u']', u'').split(u',')
return players_list, overridden_player
def set_media_players(players_list, overridden_player=u'auto'):
"""
This method saves the configured media players and overridden player to the
settings
``players_list``
this is a python list with all active media players
``overridden_player``
here an special media player is choosen for all media actions
"""
log.debug(u'set_media_players')
players = u','.join(players_list)
if QtCore.QSettings().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))
from mediacontroller import MediaController from mediacontroller import MediaController

View File

@ -32,7 +32,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, translate from openlp.core.lib import OpenLPToolbar, Receiver, translate
from openlp.core.lib.mediaplayer import MediaPlayer from openlp.core.lib.mediaplayer import MediaPlayer
from openlp.core.lib.ui import critical_error_message_box from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import MediaState, MediaInfo, MediaType from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \
get_media_players, set_media_players
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -47,7 +48,6 @@ class MediaController(object):
self.parent = parent self.parent = parent
self.mediaPlayers = {} self.mediaPlayers = {}
self.controller = [] self.controller = []
self.overridenPlayer = ''
self.curDisplayMediaPlayer = {} self.curDisplayMediaPlayer = {}
# Timer for video state # Timer for video state
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
@ -58,23 +58,21 @@ class MediaController(object):
QtCore.QObject.connect(self.timer, QtCore.QObject.connect(self.timer,
QtCore.SIGNAL("timeout()"), self.video_state) QtCore.SIGNAL("timeout()"), self.video_state)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_playback_play'), self.video_play) QtCore.SIGNAL(u'playbackPlay'), self.video_play)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_playback_pause'), self.video_pause) QtCore.SIGNAL(u'playbackPause'), self.video_pause)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_playback_stop'), self.video_stop) QtCore.SIGNAL(u'playbackStop'), self.video_stop)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'seek_slider'), self.video_seek) QtCore.SIGNAL(u'seekSlider'), self.video_seek)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'volume_slider'), self.video_volume) QtCore.SIGNAL(u'volumeSlider'), self.video_volume)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_hide'), self.video_hide) QtCore.SIGNAL(u'media_hide'), self.video_hide)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_blank'), self.video_blank) QtCore.SIGNAL(u'media_blank'), self.video_blank)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_unblank'), self.video_unblank) QtCore.SIGNAL(u'media_unblank'), self.video_unblank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_override_player'), self.override_player)
# Signals for background video # Signals for background video
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'songs_hide'), self.video_hide) QtCore.SIGNAL(u'songs_hide'), self.video_hide)
@ -84,11 +82,7 @@ class MediaController(object):
QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.set_active_players) QtCore.SIGNAL(u'mediaitem_media_rebuild'), self.set_active_players)
def set_active_players(self): def set_active_players(self):
playerSettings = str(QtCore.QSettings().value(u'media/players', savedPlayers = get_media_players()[0]
QtCore.QVariant(u'webkit')).toString())
if len(playerSettings) == 0:
playerSettings = u'webkit'
savedPlayers = playerSettings.split(u',')
for player in self.mediaPlayers.keys(): for player in self.mediaPlayers.keys():
if player in savedPlayers: if player in savedPlayers:
self.mediaPlayers[player].isActive = True self.mediaPlayers[player].isActive = True
@ -100,7 +94,6 @@ class MediaController(object):
Register each media Player controller (Webkit, Phonon, etc) and store Register each media Player controller (Webkit, Phonon, etc) and store
for later use for later use
""" """
if controller.check_available():
self.mediaPlayers[controller.name] = controller self.mediaPlayers[controller.name] = controller
def check_available_media_players(self): def check_available_media_players(self):
@ -130,17 +123,14 @@ class MediaController(object):
controller = controller_class(self) controller = controller_class(self)
self.register_controllers(controller) self.register_controllers(controller)
if self.mediaPlayers: if self.mediaPlayers:
playerSettings = str(QtCore.QSettings().value(u'media/players', savedPlayers, overriddenPlayer = get_media_players()
QtCore.QVariant(u'webkit')).toString())
savedPlayers = playerSettings.split(u',')
invalidMediaPlayers = [mediaPlayer for mediaPlayer in savedPlayers \ invalidMediaPlayers = [mediaPlayer for mediaPlayer in savedPlayers \
if not mediaPlayer in self.mediaPlayers] if not mediaPlayer in self.mediaPlayers or \
not self.mediaPlayers[mediaPlayer].check_available()]
if len(invalidMediaPlayers) > 0: if len(invalidMediaPlayers) > 0:
for invalidPlayer in invalidMediaPlayers: for invalidPlayer in invalidMediaPlayers:
savedPlayers.remove(invalidPlayer) savedPlayers.remove(invalidPlayer)
newPlayerSetting = u','.join(savedPlayers) set_media_players(savedPlayers, overriddenPlayer)
QtCore.QSettings().setValue(u'media/players',
QtCore.QVariant(newPlayerSetting))
self.set_active_players() self.set_active_players()
return True return True
else: else:
@ -160,6 +150,11 @@ class MediaController(object):
if self.curDisplayMediaPlayer[display] \ if self.curDisplayMediaPlayer[display] \
.state == MediaState.Playing: .state == MediaState.Playing:
return return
# no players are active anymore
for display in self.curDisplayMediaPlayer.keys():
if self.curDisplayMediaPlayer[display] \
.state != MediaState.Paused:
display.controller.seekSlider.setSliderPosition(0)
self.timer.stop() self.timer.stop()
def get_media_display_css(self): def get_media_display_css(self):
@ -204,47 +199,50 @@ class MediaController(object):
controller.media_info = MediaInfo() controller.media_info = MediaInfo()
# Build a Media ToolBar # Build a Media ToolBar
controller.mediabar = OpenLPToolbar(controller) controller.mediabar = OpenLPToolbar(controller)
controller.mediabar.addToolbarButton( controller.mediabar.addToolbarAction(u'playbackPlay',
u'media_playback_play', u':/slides/media_playback_start.png', text=u'media_playback_play',
translate('OpenLP.SlideController', 'Start playing media.'), icon=u':/slides/media_playback_start.png',
controller.sendToPlugins) tooltip=translate('OpenLP.SlideController', 'Start playing media.'),
controller.mediabar.addToolbarButton( triggers=controller.sendToPlugins)
u'media_playback_pause', u':/slides/media_playback_pause.png', controller.mediabar.addToolbarAction(u'playbackPause',
translate('OpenLP.SlideController', 'Pause playing media.'), text=u'media_playback_pause',
controller.sendToPlugins) icon=u':/slides/media_playback_pause.png',
controller.mediabar.addToolbarButton( tooltip=translate('OpenLP.SlideController', 'Pause playing media.'),
u'media_playback_stop', u':/slides/media_playback_stop.png', triggers=controller.sendToPlugins)
translate('OpenLP.SlideController', 'Stop playing media.'), controller.mediabar.addToolbarAction(u'playbackStop',
controller.sendToPlugins) text=u'media_playback_stop',
icon=u':/slides/media_playback_stop.png',
tooltip=translate('OpenLP.SlideController', 'Stop playing media.'),
triggers=controller.sendToPlugins)
# Build the seekSlider. # Build the seekSlider.
controller.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal) controller.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
controller.seekSlider.setMaximum(1000) controller.seekSlider.setMaximum(1000)
controller.seekSlider.setTracking(False)
controller.seekSlider.setToolTip(translate( controller.seekSlider.setToolTip(translate(
'OpenLP.SlideController', 'Video position.')) 'OpenLP.SlideController', 'Video position.'))
controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24)) controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
controller.seekSlider.setObjectName(u'seek_slider') controller.seekSlider.setObjectName(u'seekSlider')
controller.mediabar.addToolbarWidget(u'Seek Slider', controller.mediabar.addToolbarWidget(controller.seekSlider)
controller.seekSlider)
# Build the volumeSlider. # Build the volumeSlider.
controller.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal) controller.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
controller.volumeSlider.setTickInterval(10) controller.volumeSlider.setTickInterval(10)
controller.volumeSlider.setTickPosition(QtGui.QSlider.TicksAbove) controller.volumeSlider.setTickPosition(QtGui.QSlider.TicksAbove)
controller.volumeSlider.setMinimum(0) controller.volumeSlider.setMinimum(0)
controller.volumeSlider.setMaximum(100) controller.volumeSlider.setMaximum(100)
controller.volumeSlider.setTracking(True)
controller.volumeSlider.setToolTip(translate( controller.volumeSlider.setToolTip(translate(
'OpenLP.SlideController', 'Audio Volume.')) 'OpenLP.SlideController', 'Audio Volume.'))
controller.volumeSlider.setValue(controller.media_info.volume) controller.volumeSlider.setValue(controller.media_info.volume)
controller.volumeSlider.setGeometry(QtCore.QRect(90, 160, 221, 24)) controller.volumeSlider.setGeometry(QtCore.QRect(90, 160, 221, 24))
controller.volumeSlider.setObjectName(u'volume_slider') controller.volumeSlider.setObjectName(u'volumeSlider')
controller.mediabar.addToolbarWidget(u'Audio Volume', controller.mediabar.addToolbarWidget(controller.volumeSlider)
controller.volumeSlider)
control_panel.addWidget(controller.mediabar) control_panel.addWidget(controller.mediabar)
controller.mediabar.setVisible(False) controller.mediabar.setVisible(False)
# Signals # Signals
QtCore.QObject.connect(controller.seekSlider, QtCore.QObject.connect(controller.seekSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), controller.sendToPlugins) QtCore.SIGNAL(u'valueChanged(int)'), controller.sendToPlugins)
QtCore.QObject.connect(controller.volumeSlider, QtCore.QObject.connect(controller.volumeSlider,
QtCore.SIGNAL(u'sliderMoved(int)'), controller.sendToPlugins) QtCore.SIGNAL(u'valueChanged(int)'), controller.sendToPlugins)
def setup_special_controls(self, controller, control_panel): def setup_special_controls(self, controller, control_panel):
""" """
@ -276,6 +274,11 @@ class MediaController(object):
def set_controls_visible(self, controller, value): def set_controls_visible(self, controller, value):
# Generic controls # Generic controls
controller.mediabar.setVisible(value) controller.mediabar.setVisible(value)
if controller.isLive and controller.display:
if self.curDisplayMediaPlayer and value:
if self.curDisplayMediaPlayer[controller.display] != \
self.mediaPlayers[u'webkit']:
controller.display.setTransparency(False)
# Special controls: Here media type specific Controls will be enabled # Special controls: Here media type specific Controls will be enabled
# (e.g. for DVD control, ...) # (e.g. for DVD control, ...)
# TODO # TODO
@ -316,7 +319,8 @@ class MediaController(object):
controller.media_info.start_time = 0 controller.media_info.start_time = 0
controller.media_info.end_time = 0 controller.media_info.end_time = 0
else: else:
controller.media_info.start_time = display.serviceItem.start_time controller.media_info.start_time = \
display.serviceItem.start_time
controller.media_info.end_time = display.serviceItem.end_time controller.media_info.end_time = display.serviceItem.end_time
elif controller.previewDisplay: elif controller.previewDisplay:
display = controller.previewDisplay display = controller.previewDisplay
@ -353,13 +357,9 @@ class MediaController(object):
""" """
Select the correct media Player type from the prioritized Player list Select the correct media Player type from the prioritized Player list
""" """
playerSettings = str(QtCore.QSettings().value(u'media/players', usedPlayers, overriddenPlayer = get_media_players()
QtCore.QVariant(u'webkit')).toString()) if overriddenPlayer and overriddenPlayer != u'auto':
usedPlayers = playerSettings.split(u',') usedPlayers = [overriddenPlayer]
if QtCore.QSettings().value(u'media/override player',
QtCore.QVariant(QtCore.Qt.Unchecked)) == QtCore.Qt.Checked:
if self.overridenPlayer != '':
usedPlayers = [self.overridenPlayer]
if controller.media_info.file_info.isFile(): if controller.media_info.file_info.isFile():
suffix = u'*.%s' % \ suffix = u'*.%s' % \
controller.media_info.file_info.suffix().toLower() controller.media_info.file_info.suffix().toLower()
@ -443,6 +443,7 @@ class MediaController(object):
display.frame.evaluateJavaScript(u'show_blank("black");') display.frame.evaluateJavaScript(u'show_blank("black");')
self.curDisplayMediaPlayer[display].stop(display) self.curDisplayMediaPlayer[display].stop(display)
self.curDisplayMediaPlayer[display].set_visible(display, False) self.curDisplayMediaPlayer[display].set_visible(display, False)
controller.seekSlider.setSliderPosition(0)
def video_volume(self, msg): def video_volume(self, msg):
""" """
@ -478,6 +479,7 @@ class MediaController(object):
Responds to the request to reset a loaded video Responds to the request to reset a loaded video
""" """
log.debug(u'video_reset') log.debug(u'video_reset')
self.set_controls_visible(controller, False)
for display in self.curDisplayMediaPlayer.keys(): for display in self.curDisplayMediaPlayer.keys():
if display.controller == controller: if display.controller == controller:
display.override = {} display.override = {}
@ -486,7 +488,6 @@ class MediaController(object):
display.frame.evaluateJavaScript(u'show_video( \ display.frame.evaluateJavaScript(u'show_video( \
"setBackBoard", null, null, null,"hidden");') "setBackBoard", null, null, null,"hidden");')
del self.curDisplayMediaPlayer[display] del self.curDisplayMediaPlayer[display]
self.set_controls_visible(controller, False)
def video_hide(self, msg): def video_hide(self, msg):
""" """
@ -569,15 +570,6 @@ class MediaController(object):
video_list.append(item) video_list.append(item)
return video_list return video_list
def override_player(self, override_player):
playerSettings = str(QtCore.QSettings().value(u'media/players',
QtCore.QVariant(u'webkit')).toString())
usedPlayers = playerSettings.split(u',')
if override_player in usedPlayers:
self.overridenPlayer = override_player
else:
self.overridenPlayer = ''
def finalise(self): def finalise(self):
self.timer.stop() self.timer.stop()
for controller in self.controller: for controller in self.controller:

View File

@ -51,6 +51,7 @@ ADDITIONAL_EXT = {
u'video/x-matroska': [u'.mpv', u'.mkv'], u'video/x-matroska': [u'.mpv', u'.mkv'],
u'video/x-wmv': [u'.wmv'], u'video/x-wmv': [u'.wmv'],
u'video/x-mpg': [u'.mpg'], u'video/x-mpg': [u'.mpg'],
u'video/mpeg' : [u'.mp4', u'.mts'],
u'video/x-ms-wmv': [u'.wmv']} u'video/x-ms-wmv': [u'.wmv']}
@ -62,6 +63,8 @@ class PhononPlayer(MediaPlayer):
def __init__(self, parent): def __init__(self, parent):
MediaPlayer.__init__(self, parent, u'phonon') MediaPlayer.__init__(self, parent, u'phonon')
self.original_name = u'Phonon'
self.display_name = u'&Phonon'
self.parent = parent self.parent = parent
self.additional_extensions = ADDITIONAL_EXT self.additional_extensions = ADDITIONAL_EXT
mimetypes.init() mimetypes.init()
@ -189,6 +192,9 @@ class PhononPlayer(MediaPlayer):
display.phononWidget.setVisible(status) display.phononWidget.setVisible(status)
def update_ui(self, display): def update_ui(self, display):
if display.mediaObject.state() == Phonon.PausedState and \
self.state != MediaState.Paused:
self.stop(display)
controller = display.controller controller = display.controller
if controller.media_info.end_time > 0: if controller.media_info.end_time > 0:
if display.mediaObject.currentTime() > \ if display.mediaObject.currentTime() > \

5649
openlp/core/ui/media/vlc.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,224 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 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 #
###############################################################################
import logging
import sys, os
from datetime import datetime
try:
import vlc
vlc_available = bool(vlc.get_default_instance())
except (ImportError, NameError):
vlc_available = False
except OSError, e:
if sys.platform.startswith('win'):
if isinstance(e, WindowsError) and e.winerror == 126:
vlc_available = False
else:
raise
else:
raise
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver
from openlp.core.lib.mediaplayer import MediaPlayer
from openlp.core.ui.media import MediaState
log = logging.getLogger(__name__)
AUDIO_EXT = [
u'*.mp3'
, u'*.wav'
, u'*.ogg'
]
VIDEO_EXT = [
u'*.3gp'
, u'*.asf', u'*.wmv'
, u'*.au'
, u'*.avi'
, u'*.flv'
, u'*.mov'
, u'*.mp4'
, u'*.ogm'
, u'*.mkv', u'*.mka'
, u'*.ts', u'*.mpg'
, u'*.mpg', u'*.mp2'
, u'*.nsc'
, u'*.nsv'
, u'*.nut'
, u'*.ra', u'*.ram', u'*.rm', u'*.rv' ,u'*.rmbv'
, u'*.a52', u'*.dts', u'*.aac', u'*.flac' ,u'*.dv', u'*.vid'
, u'*.tta', u'*.tac'
, u'*.ty'
, u'*.dts'
, u'*.xa'
, u'*.iso'
, u'*.vob'
]
class VlcPlayer(MediaPlayer):
"""
A specialised version of the MediaPlayer class, which provides a VLC
display.
"""
def __init__(self, parent):
MediaPlayer.__init__(self, parent, u'vlc')
self.original_name = u'VLC'
self.display_name = u'&VLC'
self.parent = parent
self.canFolder = True
self.audio_extensions_list = AUDIO_EXT
self.video_extensions_list = VIDEO_EXT
def setup(self, display):
display.vlcWidget = QtGui.QFrame(display)
# creating a basic vlc instance
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',
QtCore.QVariant(False)).toBool() and \
display.controller.isLive:
command_line_options += u' --mouse-hide-timeout=0'
display.vlcInstance = vlc.Instance(command_line_options)
display.vlcInstance.set_log_verbosity(2)
# creating an empty vlc media player
display.vlcMediaPlayer = display.vlcInstance.media_player_new()
display.vlcWidget.resize(display.size())
display.vlcWidget.raise_()
display.vlcWidget.hide()
# the media player has to be 'connected' to the QFrame
# (otherwise a video would be displayed in it's own window)
# 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
display.vlcMediaPlayer.set_hwnd(int(display.vlcWidget.winId()))
elif sys.platform == "darwin": # for MacOS
display.vlcMediaPlayer.set_agl(int(display.vlcWidget.winId()))
else:
# for Linux using the X Server
display.vlcMediaPlayer.set_xwindow(int(display.vlcWidget.winId()))
self.hasOwnWidget = True
def check_available(self):
return vlc_available
def load(self, display):
log.debug(u'load vid in Vlc Controller')
controller = display.controller
volume = controller.media_info.volume
file_path = str(
controller.media_info.file_info.absoluteFilePath().toUtf8())
path = os.path.normcase(file_path)
# create the media
display.vlcMedia = display.vlcInstance.media_new_path(path)
# put the media in the media player
display.vlcMediaPlayer.set_media(display.vlcMedia)
# parse the metadata of the file
display.vlcMedia.parse()
self.volume(display, volume)
return True
def media_state_wait(self, display, mediaState):
"""
Wait for the video to change its state
Wait no longer than 60 seconds. (loading an iso file needs a long time)
"""
start = datetime.now()
while not mediaState == display.vlcMedia.get_state():
if display.vlcMedia.get_state() == vlc.State.Error:
return False
Receiver.send_message(u'openlp_process_events')
if (datetime.now() - start).seconds > 60:
return False
return True
def resize(self, display):
display.vlcWidget.resize(display.size())
def play(self, display):
controller = display.controller
start_time = 0
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:
return False
def pause(self, display):
if display.vlcMedia.get_state() != vlc.State.Playing:
return
display.vlcMediaPlayer.pause()
if self.media_state_wait(display, vlc.State.Paused):
self.state = MediaState.Paused
def stop(self, display):
display.vlcMediaPlayer.stop()
self.state = MediaState.Stopped
def volume(self, display, vol):
if display.hasAudio:
display.vlcMediaPlayer.audio_set_volume(vol)
def seek(self, display, seekVal):
if display.vlcMediaPlayer.is_seekable():
display.vlcMediaPlayer.set_time(seekVal)
def reset(self, display):
display.vlcMediaPlayer.stop()
display.vlcWidget.setVisible(False)
self.state = MediaState.Off
def set_visible(self, display, status):
if self.hasOwnWidget:
display.vlcWidget.setVisible(status)
def update_ui(self, display):
if display.vlcMedia.get_state() == vlc.State.Ended:
self.stop(display)
controller = display.controller
if controller.media_info.end_time > 0:
if display.vlcMediaPlayer.get_time() > \
controller.media_info.end_time * 1000:
self.stop(display)
self.set_visible(display, False)
if not controller.seekSlider.isSliderDown():
controller.seekSlider.setSliderPosition( \
display.vlcMediaPlayer.get_time())

View File

@ -134,6 +134,8 @@ VIDEO_JS = u"""
// doesnt work currently // doesnt work currently
vid.currentTime = varVal; vid.currentTime = varVal;
break; break;
case 'isEnded':
return vid.ended;
case 'setVisible': case 'setVisible':
vid.style.visibility = varVal; vid.style.visibility = varVal;
break; break;
@ -211,6 +213,8 @@ FLASH_JS = u"""
case 'seek': case 'seek':
// flashMovie.GotoFrame(varVal); // flashMovie.GotoFrame(varVal);
break; break;
case 'isEnded':
return false;//TODO check flash end
case 'setVisible': case 'setVisible':
text.style.visibility = varVal; text.style.visibility = varVal;
break; break;
@ -260,6 +264,8 @@ class WebkitPlayer(MediaPlayer):
def __init__(self, parent): def __init__(self, parent):
MediaPlayer.__init__(self, parent, u'webkit') MediaPlayer.__init__(self, parent, u'webkit')
self.original_name = u'WebKit'
self.display_name = u'&WebKit'
self.parent = parent self.parent = parent
self.canBackground = True self.canBackground = True
self.audio_extensions_list = AUDIO_EXT self.audio_extensions_list = AUDIO_EXT
@ -294,7 +300,7 @@ class WebkitPlayer(MediaPlayer):
def load(self, display): def load(self, display):
log.debug(u'load vid in Webkit Controller') log.debug(u'load vid in Webkit Controller')
controller = display.controller controller = display.controller
if display.hasAudio: if display.hasAudio and not controller.media_info.is_background:
volume = controller.media_info.volume volume = controller.media_info.volume
vol = float(volume) / float(100) vol = float(volume) / float(100)
else: else:
@ -354,7 +360,6 @@ class WebkitPlayer(MediaPlayer):
display.frame.evaluateJavaScript(u'show_flash("stop");') display.frame.evaluateJavaScript(u'show_flash("stop");')
else: else:
display.frame.evaluateJavaScript(u'show_video("stop");') display.frame.evaluateJavaScript(u'show_video("stop");')
controller.seekSlider.setSliderPosition(0)
self.state = MediaState.Stopped self.state = MediaState.Stopped
def volume(self, display, vol): def volume(self, display, vol):
@ -406,6 +411,9 @@ class WebkitPlayer(MediaPlayer):
length = display.frame.evaluateJavaScript( \ length = display.frame.evaluateJavaScript( \
u'show_flash("length");').toInt()[0] u'show_flash("length");').toInt()[0]
else: else:
if display.frame.evaluateJavaScript( \
u'show_video("isEnded");').toString() == 'true':
self.stop(display)
(currentTime, ok) = display.frame.evaluateJavaScript( \ (currentTime, ok) = display.frame.evaluateJavaScript( \
u'show_video("currentTime");').toFloat() u'show_video("currentTime");').toFloat()
# check if conversion was ok and value is not 'NaN' # check if conversion was ok and value is not 'NaN'

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -405,7 +405,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
# Only continue when we include the song's text. # Only continue when we include the song's text.
if not self.slideTextCheckBox.isChecked(): if not self.slideTextCheckBox.isChecked():
return return
for index, item in enumerate(self.serviceManager.serviceItems): for item in self.serviceManager.serviceItems:
# Trigger Audit requests # Trigger Audit requests
Receiver.send_message(u'print_service_started', Receiver.send_message(u'print_service_started',
[item[u'service_item']]) [item[u'service_item']])

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -222,6 +222,21 @@ class ScreenList(object):
log.debug(u'reset_current_display') log.debug(u'reset_current_display')
self.set_current_display(self.current[u'number']) self.set_current_display(self.current[u'number'])
def which_screen(self, window):
"""
Return the screen number that the centre of the passed window is in.
``window``
A QWidget we are finding the location of.
"""
x = window.x() + (window.width() / 2)
y = window.y() + (window.height() / 2)
for screen in self.screen_list:
size = screen[u'size']
if x >= size.x() and x <= (size.x() + size.width()) \
and y >= size.y() and y <= (size.y() + size.height()):
return screen[u'number']
def _load_screen_settings(self): def _load_screen_settings(self):
""" """
Loads the screen size and the monitor number from the settings. Loads the screen size and the monitor number from the settings.

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -31,6 +31,7 @@ import os
import shutil import shutil
import zipfile import zipfile
from tempfile import mkstemp from tempfile import mkstemp
from datetime import datetime, timedelta
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -40,11 +41,10 @@ from openlp.core.lib import OpenLPToolbar, ServiceItem, Receiver, build_icon, \
ItemCapabilities, SettingsManager, translate, str_to_bool ItemCapabilities, SettingsManager, translate, str_to_bool
from openlp.core.lib.theme import ThemeLevel from openlp.core.lib.theme import ThemeLevel
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
context_menu_action, context_menu_separator, find_and_set_in_combo_box create_widget_action, find_and_set_in_combo_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.ui.printserviceform import PrintServiceForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ from openlp.core.utils import AppLocation, delete_file, split_filename
split_filename
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
class ServiceManagerList(QtGui.QTreeWidget): class ServiceManagerList(QtGui.QTreeWidget):
@ -117,22 +117,23 @@ class ServiceManager(QtGui.QWidget):
self.layout.setMargin(0) self.layout.setMargin(0)
# Create the top toolbar # Create the top toolbar
self.toolbar = OpenLPToolbar(self) self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton( self.toolbar.addToolbarAction(u'newService',
UiStrings().NewService, u':/general/general_new.png', text=UiStrings().NewService, icon=u':/general/general_new.png',
UiStrings().CreateService, self.onNewServiceClicked) tooltip=UiStrings().CreateService,
self.toolbar.addToolbarButton( triggers=self.onNewServiceClicked)
UiStrings().OpenService, u':/general/general_open.png', self.toolbar.addToolbarAction(u'openService',
translate('OpenLP.ServiceManager', 'Load an existing service.'), text=UiStrings().OpenService, icon=u':/general/general_open.png',
self.onLoadServiceClicked) tooltip=translate('OpenLP.ServiceManager',
self.toolbar.addToolbarButton( 'Load an existing service.'), triggers=self.onLoadServiceClicked)
UiStrings().SaveService, u':/general/general_save.png', self.toolbar.addToolbarAction(u'saveService',
translate('OpenLP.ServiceManager', 'Save this service.'), text=UiStrings().SaveService, icon=u':/general/general_save.png',
self.saveFile) tooltip=translate('OpenLP.ServiceManager', 'Save this service.'),
triggers=self.saveFile)
self.toolbar.addSeparator() self.toolbar.addSeparator()
self.themeLabel = QtGui.QLabel(u'%s:' % UiStrings().Theme, self) self.themeLabel = QtGui.QLabel(u'%s:' % UiStrings().Theme, self)
self.themeLabel.setMargin(3) self.themeLabel.setMargin(3)
self.themeLabel.setObjectName(u'themeLabel') self.themeLabel.setObjectName(u'themeLabel')
self.toolbar.addToolbarWidget(u'ThemeLabel', self.themeLabel) self.toolbar.addToolbarWidget(self.themeLabel)
self.themeComboBox = QtGui.QComboBox(self.toolbar) self.themeComboBox = QtGui.QComboBox(self.toolbar)
self.themeComboBox.setToolTip(translate('OpenLP.ServiceManager', self.themeComboBox.setToolTip(translate('OpenLP.ServiceManager',
'Select a theme for the service.')) 'Select a theme for the service.'))
@ -141,7 +142,7 @@ class ServiceManager(QtGui.QWidget):
self.themeComboBox.setSizePolicy( self.themeComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed) QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.themeComboBox.setObjectName(u'themeComboBox') self.themeComboBox.setObjectName(u'themeComboBox')
self.toolbar.addToolbarWidget(u'ThemeWidget', self.themeComboBox) self.toolbar.addToolbarWidget(self.themeComboBox)
self.toolbar.setObjectName(u'toolbar') self.toolbar.setObjectName(u'toolbar')
self.layout.addWidget(self.toolbar) self.layout.addWidget(self.toolbar)
# Create the service manager list # Create the service manager list
@ -168,99 +169,77 @@ class ServiceManager(QtGui.QWidget):
self.layout.addWidget(self.serviceManagerList) self.layout.addWidget(self.serviceManagerList)
# Add the bottom toolbar # Add the bottom toolbar
self.orderToolbar = OpenLPToolbar(self) self.orderToolbar = OpenLPToolbar(self)
self.serviceManagerList.moveTop = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Move to &top'),
u':/services/service_top.png',
translate('OpenLP.ServiceManager',
'Move item to the top of the service.'),
self.onServiceTop, shortcuts=[QtCore.Qt.Key_Home])
self.serviceManagerList.moveTop.setObjectName(u'moveTop')
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_category( action_list.add_category(
unicode(UiStrings().Service), CategoryOrder.standardToolbar) unicode(UiStrings().Service), CategoryOrder.standardToolbar)
action_list.add_action( self.serviceManagerList.moveTop = self.orderToolbar.addToolbarAction(
self.serviceManagerList.moveTop, unicode(UiStrings().Service)) u'moveTop', text=translate('OpenLP.ServiceManager', 'Move to &top'),
self.serviceManagerList.moveUp = self.orderToolbar.addToolbarButton( icon=u':/services/service_top.png', tooltip=translate(
translate('OpenLP.ServiceManager', 'Move &up'), 'OpenLP.ServiceManager', 'Move item to the top of the service.'),
u':/services/service_up.png', shortcuts=[QtCore.Qt.Key_Home], category=UiStrings().Service,
translate('OpenLP.ServiceManager', triggers=self.onServiceTop)
self.serviceManagerList.moveUp = self.orderToolbar.addToolbarAction(
u'moveUp', text=translate('OpenLP.ServiceManager', 'Move &up'),
icon=u':/services/service_up.png',
tooltip=translate( 'OpenLP.ServiceManager',
'Move item up one position in the service.'), 'Move item up one position in the service.'),
self.onServiceUp, shortcuts=[QtCore.Qt.Key_PageUp]) shortcuts=[QtCore.Qt.Key_PageUp], category=UiStrings().Service,
self.serviceManagerList.moveUp.setObjectName(u'moveUp') triggers=self.onServiceUp)
action_list.add_action( self.serviceManagerList.moveDown = self.orderToolbar.addToolbarAction(
self.serviceManagerList.moveUp, unicode(UiStrings().Service)) u'moveDown', text=translate('OpenLP.ServiceManager', 'Move &down'),
self.serviceManagerList.moveDown = self.orderToolbar.addToolbarButton( icon=u':/services/service_down.png',
translate('OpenLP.ServiceManager', 'Move &down'), tooltip=translate('OpenLP.ServiceManager',
u':/services/service_down.png',
translate('OpenLP.ServiceManager',
'Move item down one position in the service.'), 'Move item down one position in the service.'),
self.onServiceDown, shortcuts=[QtCore.Qt.Key_PageDown]) shortcuts=[QtCore.Qt.Key_PageDown], category=UiStrings().Service,
self.serviceManagerList.moveDown.setObjectName(u'moveDown') triggers=self.onServiceDown)
action_list.add_action( self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarAction(
self.serviceManagerList.moveDown, unicode(UiStrings().Service)) u'moveBottom',
self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarButton( text=translate('OpenLP.ServiceManager', 'Move to &bottom'),
translate('OpenLP.ServiceManager', 'Move to &bottom'), icon=u':/services/service_bottom.png', tooltip=translate(
u':/services/service_bottom.png', 'OpenLP.ServiceManager', 'Move item to the end of the service.'),
translate('OpenLP.ServiceManager', shortcuts=[QtCore.Qt.Key_End], category=UiStrings().Service,
'Move item to the end of the service.'), triggers=self.onServiceEnd)
self.onServiceEnd, shortcuts=[QtCore.Qt.Key_End]) self.serviceManagerList.down = self.orderToolbar.addToolbarAction(
self.serviceManagerList.moveBottom.setObjectName(u'moveBottom') u'down', text=translate('OpenLP.ServiceManager', 'Move &down'),
action_list.add_action( tooltip=translate('OpenLP.ServiceManager',
self.serviceManagerList.moveBottom, unicode(UiStrings().Service)) 'Moves the selection down the window.'), visible=False,
self.serviceManagerList.down = self.orderToolbar.addToolbarButton( shortcuts=[QtCore.Qt.Key_Down], triggers=self.onMoveSelectionDown)
translate('OpenLP.ServiceManager', 'Move &down'),
None,
translate('OpenLP.ServiceManager',
'Moves the selection down the window.'),
self.onMoveSelectionDown, shortcuts=[QtCore.Qt.Key_Down])
self.serviceManagerList.down.setObjectName(u'down')
action_list.add_action(self.serviceManagerList.down) action_list.add_action(self.serviceManagerList.down)
self.serviceManagerList.down.setVisible(False) self.serviceManagerList.up = self.orderToolbar.addToolbarAction(
self.serviceManagerList.up = self.orderToolbar.addToolbarButton( u'up', text=translate('OpenLP.ServiceManager', 'Move up'),
translate('OpenLP.ServiceManager', 'Move up'), tooltip=translate('OpenLP.ServiceManager',
None, 'Moves the selection up the window.'), visible=False,
translate('OpenLP.ServiceManager', shortcuts=[QtCore.Qt.Key_Up], triggers=self.onMoveSelectionUp)
'Moves the selection up the window.'),
self.onMoveSelectionUp, shortcuts=[QtCore.Qt.Key_Up])
self.serviceManagerList.up.setObjectName(u'up')
action_list.add_action(self.serviceManagerList.up) action_list.add_action(self.serviceManagerList.up)
self.serviceManagerList.up.setVisible(False)
self.orderToolbar.addSeparator() self.orderToolbar.addSeparator()
self.serviceManagerList.delete = self.orderToolbar.addToolbarButton( self.serviceManagerList.delete = self.orderToolbar.addToolbarAction(
translate('OpenLP.ServiceManager', '&Delete From Service'), u'delete',
u':/general/general_delete.png', text=translate('OpenLP.ServiceManager', '&Delete From Service'),
translate('OpenLP.ServiceManager', icon=u':/general/general_delete.png',
tooltip=translate('OpenLP.ServiceManager',
'Delete the selected item from the service.'), 'Delete the selected item from the service.'),
self.onDeleteFromService) triggers=self.onDeleteFromService)
self.orderToolbar.addSeparator() self.orderToolbar.addSeparator()
self.serviceManagerList.expand = self.orderToolbar.addToolbarButton( self.serviceManagerList.expand = self.orderToolbar.addToolbarAction(
translate('OpenLP.ServiceManager', '&Expand all'), u'expand', text=translate('OpenLP.ServiceManager', '&Expand all'),
u':/services/service_expand_all.png', icon=u':/services/service_expand_all.png', tooltip=translate(
translate('OpenLP.ServiceManager', 'OpenLP.ServiceManager', 'Expand all the service items.'),
'Expand all the service items.'), shortcuts=[QtCore.Qt.Key_Plus], category=UiStrings().Service,
self.onExpandAll, shortcuts=[QtCore.Qt.Key_Plus]) triggers=self.onExpandAll)
self.serviceManagerList.expand.setObjectName(u'expand') self.serviceManagerList.collapse = self.orderToolbar.addToolbarAction(
action_list.add_action( u'collapse',
self.serviceManagerList.expand, unicode(UiStrings().Service)) text=translate('OpenLP.ServiceManager', '&Collapse all'),
self.serviceManagerList.collapse = self.orderToolbar.addToolbarButton( icon=u':/services/service_collapse_all.png', tooltip=translate(
translate('OpenLP.ServiceManager', '&Collapse all'), 'OpenLP.ServiceManager', 'Collapse all the service items.'),
u':/services/service_collapse_all.png', shortcuts=[QtCore.Qt.Key_Minus], category=UiStrings().Service,
translate('OpenLP.ServiceManager', triggers=self.onCollapseAll)
'Collapse all the service items.'),
self.onCollapseAll, shortcuts=[QtCore.Qt.Key_Minus])
self.serviceManagerList.collapse.setObjectName(u'collapse')
action_list.add_action(
self.serviceManagerList.collapse, unicode(UiStrings().Service))
self.orderToolbar.addSeparator() self.orderToolbar.addSeparator()
self.serviceManagerList.makeLive = self.orderToolbar.addToolbarButton( self.serviceManagerList.makeLive = self.orderToolbar.addToolbarAction(
translate('OpenLP.ServiceManager', 'Go Live'), u'makeLive', text=translate('OpenLP.ServiceManager', 'Go Live'),
u':/general/general_live.png', icon=u':/general/general_live.png', tooltip=translate(
translate('OpenLP.ServiceManager', 'OpenLP.ServiceManager', 'Send the selected item to Live.'),
'Send the selected item to Live.'), self.makeLive, shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return],
shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]) category=UiStrings().Service, triggers=self.makeLive)
self.serviceManagerList.makeLive.setObjectName(u'orderToolbar')
action_list.add_action(
self.serviceManagerList.makeLive, unicode(UiStrings().Service))
self.layout.addWidget(self.orderToolbar) self.layout.addWidget(self.orderToolbar)
# Connect up our signals and slots # Connect up our signals and slots
QtCore.QObject.connect(self.themeComboBox, QtCore.QObject.connect(self.themeComboBox,
@ -305,34 +284,32 @@ class ServiceManager(QtGui.QWidget):
self.addToAction.setIcon(build_icon(u':/general/general_edit.png')) self.addToAction.setIcon(build_icon(u':/general/general_edit.png'))
# build the context menu # build the context menu
self.menu = QtGui.QMenu() self.menu = QtGui.QMenu()
self.editAction = context_menu_action( self.editAction = create_widget_action(self.menu,
self.menu, u':/general/general_edit.png', text=translate('OpenLP.ServiceManager', '&Edit Item'),
translate('OpenLP.ServiceManager', '&Edit Item'), self.remoteEdit) icon=u':/general/general_edit.png', triggers=self.remoteEdit)
self.maintainAction = context_menu_action( self.maintainAction = create_widget_action(self.menu,
self.menu, u':/general/general_edit.png', text=translate('OpenLP.ServiceManager', '&Reorder Item'),
translate('OpenLP.ServiceManager', '&Reorder Item'), icon=u':/general/general_edit.png',
self.onServiceItemEditForm) triggers=self.onServiceItemEditForm)
self.notesAction = context_menu_action( self.notesAction = create_widget_action(self.menu,
self.menu, u':/services/service_notes.png', text=translate('OpenLP.ServiceManager', '&Notes'),
translate('OpenLP.ServiceManager', '&Notes'), icon=u':/services/service_notes.png',
self.onServiceItemNoteForm) triggers=self.onServiceItemNoteForm)
self.timeAction = context_menu_action( self.timeAction = create_widget_action(self.menu,
self.menu, u':/media/media_time.png', text=translate('OpenLP.ServiceManager', '&Start Time'),
translate('OpenLP.ServiceManager', '&Start Time'), icon=u':/media/media_time.png', triggers=self.onStartTimeForm)
self.onStartTimeForm) self.deleteAction = create_widget_action(self.menu,
self.deleteAction = context_menu_action( text=translate('OpenLP.ServiceManager', '&Delete From Service'),
self.menu, u':/general/general_delete.png', icon=u':/general/general_delete.png',
translate('OpenLP.ServiceManager', '&Delete From Service'), triggers=self.onDeleteFromService)
self.onDeleteFromService) self.menu.addSeparator()
context_menu_separator(self.menu) self.previewAction = create_widget_action(self.menu,
self.previewAction = context_menu_action( text=translate('OpenLP.ServiceManager', 'Show &Preview'),
self.menu, u':/general/general_preview.png', icon=u':/general/general_preview.png', triggers=self.makePreview)
translate('OpenLP.ServiceManager', 'Show &Preview'), self.liveAction = create_widget_action(self.menu,
self.makePreview) text=translate('OpenLP.ServiceManager', 'Show &Live'),
self.liveAction = context_menu_action( icon=u':/general/general_live.png', triggers=self.makeLive)
self.menu, u':/general/general_live.png', self.menu.addSeparator()
translate('OpenLP.ServiceManager', 'Show &Live'), self.makeLive)
context_menu_separator(self.menu)
self.themeMenu = QtGui.QMenu( self.themeMenu = QtGui.QMenu(
translate('OpenLP.ServiceManager', '&Change Item Theme')) translate('OpenLP.ServiceManager', '&Change Item Theme'))
self.menu.addMenu(self.themeMenu) self.menu.addMenu(self.themeMenu)
@ -484,7 +461,7 @@ class ServiceManager(QtGui.QWidget):
log.debug(temp_file_name) log.debug(temp_file_name)
path_file_name = unicode(self.fileName()) path_file_name = unicode(self.fileName())
path, file_name = os.path.split(path_file_name) path, file_name = os.path.split(path_file_name)
basename, extension = os.path.splitext(file_name) basename = os.path.splitext(file_name)[0]
service_file_name = '%s.osd' % basename service_file_name = '%s.osd' % basename
log.debug(u'ServiceManager.saveFile - %s', path_file_name) log.debug(u'ServiceManager.saveFile - %s', path_file_name)
SettingsManager.set_last_dir( SettingsManager.set_last_dir(
@ -506,8 +483,7 @@ class ServiceManager(QtGui.QWidget):
for i, filename in \ for i, filename in \
enumerate(service_item[u'header'][u'background_audio']): enumerate(service_item[u'header'][u'background_audio']):
new_file = os.path.join(u'audio', new_file = os.path.join(u'audio',
item[u'service_item']._uuid, item[u'service_item']._uuid, filename)
os.path.split(filename)[1])
audio_files.append((filename, new_file)) audio_files.append((filename, new_file))
service_item[u'header'][u'background_audio'][i] = new_file service_item[u'header'][u'background_audio'][i] = new_file
# Add the service item to the service. # Add the service item to the service.
@ -596,7 +572,10 @@ class ServiceManager(QtGui.QWidget):
self.mainwindow.finishedProgressBar() self.mainwindow.finishedProgressBar()
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
if success: if success:
try:
shutil.copy(temp_file_name, path_file_name) shutil.copy(temp_file_name, path_file_name)
except:
return self.saveFileAs()
self.mainwindow.addRecentFile(path_file_name) self.mainwindow.addRecentFile(path_file_name)
self.setModified(False) self.setModified(False)
try: try:
@ -610,10 +589,39 @@ class ServiceManager(QtGui.QWidget):
Get a file name and then call :func:`ServiceManager.saveFile` to Get a file name and then call :func:`ServiceManager.saveFile` to
save the file. save the file.
""" """
default_service_enabled = QtCore.QSettings().value(
u'advanced/default service enabled', QtCore.QVariant(True)).toBool()
if default_service_enabled:
service_day = QtCore.QSettings().value(
u'advanced/default service day', 7).toInt()[0]
if service_day == 7:
time = datetime.now()
else:
service_hour = QtCore.QSettings().value(
u'advanced/default service hour', 11).toInt()[0]
service_minute = QtCore.QSettings().value(
u'advanced/default service minute', 0).toInt()[0]
now = datetime.now()
day_delta = service_day - now.weekday()
if day_delta < 0:
day_delta += 7
time = now + timedelta(days=day_delta)
time = time.replace(hour=service_hour, minute=service_minute)
default_pattern = unicode(QtCore.QSettings().value(
u'advanced/default service name',
translate('OpenLP.AdvancedTab', 'Service %Y-%m-%d %H-%M',
'This may not contain any of the following characters: '
'/\\?*|<>\[\]":+\nSee http://docs.python.org/library/'
'datetime.html#strftime-strptime-behavior for more '
'information.')).toString())
default_filename = time.strftime(default_pattern)
else:
default_filename = u''
directory = unicode(SettingsManager.get_last_dir(
self.mainwindow.servicemanagerSettingsSection))
path = os.path.join(directory, default_filename)
fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow, fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow,
UiStrings().SaveService, UiStrings().SaveService, path,
SettingsManager.get_last_dir(
self.mainwindow.servicemanagerSettingsSection),
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))
if not fileName: if not fileName:
return False return False
@ -636,14 +644,17 @@ class ServiceManager(QtGui.QWidget):
try: try:
zip = zipfile.ZipFile(fileName) zip = zipfile.ZipFile(fileName)
for zipinfo in zip.infolist(): for zipinfo in zip.infolist():
ucsfile = file_is_unicode(zipinfo.filename) try:
if not ucsfile: ucsfile = zipinfo.filename.decode(u'utf-8')
except UnicodeDecodeError:
log.exception(u'Filename "%s" is not valid UTF-8' %
zipinfo.filename.decode(u'utf-8', u'replace'))
critical_error_message_box( critical_error_message_box(
message=translate('OpenLP.ServiceManager', message=translate('OpenLP.ServiceManager',
'File is not a valid service.\n' 'File is not a valid service.\n'
'The content encoding is not UTF-8.')) 'The content encoding is not UTF-8.'))
continue continue
osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) osfile = ucsfile.replace(u'/', os.path.sep)
if not osfile.startswith(u'audio'): if not osfile.startswith(u'audio'):
osfile = os.path.split(osfile)[1] osfile = os.path.split(osfile)[1]
log.debug(u'Extract file: %s', osfile) log.debug(u'Extract file: %s', osfile)
@ -821,7 +832,7 @@ class ServiceManager(QtGui.QWidget):
lookFor = 1 lookFor = 1
serviceIterator += 1 serviceIterator += 1
def previousItem(self): def previousItem(self, message):
""" """
Called by the SlideController to select the previous service item. Called by the SlideController to select the previous service item.
""" """
@ -829,15 +840,26 @@ class ServiceManager(QtGui.QWidget):
return return
selected = self.serviceManagerList.selectedItems()[0] selected = self.serviceManagerList.selectedItems()[0]
prevItem = None prevItem = None
prevItemLastSlide = None
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList) serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
while serviceIterator.value(): while serviceIterator.value():
if serviceIterator.value() == selected: if serviceIterator.value() == selected:
if prevItem: if message == u'last slide' and prevItemLastSlide:
pos = prevItem.data(0, QtCore.Qt.UserRole).toInt()[0]
check_expanded = self.serviceItems[pos - 1][u'expanded']
self.serviceManagerList.setCurrentItem(prevItemLastSlide)
if not check_expanded:
self.serviceManagerList.collapseItem(prevItem)
self.makeLive()
self.serviceManagerList.setCurrentItem(prevItem)
elif prevItem:
self.serviceManagerList.setCurrentItem(prevItem) self.serviceManagerList.setCurrentItem(prevItem)
self.makeLive() self.makeLive()
return return
if serviceIterator.value().parent() is None: if serviceIterator.value().parent() is None:
prevItem = serviceIterator.value() prevItem = serviceIterator.value()
if serviceIterator.value().parent() is prevItem:
prevItemLastSlide = serviceIterator.value()
serviceIterator += 1 serviceIterator += 1
def onSetItem(self, message): def onSetItem(self, message):
@ -1092,12 +1114,9 @@ class ServiceManager(QtGui.QWidget):
sure the theme combo box is in the correct state. sure the theme combo box is in the correct state.
""" """
log.debug(u'themeChange') log.debug(u'themeChange')
if self.mainwindow.renderer.theme_level == ThemeLevel.Global: visible = self.mainwindow.renderer.theme_level == ThemeLevel.Global
self.toolbar.actions[u'ThemeLabel'].setVisible(False) self.themeLabel.setVisible(visible)
self.toolbar.actions[u'ThemeWidget'].setVisible(False) self.themeComboBox.setVisible(visible)
else:
self.toolbar.actions[u'ThemeLabel'].setVisible(True)
self.toolbar.actions[u'ThemeWidget'].setVisible(True)
def regenerateServiceItems(self): def regenerateServiceItems(self):
""" """
@ -1334,15 +1353,15 @@ class ServiceManager(QtGui.QWidget):
Handle of the event pint passed Handle of the event pint passed
""" """
link = event.mimeData() link = event.mimeData()
if event.mimeData().hasUrls(): if link.hasUrls():
event.setDropAction(QtCore.Qt.CopyAction) event.setDropAction(QtCore.Qt.CopyAction)
event.accept() event.accept()
for url in event.mimeData().urls(): for url in link.urls():
filename = unicode(url.toLocalFile()) filename = unicode(url.toLocalFile())
if filename.endswith(u'.osz'): if filename.endswith(u'.osz'):
self.onLoadServiceClicked(filename) self.onLoadServiceClicked(filename)
elif event.mimeData().hasText(): elif link.hasText():
plugin = unicode(event.mimeData().text()) plugin = unicode(link.text())
item = self.serviceManagerList.itemAt(event.pos()) item = self.serviceManagerList.itemAt(event.pos())
# ServiceManager started the drag and drop # ServiceManager started the drag and drop
if plugin == u'ServiceManager': if plugin == u'ServiceManager':
@ -1399,19 +1418,16 @@ class ServiceManager(QtGui.QWidget):
themeGroup.setObjectName(u'themeGroup') themeGroup.setObjectName(u'themeGroup')
# Create a "Default" theme, which allows the user to reset the item's # Create a "Default" theme, which allows the user to reset the item's
# theme to the service theme or global theme. # theme to the service theme or global theme.
defaultTheme = context_menu_action(self.themeMenu, None, defaultTheme = create_widget_action(self.themeMenu,
UiStrings().Default, self.onThemeChangeAction) text=UiStrings().Default, checked=False,
defaultTheme.setCheckable(True) triggers=self.onThemeChangeAction)
self.themeMenu.setDefaultAction(defaultTheme) self.themeMenu.setDefaultAction(defaultTheme)
themeGroup.addAction(defaultTheme) themeGroup.addAction(defaultTheme)
context_menu_separator(self.themeMenu) self.themeMenu.addSeparator()
for theme in theme_list: for theme in theme_list:
self.themeComboBox.addItem(theme) self.themeComboBox.addItem(theme)
themeAction = context_menu_action(self.themeMenu, None, theme, themeGroup.addAction(create_widget_action(self.themeMenu, theme,
self.onThemeChangeAction) text=theme, checked=False, triggers=self.onThemeChangeAction))
themeAction.setObjectName(theme)
themeAction.setCheckable(True)
themeGroup.addAction(themeAction)
find_and_set_in_combo_box(self.themeComboBox, self.service_theme) find_and_set_in_combo_box(self.themeComboBox, self.service_theme)
self.mainwindow.renderer.set_service_theme(self.service_theme) self.mainwindow.renderer.set_service_theme(self.service_theme)
self.regenerateServiceItems() self.regenerateServiceItems()

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -57,7 +57,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
def exec_(self): def exec_(self):
# load all the settings # load all the settings
self.settingListWidget.clear() self.settingListWidget.clear()
for tabIndex in range(0, self.stackedLayout.count() + 1): while self.stackedLayout.count():
# take at 0 and the rest shuffle up. # take at 0 and the rest shuffle up.
self.stackedLayout.takeAt(0) self.stackedLayout.takeAt(0)
self.insertTab(self.generalTab, 0, PluginStatus.Active) self.insertTab(self.generalTab, 0, PluginStatus.Active)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -344,8 +344,11 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
if category.name is None: if category.name is None:
continue continue
for action in category.actions: for action in category.actions:
if self.changedActions .has_key(action): if action in self.changedActions:
old_shortcuts = map(unicode,
map(QtGui.QKeySequence.toString, action.shortcuts()))
action.setShortcuts(self.changedActions[action]) action.setShortcuts(self.changedActions[action])
self.action_list.update_shortcut_map(action, old_shortcuts)
settings.setValue( settings.setValue(
action.objectName(), QtCore.QVariant(action.shortcuts())) action.objectName(), QtCore.QVariant(action.shortcuts()))
settings.endGroup() settings.endGroup()
@ -452,7 +455,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
those shortcuts which are not saved yet but already assigned (as changes those shortcuts which are not saved yet but already assigned (as changes
are applied when closing the dialog). are applied when closing the dialog).
""" """
if self.changedActions.has_key(action): if action in self.changedActions:
return self.changedActions[action] return self.changedActions[action]
return action.shortcuts() return action.shortcuts()

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -33,8 +33,9 @@ from collections import deque
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \ from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
translate, build_icon, ServiceItem, build_html, PluginManager, ServiceItem translate, build_icon, build_html, PluginManager, ServiceItem
from openlp.core.lib.ui import UiStrings, shortcut_action from openlp.core.lib.ui import UiStrings, create_action
from openlp.core.lib import SlideLimits, ServiceItemAction
from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList
from openlp.core.utils.actions import ActionList, CategoryOrder from openlp.core.utils.actions import ActionList, CategoryOrder
@ -45,9 +46,10 @@ class SlideList(QtGui.QTableWidget):
Customised version of QTableWidget which can respond to keyboard Customised version of QTableWidget which can respond to keyboard
events. events.
""" """
def __init__(self, parent=None, name=None): def __init__(self, parent=None):
QtGui.QTableWidget.__init__(self, parent.controller) QtGui.QTableWidget.__init__(self, parent.controller)
class Controller(QtGui.QWidget): class Controller(QtGui.QWidget):
""" """
Controller is a general controller widget. Controller is a general controller widget.
@ -82,26 +84,29 @@ class SlideController(Controller):
""" """
Controller.__init__(self, parent, isLive) Controller.__init__(self, parent, isLive)
self.screens = ScreenList.get_instance() self.screens = ScreenList.get_instance()
try:
self.ratio = float(self.screens.current[u'size'].width()) / \ self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height()) float(self.screens.current[u'size'].height())
except ZeroDivisionError:
self.ratio = 1
self.imageManager = self.parent().imageManager self.imageManager = self.parent().imageManager
self.mediaController = self.parent().mediaController self.mediaController = self.parent().mediaController
self.loopList = [ self.loopList = [
u'Play Slides Menu', u'playSlidesMenu',
u'Loop Separator', u'loopSeparator',
u'Image SpinBox' u'delaySpinBox'
] ]
self.songEditList = [ self.audioList = [
u'Edit Song', u'songMenu',
] u'audioPauseItem',
self.nextPreviousList = [ u'audioTimeLabel'
u'Previous Slide',
u'Next Slide'
] ]
self.timer_id = 0 self.timer_id = 0
self.songEdit = False self.songEdit = False
self.selectedRow = 0 self.selectedRow = 0
self.serviceItem = None self.serviceItem = None
self.slide_limits = None
self.updateSlideLimits()
self.panel = QtGui.QWidget(parent.controlSplitter) self.panel = QtGui.QWidget(parent.controlSplitter)
self.slideList = {} self.slideList = {}
# Layout for holding panel # Layout for holding panel
@ -116,10 +121,14 @@ class SlideController(Controller):
self.typePrefix = u'live' self.typePrefix = u'live'
self.keypress_queue = deque() self.keypress_queue = deque()
self.keypress_loop = False self.keypress_loop = False
self.category = UiStrings().LiveToolbar
ActionList.get_instance().add_category(
unicode(self.category), CategoryOrder.standardToolbar)
else: else:
self.typeLabel.setText(UiStrings().Preview) self.typeLabel.setText(UiStrings().Preview)
self.split = 0 self.split = 0
self.typePrefix = u'preview' self.typePrefix = u'preview'
self.category = None
self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;') self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;')
self.typeLabel.setAlignment(QtCore.Qt.AlignCenter) self.typeLabel.setAlignment(QtCore.Qt.AlignCenter)
self.panelLayout.addWidget(self.typeLabel) self.panelLayout.addWidget(self.typeLabel)
@ -162,72 +171,71 @@ class SlideController(Controller):
sizeToolbarPolicy.setHeightForWidth( sizeToolbarPolicy.setHeightForWidth(
self.toolbar.sizePolicy().hasHeightForWidth()) self.toolbar.sizePolicy().hasHeightForWidth())
self.toolbar.setSizePolicy(sizeToolbarPolicy) self.toolbar.setSizePolicy(sizeToolbarPolicy)
self.previousItem = self.toolbar.addToolbarButton( self.previousItem = create_action(self,
u'Previous Slide', u'previousItem_' + self.typePrefix,
u':/slides/slide_previous.png', text=translate('OpenLP.SlideController', 'Previous Slide'),
translate('OpenLP.SlideController', 'Move to previous.'), icon=u':/slides/slide_previous.png',
self.onSlideSelectedPrevious, tooltip=translate('OpenLP.SlideController', 'Move to previous.'),
shortcuts=[QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp], shortcuts=[QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp],
context=QtCore.Qt.WidgetWithChildrenShortcut) context=QtCore.Qt.WidgetWithChildrenShortcut,
self.nextItem = self.toolbar.addToolbarButton( category=self.category, triggers=self.onSlideSelectedPrevious)
u'Next Slide', self.toolbar.addAction(self.previousItem)
u':/slides/slide_next.png', self.nextItem = create_action(self, u'nextItem_' + self.typePrefix,
translate('OpenLP.SlideController', 'Move to next.'), text=translate('OpenLP.SlideController', 'Next Slide'),
self.onSlideSelectedNext, icon=u':/slides/slide_next.png',
tooltip=translate('OpenLP.SlideController', 'Move to next.'),
shortcuts=[QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown], shortcuts=[QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown],
context=QtCore.Qt.WidgetWithChildrenShortcut) context=QtCore.Qt.WidgetWithChildrenShortcut,
self.toolbar.addToolbarSeparator(u'Close Separator') category=self.category, triggers=self.onSlideSelectedNextAction)
self.toolbar.addAction(self.nextItem)
self.toolbar.addSeparator()
if self.isLive: if self.isLive:
# Hide Menu # Hide Menu
self.hideMenu = QtGui.QToolButton(self.toolbar) self.hideMenu = QtGui.QToolButton(self.toolbar)
self.hideMenu.setObjectName(u'hideMenu')
self.hideMenu.setText(translate('OpenLP.SlideController', 'Hide')) self.hideMenu.setText(translate('OpenLP.SlideController', 'Hide'))
self.hideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) self.hideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
self.toolbar.addToolbarWidget(u'Hide Menu', self.hideMenu)
self.hideMenu.setMenu(QtGui.QMenu( self.hideMenu.setMenu(QtGui.QMenu(
translate('OpenLP.SlideController', 'Hide'), self.toolbar)) translate('OpenLP.SlideController', 'Hide'), self.toolbar))
self.blankScreen = shortcut_action(self.hideMenu, u'blankScreen', self.toolbar.addToolbarWidget(self.hideMenu)
[QtCore.Qt.Key_Period], self.onBlankDisplay, self.blankScreen = create_action(self, u'blankScreen',
u':/slides/slide_blank.png', False, text=translate('OpenLP.SlideController', 'Blank Screen'),
unicode(UiStrings().LiveToolbar)) icon=u':/slides/slide_blank.png', checked=False,
self.blankScreen.setText( shortcuts=[QtCore.Qt.Key_Period],
translate('OpenLP.SlideController', 'Blank Screen')) category=self.category, triggers=self.onBlankDisplay)
self.themeScreen = shortcut_action(self.hideMenu, u'themeScreen', self.themeScreen = create_action(self, u'themeScreen',
[QtGui.QKeySequence(u'T')], self.onThemeDisplay, text=translate('OpenLP.SlideController', 'Blank to Theme'),
u':/slides/slide_theme.png', False, icon=u':/slides/slide_theme.png', checked=False,
unicode(UiStrings().LiveToolbar)) shortcuts=[QtGui.QKeySequence(u'T')],
self.themeScreen.setText( category=self.category, triggers=self.onThemeDisplay)
translate('OpenLP.SlideController', 'Blank to Theme')) self.desktopScreen = create_action(self, u'desktopScreen',
self.desktopScreen = shortcut_action(self.hideMenu, text=translate('OpenLP.SlideController', 'Show Desktop'),
u'desktopScreen', [QtGui.QKeySequence(u'D')], icon=u':/slides/slide_desktop.png', checked=False,
self.onHideDisplay, u':/slides/slide_desktop.png', False, shortcuts=[QtGui.QKeySequence(u'D')],
unicode(UiStrings().LiveToolbar)) category=self.category, triggers=self.onHideDisplay)
self.desktopScreen.setText(
translate('OpenLP.SlideController', 'Show Desktop'))
self.hideMenu.setDefaultAction(self.blankScreen) self.hideMenu.setDefaultAction(self.blankScreen)
self.hideMenu.menu().addAction(self.blankScreen) self.hideMenu.menu().addAction(self.blankScreen)
self.hideMenu.menu().addAction(self.themeScreen) self.hideMenu.menu().addAction(self.themeScreen)
self.hideMenu.menu().addAction(self.desktopScreen) self.hideMenu.menu().addAction(self.desktopScreen)
self.toolbar.addToolbarSeparator(u'Loop Separator') self.toolbar.addToolbarAction(u'loopSeparator', separator=True)
# Play Slides Menu # Play Slides Menu
self.playSlidesMenu = QtGui.QToolButton(self.toolbar) self.playSlidesMenu = QtGui.QToolButton(self.toolbar)
self.playSlidesMenu.setObjectName(u'playSlidesMenu')
self.playSlidesMenu.setText(translate('OpenLP.SlideController', self.playSlidesMenu.setText(translate('OpenLP.SlideController',
'Play Slides')) 'Play Slides'))
self.playSlidesMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) self.playSlidesMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
self.toolbar.addToolbarWidget(u'Play Slides Menu',
self.playSlidesMenu)
self.playSlidesMenu.setMenu(QtGui.QMenu( self.playSlidesMenu.setMenu(QtGui.QMenu(
translate('OpenLP.SlideController', 'Play Slides'), translate('OpenLP.SlideController', 'Play Slides'),
self.toolbar)) self.toolbar))
self.playSlidesLoop = shortcut_action(self.playSlidesMenu, self.toolbar.addToolbarWidget(self.playSlidesMenu)
u'playSlidesLoop', [], self.onPlaySlidesLoop, self.playSlidesLoop = create_action(self, u'playSlidesLoop',
u':/media/media_time.png', False, text=UiStrings().PlaySlidesInLoop,
unicode(UiStrings().LiveToolbar)) icon=u':/media/media_time.png', checked=False, shortcuts=[],
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop) category=self.category, triggers=self.onPlaySlidesLoop)
self.playSlidesOnce = shortcut_action(self.playSlidesMenu, self.playSlidesOnce = create_action(self, u'playSlidesOnce',
u'playSlidesOnce', [], self.onPlaySlidesOnce, text=UiStrings().PlaySlidesToEnd,
u':/media/media_time.png', False, icon=u':/media/media_time.png', checked=False, shortcuts=[],
unicode(UiStrings().LiveToolbar)) category=self.category, triggers=self.onPlaySlidesOnce)
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
if QtCore.QSettings().value(self.parent().generalSettingsSection + if QtCore.QSettings().value(self.parent().generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool(): u'/enable slide loop', QtCore.QVariant(True)).toBool():
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop) self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
@ -237,47 +245,75 @@ class SlideController(Controller):
self.playSlidesMenu.menu().addAction(self.playSlidesOnce) self.playSlidesMenu.menu().addAction(self.playSlidesOnce)
# Loop Delay Spinbox # Loop Delay Spinbox
self.delaySpinBox = QtGui.QSpinBox() self.delaySpinBox = QtGui.QSpinBox()
self.delaySpinBox.setObjectName(u'delaySpinBox')
self.delaySpinBox.setRange(1, 180) self.delaySpinBox.setRange(1, 180)
self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox)
self.delaySpinBox.setSuffix(UiStrings().Seconds) self.delaySpinBox.setSuffix(UiStrings().Seconds)
self.delaySpinBox.setToolTip(translate('OpenLP.SlideController', self.delaySpinBox.setToolTip(translate('OpenLP.SlideController',
'Delay between slides in seconds.')) 'Delay between slides in seconds.'))
self.toolbar.addToolbarWidget(self.delaySpinBox)
else: else:
self.toolbar.addToolbarButton( self.toolbar.addToolbarAction(u'goLive',
# Does not need translating - control string. icon=u':/general/general_live.png',
u'Go Live', u':/general/general_live.png', tooltip=translate('OpenLP.SlideController', 'Move to live.'),
translate('OpenLP.SlideController', 'Move to live.'), triggers=self.onGoLive)
self.onGoLive) self.toolbar.addToolbarAction(u'addToService',
self.toolbar.addToolbarButton( icon=u':/general/general_add.png',
# Does not need translating - control string. tooltip=translate('OpenLP.SlideController', 'Add to Service.'),
u'Add to Service', u':/general/general_add.png', triggers=self.onPreviewAddToService)
translate('OpenLP.SlideController', 'Add to Service.'), self.toolbar.addSeparator()
self.onPreviewAddToService) self.toolbar.addToolbarAction(u'editSong',
self.toolbar.addToolbarSeparator(u'Close Separator') icon=u':/general/general_edit.png',
self.toolbar.addToolbarButton( tooltip=translate('OpenLP.SlideController',
# Does not need translating - control string. 'Edit and reload song preview.'), triggers=self.onEditSong)
u'Edit Song', u':/general/general_edit.png',
translate('OpenLP.SlideController',
'Edit and reload song preview.'),
self.onEditSong)
self.controllerLayout.addWidget(self.toolbar) self.controllerLayout.addWidget(self.toolbar)
# Build the Media Toolbar # Build the Media Toolbar
self.mediaController.add_controller_items(self, self.controllerLayout) self.mediaController.add_controller_items(self, self.controllerLayout)
if self.isLive: if self.isLive:
# Build the Song Toolbar # Build the Song Toolbar
self.songMenu = QtGui.QToolButton(self.toolbar) self.songMenu = QtGui.QToolButton(self.toolbar)
self.songMenu.setObjectName(u'songMenu')
self.songMenu.setText(translate('OpenLP.SlideController', 'Go To')) self.songMenu.setText(translate('OpenLP.SlideController', 'Go To'))
self.songMenu.setPopupMode(QtGui.QToolButton.InstantPopup) self.songMenu.setPopupMode(QtGui.QToolButton.InstantPopup)
self.toolbar.addToolbarWidget(u'Song Menu', self.songMenu)
self.songMenu.setMenu(QtGui.QMenu( self.songMenu.setMenu(QtGui.QMenu(
translate('OpenLP.SlideController', 'Go To'), self.toolbar)) translate('OpenLP.SlideController', 'Go To'), self.toolbar))
self.toolbar.makeWidgetsInvisible([u'Song Menu']) self.toolbar.addToolbarWidget(self.songMenu)
# Stuff for items with background audio. # Stuff for items with background audio.
self.audioPauseItem = self.toolbar.addToolbarButton( self.audioPauseItem = self.toolbar.addToolbarAction(
u'Pause Audio', u':/slides/media_playback_pause.png', u'audioPauseItem', icon=u':/slides/media_playback_pause.png',
translate('OpenLP.SlideController', 'Pause audio.'), text=translate('OpenLP.SlideController', 'Pause Audio'),
self.onAudioPauseClicked, True) tooltip=translate('OpenLP.SlideController', 'Pause audio.'),
self.audioPauseItem.setVisible(False) checked=False, visible=False, category=self.category,
triggers=self.onAudioPauseClicked)
self.audioMenu = QtGui.QMenu(
translate('OpenLP.SlideController', 'Background Audio'), self)
self.audioPauseItem.setMenu(self.audioMenu)
self.audioPauseItem.setParent(self)
self.toolbar.widgetForAction(self.audioPauseItem).setPopupMode(
QtGui.QToolButton.MenuButtonPopup)
self.nextTrackItem = create_action(self, u'nextTrackItem',
text=translate('OpenLP.SlideController', 'Next Track'),
icon=u':/slides/media_playback_next.png', tooltip=translate(
'OpenLP.SlideController', 'Go to next audio track.'),
category=self.category, context=QtCore.Qt.WindowShortcut,
triggers=self.onNextTrackClicked)
self.audioMenu.addAction(self.nextTrackItem)
self.trackMenu = self.audioMenu.addMenu(
translate('OpenLP.SlideController', 'Tracks'))
self.audioTimeLabel = QtGui.QLabel(u' 00:00 ', self.toolbar)
self.audioTimeLabel.setAlignment(
QtCore.Qt.AlignCenter|QtCore.Qt.AlignHCenter)
self.audioTimeLabel.setStyleSheet(
u'background-color: palette(background); '
u'border-top-color: palette(shadow); '
u'border-left-color: palette(shadow); '
u'border-bottom-color: palette(light); '
u'border-right-color: palette(light); '
u'border-radius: 3px; border-style: inset; '
u'border-width: 1; font-family: monospace; margin: 2px;'
)
self.audioTimeLabel.setObjectName(u'audioTimeLabel')
self.toolbar.addToolbarWidget(self.audioTimeLabel)
self.toolbar.setWidgetVisible(self.audioList, False)
# Screen preview area # Screen preview area
self.previewFrame = QtGui.QFrame(self.splitter) self.previewFrame = QtGui.QFrame(self.splitter)
self.previewFrame.setGeometry(QtCore.QRect(0, 0, 300, 300 * self.ratio)) self.previewFrame.setGeometry(QtCore.QRect(0, 0, 300, 300 * self.ratio))
@ -322,89 +358,31 @@ class SlideController(Controller):
self.shortcutTimer = QtCore.QTimer() self.shortcutTimer = QtCore.QTimer()
self.shortcutTimer.setObjectName(u'shortcutTimer') self.shortcutTimer.setObjectName(u'shortcutTimer')
self.shortcutTimer.setSingleShot(True) self.shortcutTimer.setSingleShot(True)
self.verseShortcut = shortcut_action(self, u'verseShortcut', shortcuts = [{u'key': u'V', u'configurable': True,
[QtGui.QKeySequence(u'V')], self.slideShortcutActivated, u'text': translate('OpenLP.SlideController', 'Go to "Verse"')},
category=unicode(UiStrings().LiveToolbar), {u'key': u'C', u'configurable': True,
context=QtCore.Qt.WidgetWithChildrenShortcut) u'text': translate('OpenLP.SlideController', 'Go to "Chorus"')},
self.verseShortcut.setText(translate( {u'key': u'B', u'configurable': True,
'OpenLP.SlideController', 'Go to "Verse"')) u'text': translate('OpenLP.SlideController', 'Go to "Bridge"')},
self.shortcut0 = shortcut_action(self, u'0', {u'key': u'P', u'configurable': True,
[QtGui.QKeySequence(u'0')], self.slideShortcutActivated, u'text': translate('OpenLP.SlideController',
context=QtCore.Qt.WidgetWithChildrenShortcut) 'Go to "Pre-Chorus"')},
self.shortcut1 = shortcut_action(self, u'1', {u'key': u'I', u'configurable': True,
[QtGui.QKeySequence(u'1')], self.slideShortcutActivated, u'text': translate('OpenLP.SlideController', 'Go to "Intro"')},
context=QtCore.Qt.WidgetWithChildrenShortcut) {u'key': u'E', u'configurable': True,
self.shortcut2 = shortcut_action(self, u'2', u'text': translate('OpenLP.SlideController', 'Go to "Ending"')},
[QtGui.QKeySequence(u'2')], self.slideShortcutActivated, {u'key': u'O', u'configurable': True,
context=QtCore.Qt.WidgetWithChildrenShortcut) u'text': translate('OpenLP.SlideController', 'Go to "Other"')}]
self.shortcut3 = shortcut_action(self, u'3', shortcuts += [{u'key': unicode(number)} for number in range(0, 10)]
[QtGui.QKeySequence(u'3')], self.slideShortcutActivated, self.previewListWidget.addActions([create_action(self,
context=QtCore.Qt.WidgetWithChildrenShortcut) u'shortcutAction_%s' % s[u'key'], text=s.get(u'text'),
self.shortcut4 = shortcut_action(self, u'4', shortcuts=[QtGui.QKeySequence(s[u'key'])],
[QtGui.QKeySequence(u'4')], self.slideShortcutActivated, context=QtCore.Qt.WidgetWithChildrenShortcut,
context=QtCore.Qt.WidgetWithChildrenShortcut) category=self.category if s.get(u'configurable') else None,
self.shortcut5 = shortcut_action(self, u'5', triggers=self._slideShortcutActivated) for s in shortcuts])
[QtGui.QKeySequence(u'5')], self.slideShortcutActivated,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.shortcut6 = shortcut_action(self, u'6',
[QtGui.QKeySequence(u'6')], self.slideShortcutActivated,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.shortcut7 = shortcut_action(self, u'7',
[QtGui.QKeySequence(u'7')], self.slideShortcutActivated,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.shortcut8 = shortcut_action(self, u'8',
[QtGui.QKeySequence(u'8')], self.slideShortcutActivated,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.shortcut9 = shortcut_action(self, u'9',
[QtGui.QKeySequence(u'9')], self.slideShortcutActivated,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.chorusShortcut = shortcut_action(self, u'chorusShortcut',
[QtGui.QKeySequence(u'C')], self.slideShortcutActivated,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.chorusShortcut.setText(translate(
'OpenLP.SlideController', 'Go to "Chorus"'))
self.bridgeShortcut = shortcut_action(self, u'bridgeShortcut',
[QtGui.QKeySequence(u'B')], self.slideShortcutActivated,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.bridgeShortcut.setText(translate(
'OpenLP.SlideController', 'Go to "Bridge"'))
self.preChorusShortcut = shortcut_action(self, u'preChorusShortcut',
[QtGui.QKeySequence(u'P')], self.slideShortcutActivated,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.preChorusShortcut.setText(translate(
'OpenLP.SlideController', 'Go to "Pre-Chorus"'))
self.introShortcut = shortcut_action(self, u'introShortcut',
[QtGui.QKeySequence(u'I')], self.slideShortcutActivated,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.introShortcut.setText(translate(
'OpenLP.SlideController', 'Go to "Intro"'))
self.endingShortcut = shortcut_action(self, u'endingShortcut',
[QtGui.QKeySequence(u'E')], self.slideShortcutActivated,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.endingShortcut.setText(translate(
'OpenLP.SlideController', 'Go to "Ending"'))
self.otherShortcut = shortcut_action(self, u'otherShortcut',
[QtGui.QKeySequence(u'O')], self.slideShortcutActivated,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.otherShortcut.setText(translate(
'OpenLP.SlideController', 'Go to "Other"'))
self.previewListWidget.addActions([
self.shortcut0, self.shortcut1, self.shortcut2, self.shortcut3,
self.shortcut4, self.shortcut5, self.shortcut6, self.shortcut7,
self.shortcut8, self.shortcut9, self.verseShortcut,
self.chorusShortcut, self.bridgeShortcut,
self.preChorusShortcut, self.introShortcut, self.endingShortcut,
self.otherShortcut
])
QtCore.QObject.connect( QtCore.QObject.connect(
self.shortcutTimer, QtCore.SIGNAL(u'timeout()'), self.shortcutTimer, QtCore.SIGNAL(u'timeout()'),
self.slideShortcutActivated) self._slideShortcutActivated)
# Signals # Signals
QtCore.QObject.connect(self.previewListWidget, QtCore.QObject.connect(self.previewListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
@ -412,20 +390,21 @@ class SlideController(Controller):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
self.receiveSpinDelay) self.receiveSpinDelay)
self.toolbar.makeWidgetsInvisible(self.loopList) QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_toggle_display'),
self.toggleDisplay)
self.toolbar.setWidgetVisible(self.loopList, False)
else: else:
QtCore.QObject.connect(self.previewListWidget, QtCore.QObject.connect(self.previewListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onGoLiveClick) self.onGoLiveClick)
self.toolbar.makeWidgetsInvisible(self.songEditList) self.toolbar.setWidgetVisible([u'editSong'], False)
if self.isLive: if self.isLive:
self.setLiveHotkeys(self) self.setLiveHotkeys(self)
self.__addActionsToWidget(self.previewListWidget) self.__addActionsToWidget(self.previewListWidget)
else: else:
self.setPreviewHotkeys()
self.previewListWidget.addActions( self.previewListWidget.addActions(
[self.nextItem, [self.nextItem, self.previousItem])
self.previousItem])
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix), QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix),
self.onStopLoop) self.onStopLoop)
@ -447,8 +426,11 @@ class SlideController(Controller):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix), QtCore.SIGNAL(u'slidecontroller_%s_unblank' % self.typePrefix),
self.onSlideUnblank) self.onSlideUnblank)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_update_slide_limits'),
self.updateSlideLimits)
def slideShortcutActivated(self): def _slideShortcutActivated(self):
""" """
Called, when a shortcut has been activated to jump to a chorus, verse, Called, when a shortcut has been activated to jump to a chorus, verse,
etc. etc.
@ -464,52 +446,38 @@ class SlideController(Controller):
SONGS_PLUGIN_AVAILABLE = True SONGS_PLUGIN_AVAILABLE = True
except ImportError: except ImportError:
SONGS_PLUGIN_AVAILABLE = False SONGS_PLUGIN_AVAILABLE = False
verse_type = unicode(self.sender().objectName()) sender_name = unicode(self.sender().objectName())
if verse_type.startswith(u'verseShortcut'): verse_type = sender_name[15:] \
if sender_name[:15] == u'shortcutAction_' else u''
if SONGS_PLUGIN_AVAILABLE: if SONGS_PLUGIN_AVAILABLE:
if verse_type == u'V':
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.Verse] VerseType.TranslatedTags[VerseType.Verse]
else: elif verse_type == u'C':
self.current_shortcut = u'V'
elif verse_type.startswith(u'chorusShortcut'):
if SONGS_PLUGIN_AVAILABLE:
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.Chorus] VerseType.TranslatedTags[VerseType.Chorus]
else: elif verse_type == u'B':
self.current_shortcut = u'C'
elif verse_type.startswith(u'bridgeShortcut'):
if SONGS_PLUGIN_AVAILABLE:
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.Bridge] VerseType.TranslatedTags[VerseType.Bridge]
else: elif verse_type == u'P':
self.current_shortcut = u'B'
elif verse_type.startswith(u'preChorusShortcut'):
if SONGS_PLUGIN_AVAILABLE:
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.PreChorus] VerseType.TranslatedTags[VerseType.PreChorus]
else: elif verse_type == u'I':
self.current_shortcut = u'P'
elif verse_type.startswith(u'introShortcut'):
if SONGS_PLUGIN_AVAILABLE:
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.Intro] VerseType.TranslatedTags[VerseType.Intro]
else: elif verse_type == u'E':
self.current_shortcut = u'I'
elif verse_type.startswith(u'endingShortcut'):
if SONGS_PLUGIN_AVAILABLE:
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.Ending] VerseType.TranslatedTags[VerseType.Ending]
else: elif verse_type == u'O':
self.current_shortcut = u'E'
elif verse_type.startswith(u'otherShortcut'):
if SONGS_PLUGIN_AVAILABLE:
self.current_shortcut = \ self.current_shortcut = \
VerseType.TranslatedTags[VerseType.Other] VerseType.TranslatedTags[VerseType.Other]
else:
self.current_shortcut = u'O'
elif verse_type.isnumeric(): elif verse_type.isnumeric():
self.current_shortcut += verse_type self.current_shortcut += verse_type
self.current_shortcut = self.current_shortcut.upper() self.current_shortcut = self.current_shortcut.upper()
elif verse_type.isnumeric():
self.current_shortcut += verse_type
elif verse_type:
self.current_shortcut = verse_type
keys = self.slideList.keys() keys = self.slideList.keys()
matches = [match for match in keys matches = [match for match in keys
if match.startswith(self.current_shortcut)] if match.startswith(self.current_shortcut)]
@ -518,7 +486,7 @@ class SlideController(Controller):
self.current_shortcut = u'' self.current_shortcut = u''
self.__checkUpdateSelectedSlide(self.slideList[matches[0]]) self.__checkUpdateSelectedSlide(self.slideList[matches[0]])
self.slideSelected() self.slideSelected()
elif verse_type != u'shortcutTimer': elif sender_name != u'shortcutTimer':
# Start the time as we did not have any match. # Start the time as we did not have any match.
self.shortcutTimer.start(350) self.shortcutTimer.start(350)
else: else:
@ -532,56 +500,54 @@ class SlideController(Controller):
# Reset the shortcut. # Reset the shortcut.
self.current_shortcut = u'' self.current_shortcut = u''
def setPreviewHotkeys(self, parent=None):
self.previousItem.setObjectName(u'previousItemPreview')
self.nextItem.setObjectName(u'nextItemPreview')
action_list = ActionList.get_instance()
action_list.add_action(self.previousItem)
action_list.add_action(self.nextItem)
def setLiveHotkeys(self, parent=None): def setLiveHotkeys(self, parent=None):
self.previousItem.setObjectName(u'previousItemLive') self.previousService = create_action(parent, u'previousService',
self.nextItem.setObjectName(u'nextItemLive') text=translate('OpenLP.SlideController', 'Previous Service'),
action_list = ActionList.get_instance() shortcuts=[QtCore.Qt.Key_Left],
action_list.add_category( context=QtCore.Qt.WidgetWithChildrenShortcut,
unicode(UiStrings().LiveToolbar), CategoryOrder.standardToolbar) category=self.category, triggers=self.servicePrevious)
action_list.add_action(self.previousItem) self.nextService = create_action(parent, 'nextService',
action_list.add_action(self.nextItem) text=translate('OpenLP.SlideController', 'Next Service'),
self.previousService = shortcut_action(parent, u'previousService', shortcuts=[QtCore.Qt.Key_Right],
[QtCore.Qt.Key_Left], self.servicePrevious, context=QtCore.Qt.WidgetWithChildrenShortcut,
category=unicode(UiStrings().LiveToolbar), category=self.category, triggers=self.serviceNext)
context=QtCore.Qt.WidgetWithChildrenShortcut) self.escapeItem = create_action(parent, 'escapeItem',
self.previousService.setText( text=translate('OpenLP.SlideController', 'Escape Item'),
translate('OpenLP.SlideController', 'Previous Service')) shortcuts=[QtCore.Qt.Key_Escape],
self.nextService = shortcut_action(parent, 'nextService', context=QtCore.Qt.WidgetWithChildrenShortcut,
[QtCore.Qt.Key_Right], self.serviceNext, category=self.category, triggers=self.liveEscape)
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.nextService.setText(
translate('OpenLP.SlideController', 'Next Service'))
self.escapeItem = shortcut_action(parent, 'escapeItem',
[QtCore.Qt.Key_Escape], self.liveEscape,
category=unicode(UiStrings().LiveToolbar),
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.escapeItem.setText(
translate('OpenLP.SlideController', 'Escape Item'))
def liveEscape(self): def liveEscape(self):
self.display.setVisible(False) self.display.setVisible(False)
self.mediaController.video_stop([self]) self.mediaController.video_stop([self])
def toggleDisplay(self, action):
"""
Toggle the display settings triggered from remote messages.
"""
if action == u'blank' or action == u'hide':
self.onBlankDisplay(True)
elif action == u'theme':
self.onThemeDisplay(True)
elif action == u'desktop':
self.onHideDisplay(True)
elif action == u'show':
self.onBlankDisplay(False)
self.onThemeDisplay(False)
self.onHideDisplay(False)
def servicePrevious(self): def servicePrevious(self):
""" """
Live event to select the previous service item from the service manager. Live event to select the previous service item from the service manager.
""" """
self.keypress_queue.append(u'previous') self.keypress_queue.append(ServiceItemAction.Previous)
self._process_queue() self._process_queue()
def serviceNext(self): def serviceNext(self):
""" """
Live event to select the next service item from the service manager. Live event to select the next service item from the service manager.
""" """
self.keypress_queue.append(u'next') self.keypress_queue.append(ServiceItemAction.Next)
self._process_queue() self._process_queue()
def _process_queue(self): def _process_queue(self):
@ -592,8 +558,13 @@ class SlideController(Controller):
if len(self.keypress_queue): if len(self.keypress_queue):
while len(self.keypress_queue) and not self.keypress_loop: while len(self.keypress_queue) and not self.keypress_loop:
self.keypress_loop = True self.keypress_loop = True
if self.keypress_queue.popleft() == u'previous': keypressCommand = self.keypress_queue.popleft()
if keypressCommand == ServiceItemAction.Previous:
Receiver.send_message('servicemanager_previous_item') Receiver.send_message('servicemanager_previous_item')
elif keypressCommand == ServiceItemAction.PreviousLastSlide:
# Go to the last slide of the previous item
Receiver.send_message('servicemanager_previous_item',
u'last slide')
else: else:
Receiver.send_message('servicemanager_next_item') Receiver.send_message('servicemanager_next_item')
self.keypress_loop = False self.keypress_loop = False
@ -611,15 +582,20 @@ class SlideController(Controller):
self.display.setup() self.display.setup()
if self.isLive: if self.isLive:
self.__addActionsToWidget(self.display) self.__addActionsToWidget(self.display)
self.display.audioPlayer.connectSlot(
QtCore.SIGNAL(u'tick(qint64)'), self.onAudioTimeRemaining)
# The SlidePreview's ratio. # The SlidePreview's ratio.
try:
self.ratio = float(self.screens.current[u'size'].width()) / \ self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height()) float(self.screens.current[u'size'].height())
except ZeroDivisionError:
self.ratio = 1
self.mediaController.setup_display(self.display) self.mediaController.setup_display(self.display)
self.previewSizeChanged() self.previewSizeChanged()
self.previewDisplay.setup() self.previewDisplay.setup()
serviceItem = ServiceItem() serviceItem = ServiceItem()
self.previewDisplay.webView.setHtml(build_html(serviceItem, self.previewDisplay.webView.setHtml(build_html(serviceItem,
self.previewDisplay.screen, None, self.isLive, None, self.previewDisplay.screen, None, self.isLive,
plugins=PluginManager.get_instance().plugins)) plugins=PluginManager.get_instance().plugins))
self.mediaController.setup_display(self.previewDisplay) self.mediaController.setup_display(self.previewDisplay)
if self.serviceItem: if self.serviceItem:
@ -682,6 +658,14 @@ class SlideController(Controller):
""" """
self.delaySpinBox.setValue(int(value)) self.delaySpinBox.setValue(int(value))
def updateSlideLimits(self):
"""
Updates the Slide Limits variable from the settings.
"""
self.slide_limits = QtCore.QSettings().value(
self.parent().advancedlSettingsSection + u'/slide limits',
QtCore.QVariant(SlideLimits.End)).toInt()[0]
def enableToolBar(self, item): def enableToolBar(self, item):
""" """
Allows the toolbars to be reconfigured based on Controller Type Allows the toolbars to be reconfigured based on Controller Type
@ -699,9 +683,9 @@ class SlideController(Controller):
# Work-around for OS X, hide and then show the toolbar # Work-around for OS X, hide and then show the toolbar
# See bug #791050 # See bug #791050
self.toolbar.hide() self.toolbar.hide()
self.mediabar.setVisible(False) self.mediabar.hide()
self.toolbar.makeWidgetsInvisible([u'Song Menu']) self.songMenu.hide()
self.toolbar.makeWidgetsInvisible(self.loopList) self.toolbar.setWidgetVisible(self.loopList, False)
# Reset the button # Reset the button
self.playSlidesOnce.setChecked(False) self.playSlidesOnce.setChecked(False)
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png')) self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
@ -711,17 +695,16 @@ class SlideController(Controller):
if QtCore.QSettings().value( if QtCore.QSettings().value(
self.parent().songsSettingsSection + u'/display songbar', self.parent().songsSettingsSection + u'/display songbar',
QtCore.QVariant(True)).toBool() and len(self.slideList) > 0: QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
self.toolbar.makeWidgetsVisible([u'Song Menu']) self.songMenu.show()
if item.is_capable(ItemCapabilities.CanLoop) and \ if item.is_capable(ItemCapabilities.CanLoop) and \
len(item.get_frames()) > 1: len(item.get_frames()) > 1:
self.toolbar.makeWidgetsVisible(self.loopList) self.toolbar.setWidgetVisible(self.loopList)
if item.is_media(): if item.is_media():
self.mediabar.setVisible(True) self.mediabar.show()
self.toolbar.makeWidgetsInvisible(self.nextPreviousList) self.previousItem.setVisible(not item.is_media())
else: self.nextItem.setVisible(not item.is_media())
# Work-around for OS X, hide and then show the toolbar # Work-around for OS X, hide and then show the toolbar
# See bug #791050 # See bug #791050
self.toolbar.makeWidgetsVisible(self.nextPreviousList)
self.toolbar.show() self.toolbar.show()
def enablePreviewToolBar(self, item): def enablePreviewToolBar(self, item):
@ -731,17 +714,16 @@ class SlideController(Controller):
# Work-around for OS X, hide and then show the toolbar # Work-around for OS X, hide and then show the toolbar
# See bug #791050 # See bug #791050
self.toolbar.hide() self.toolbar.hide()
self.mediabar.setVisible(False) self.mediabar.hide()
self.toolbar.makeWidgetsInvisible(self.songEditList) self.toolbar.setWidgetVisible([u'editSong'], False)
if item.is_capable(ItemCapabilities.CanEdit) and item.from_plugin: if item.is_capable(ItemCapabilities.CanEdit) and item.from_plugin:
self.toolbar.makeWidgetsVisible(self.songEditList) self.toolbar.setWidgetVisible([u'editSong'])
elif item.is_media(): elif item.is_media():
self.mediabar.setVisible(True) self.mediabar.show()
self.toolbar.makeWidgetsInvisible(self.nextPreviousList) self.previousItem.setVisible(not item.is_media())
if not item.is_media(): self.nextItem.setVisible(not item.is_media())
# Work-around for OS X, hide and then show the toolbar # Work-around for OS X, hide and then show the toolbar
# See bug #791050 # See bug #791050
self.toolbar.makeWidgetsVisible(self.nextPreviousList)
self.toolbar.show() self.toolbar.show()
def refreshServiceItem(self): def refreshServiceItem(self):
@ -818,10 +800,23 @@ class SlideController(Controller):
self.display.audioPlayer.reset() self.display.audioPlayer.reset()
self.setAudioItemsVisibility(False) self.setAudioItemsVisibility(False)
self.audioPauseItem.setChecked(False) self.audioPauseItem.setChecked(False)
# If the current item has background audio
if self.serviceItem.is_capable(ItemCapabilities.HasBackgroundAudio): if self.serviceItem.is_capable(ItemCapabilities.HasBackgroundAudio):
log.debug(u'Starting to play...') log.debug(u'Starting to play...')
self.display.audioPlayer.addToPlaylist( self.display.audioPlayer.addToPlaylist(
self.serviceItem.background_audio) self.serviceItem.background_audio)
self.trackMenu.clear()
for counter in range(len(self.serviceItem.background_audio)):
action = self.trackMenu.addAction(os.path.basename(
self.serviceItem.background_audio[counter]))
action.setData(counter)
QtCore.QObject.connect(action,
QtCore.SIGNAL(u'triggered(bool)'),
self.onTrackTriggered)
self.display.audioPlayer.repeat = QtCore.QSettings().value(
self.parent().generalSettingsSection + \
u'/audio repeat list',
QtCore.QVariant(False)).toBool()
if QtCore.QSettings().value( if QtCore.QSettings().value(
self.parent().generalSettingsSection + \ self.parent().generalSettingsSection + \
u'/audio start paused', u'/audio start paused',
@ -873,7 +868,7 @@ class SlideController(Controller):
self.slideList[unicode(row)] = row - 1 self.slideList[unicode(row)] = row - 1
text.append(unicode(row)) text.append(unicode(row))
self.previewListWidget.setItem(framenumber, 0, item) self.previewListWidget.setItem(framenumber, 0, item)
if slideHeight != 0: if slideHeight:
self.previewListWidget.setRowHeight(framenumber, slideHeight) self.previewListWidget.setRowHeight(framenumber, slideHeight)
self.previewListWidget.setVerticalHeaderLabels(text) self.previewListWidget.setVerticalHeaderLabels(text)
if self.serviceItem.is_text(): if self.serviceItem.is_text():
@ -938,7 +933,8 @@ class SlideController(Controller):
display_type = QtCore.QSettings().value( display_type = QtCore.QSettings().value(
self.parent().generalSettingsSection + u'/screen blank', self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'')).toString() QtCore.QVariant(u'')).toString()
if not self.display.primary: if self.screens.which_screen(self.window()) != \
self.screens.which_screen(self.display):
# Order done to handle initial conversion # Order done to handle initial conversion
if display_type == u'themed': if display_type == u'themed':
self.onThemeDisplay(True) self.onThemeDisplay(True)
@ -949,7 +945,7 @@ class SlideController(Controller):
else: else:
Receiver.send_message(u'live_display_show') Receiver.send_message(u'live_display_show')
else: else:
Receiver.send_message(u'live_display_hide', HideMode.Screen) self.liveEscape()
def onSlideBlank(self): def onSlideBlank(self):
""" """
@ -1074,7 +1070,7 @@ class SlideController(Controller):
else: else:
Receiver.send_message(u'live_display_show') Receiver.send_message(u'live_display_show')
def onSlideSelected(self, start=False): def onSlideSelected(self):
""" """
Slide selected in controller Slide selected in controller
""" """
@ -1087,7 +1083,7 @@ class SlideController(Controller):
""" """
row = self.previewListWidget.currentRow() row = self.previewListWidget.currentRow()
self.selectedRow = 0 self.selectedRow = 0
if row > -1 and row < self.previewListWidget.rowCount(): if -1 < row < self.previewListWidget.rowCount():
if self.serviceItem.is_command(): if self.serviceItem.is_command():
if self.isLive and not start: if self.isLive and not start:
Receiver.send_message( Receiver.send_message(
@ -1144,6 +1140,13 @@ class SlideController(Controller):
rect.y(), rect.width(), rect.height()) rect.y(), rect.width(), rect.height())
self.slidePreview.setPixmap(winimg) self.slidePreview.setPixmap(winimg)
def onSlideSelectedNextAction(self, checked):
"""
Wrapper function from create_action so we can throw away the
incorrect parameter
"""
self.onSlideSelectedNext()
def onSlideSelectedNext(self, wrap=None): def onSlideSelectedNext(self, wrap=None):
""" """
Go to the next slide. Go to the next slide.
@ -1158,10 +1161,14 @@ class SlideController(Controller):
row = self.previewListWidget.currentRow() + 1 row = self.previewListWidget.currentRow() + 1
if row == self.previewListWidget.rowCount(): if row == self.previewListWidget.rowCount():
if wrap is None: if wrap is None:
wrap = QtCore.QSettings().value( if self.slide_limits == SlideLimits.Wrap:
self.parent().generalSettingsSection + row = 0
u'/enable slide loop', QtCore.QVariant(True)).toBool() elif self.isLive and self.slide_limits == SlideLimits.Next:
if wrap: self.serviceNext()
return
else:
row = self.previewListWidget.rowCount() - 1
elif wrap:
row = 0 row = 0
else: else:
row = self.previewListWidget.rowCount() - 1 row = self.previewListWidget.rowCount() - 1
@ -1181,9 +1188,13 @@ class SlideController(Controller):
else: else:
row = self.previewListWidget.currentRow() - 1 row = self.previewListWidget.currentRow() - 1
if row == -1: if row == -1:
if QtCore.QSettings().value(self.parent().generalSettingsSection if self.slide_limits == SlideLimits.Wrap:
+ u'/enable slide loop', QtCore.QVariant(True)).toBool():
row = self.previewListWidget.rowCount() - 1 row = self.previewListWidget.rowCount() - 1
elif self.isLive and self.slide_limits == SlideLimits.Next:
self.keypress_queue.append(
ServiceItemAction.PreviousLastSlide)
self._process_queue()
return
else: else:
row = 0 row = 0
self.__checkUpdateSelectedSlide(row) self.__checkUpdateSelectedSlide(row)
@ -1216,7 +1227,7 @@ class SlideController(Controller):
""" """
Stop the timer loop running Stop the timer loop running
""" """
if self.timer_id != 0: if self.timer_id:
self.killTimer(self.timer_id) self.killTimer(self.timer_id)
self.timer_id = 0 self.timer_id = 0
@ -1263,7 +1274,7 @@ class SlideController(Controller):
self.onToggleLoop() self.onToggleLoop()
def setAudioItemsVisibility(self, visible): def setAudioItemsVisibility(self, visible):
self.audioPauseItem.setVisible(visible) self.toolbar.setWidgetVisible(self.audioList, visible)
def onAudioPauseClicked(self, checked): def onAudioPauseClicked(self, checked):
if not self.audioPauseItem.isVisible(): if not self.audioPauseItem.isVisible():
@ -1317,7 +1328,7 @@ class SlideController(Controller):
If preview copy slide item to live If preview copy slide item to live
""" """
row = self.previewListWidget.currentRow() row = self.previewListWidget.currentRow()
if row > -1 and row < self.previewListWidget.rowCount(): if -1 < row < self.previewListWidget.rowCount():
if self.serviceItem.from_service: if self.serviceItem.from_service:
Receiver.send_message('servicemanager_preview_live', Receiver.send_message('servicemanager_preview_live',
u'%s:%s' % (self.serviceItem._uuid, row)) u'%s:%s' % (self.serviceItem._uuid, row))
@ -1374,3 +1385,17 @@ class SlideController(Controller):
return HideMode.Screen return HideMode.Screen
else: else:
return None return None
def onNextTrackClicked(self):
self.display.audioPlayer.next()
def onAudioTimeRemaining(self, time):
seconds = self.display.audioPlayer.mediaObject.remainingTime() // 1000
minutes = seconds // 60
seconds %= 60
self.audioTimeLabel.setText(u' %02d:%02d ' % (minutes, seconds))
def onTrackTriggered(self):
action = self.sender()
index = action.data().toInt()[0]
self.display.audioPlayer.goTo(index)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -359,11 +359,15 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.gradientEndButton.setStyleSheet(u'background-color: %s' % self.gradientEndButton.setStyleSheet(u'background-color: %s' %
self.theme.background_end_color) self.theme.background_end_color)
self.setField(u'background_type', QtCore.QVariant(1)) self.setField(u'background_type', QtCore.QVariant(1))
else: elif self.theme.background_type == \
BackgroundType.to_string(BackgroundType.Image):
self.imageColorButton.setStyleSheet(u'background-color: %s' % self.imageColorButton.setStyleSheet(u'background-color: %s' %
self.theme.background_border_color) self.theme.background_border_color)
self.imageFileEdit.setText(self.theme.background_filename) self.imageFileEdit.setText(self.theme.background_filename)
self.setField(u'background_type', QtCore.QVariant(2)) self.setField(u'background_type', QtCore.QVariant(2))
elif self.theme.background_type == \
BackgroundType.to_string(BackgroundType.Transparent):
self.setField(u'background_type', QtCore.QVariant(3))
if self.theme.background_direction == \ if self.theme.background_direction == \
BackgroundGradientType.to_string(BackgroundGradientType.Horizontal): BackgroundGradientType.to_string(BackgroundGradientType.Horizontal):
self.setField(u'gradient', QtCore.QVariant(0)) self.setField(u'gradient', QtCore.QVariant(0))

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -30,6 +30,7 @@ import zipfile
import shutil import shutil
import logging import logging
import locale import locale
import re
from xml.etree.ElementTree import ElementTree, XML from xml.etree.ElementTree import ElementTree, XML
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
@ -40,11 +41,10 @@ from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \ from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \
BackgroundGradientType BackgroundGradientType
from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ from openlp.core.lib.ui import UiStrings, critical_error_message_box, \
context_menu_action, context_menu_separator create_widget_action
from openlp.core.theme import Theme from openlp.core.theme import Theme
from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding
get_filesystem_encoding
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -64,32 +64,32 @@ class ThemeManager(QtGui.QWidget):
self.layout.setMargin(0) self.layout.setMargin(0)
self.layout.setObjectName(u'layout') self.layout.setObjectName(u'layout')
self.toolbar = OpenLPToolbar(self) self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton(UiStrings().NewTheme,
u':/themes/theme_new.png',
translate('OpenLP.ThemeManager', 'Create a new theme.'),
self.onAddTheme)
self.toolbar.addToolbarButton(
translate('OpenLP.ThemeManager', 'Edit Theme'),
u':/themes/theme_edit.png',
translate('OpenLP.ThemeManager', 'Edit a theme.'),
self.onEditTheme)
self.deleteToolbarAction = self.toolbar.addToolbarButton(
translate('OpenLP.ThemeManager', 'Delete Theme'),
u':/general/general_delete.png',
translate('OpenLP.ThemeManager', 'Delete a theme.'),
self.onDeleteTheme)
self.toolbar.addSeparator()
self.toolbar.addToolbarButton(
translate('OpenLP.ThemeManager', 'Import Theme'),
u':/general/general_import.png',
translate('OpenLP.ThemeManager', 'Import a theme.'),
self.onImportTheme)
self.toolbar.addToolbarButton(
translate('OpenLP.ThemeManager', 'Export Theme'),
u':/general/general_export.png',
translate('OpenLP.ThemeManager', 'Export a theme.'),
self.onExportTheme)
self.toolbar.setObjectName(u'toolbar') self.toolbar.setObjectName(u'toolbar')
self.toolbar.addToolbarAction(u'newTheme',
text=UiStrings().NewTheme, icon=u':/themes/theme_new.png',
tooltip=translate('OpenLP.ThemeManager', 'Create a new theme.'),
triggers=self.onAddTheme)
self.toolbar.addToolbarAction(u'editTheme',
text=translate('OpenLP.ThemeManager', 'Edit Theme'),
icon=u':/themes/theme_edit.png',
tooltip=translate('OpenLP.ThemeManager', 'Edit a theme.'),
triggers=self.onEditTheme)
self.deleteToolbarAction = self.toolbar.addToolbarAction(u'deleteTheme',
text=translate('OpenLP.ThemeManager', 'Delete Theme'),
icon=u':/general/general_delete.png',
tooltip=translate('OpenLP.ThemeManager', 'Delete a theme.'),
triggers=self.onDeleteTheme)
self.toolbar.addSeparator()
self.toolbar.addToolbarAction(u'importTheme',
text=translate('OpenLP.ThemeManager', 'Import Theme'),
icon=u':/general/general_import.png',
tooltip=translate('OpenLP.ThemeManager', 'Import a theme.'),
triggers=self.onImportTheme)
self.toolbar.addToolbarAction(u'exportTheme',
text=translate('OpenLP.ThemeManager', 'Export Theme'),
icon=u':/general/general_export.png',
tooltip=translate('OpenLP.ThemeManager', 'Export a theme.'),
triggers=self.onExportTheme)
self.layout.addWidget(self.toolbar) self.layout.addWidget(self.toolbar)
self.themeWidget = QtGui.QWidgetAction(self.toolbar) self.themeWidget = QtGui.QWidgetAction(self.toolbar)
self.themeWidget.setObjectName(u'themeWidget') self.themeWidget.setObjectName(u'themeWidget')
@ -105,29 +105,26 @@ class ThemeManager(QtGui.QWidget):
self.contextMenu) self.contextMenu)
# build the context menu # build the context menu
self.menu = QtGui.QMenu() self.menu = QtGui.QMenu()
self.editAction = context_menu_action( self.editAction = create_widget_action(self.menu,
self.menu, u':/themes/theme_edit.png', text=translate('OpenLP.ThemeManager', '&Edit Theme'),
translate('OpenLP.ThemeManager', '&Edit Theme'), self.onEditTheme) icon=u':/themes/theme_edit.png', triggers=self.onEditTheme)
self.copyAction = context_menu_action( self.copyAction = create_widget_action(self.menu,
self.menu, u':/themes/theme_edit.png', text=translate('OpenLP.ThemeManager', '&Copy Theme'),
translate('OpenLP.ThemeManager', '&Copy Theme'), self.onCopyTheme) icon=u':/themes/theme_edit.png', triggers=self.onCopyTheme)
self.renameAction = context_menu_action( self.renameAction = create_widget_action(self.menu,
self.menu, u':/themes/theme_edit.png', text=translate('OpenLP.ThemeManager', '&Rename Theme'),
translate('OpenLP.ThemeManager', '&Rename Theme'), icon=u':/themes/theme_edit.png', triggers=self.onRenameTheme)
self.onRenameTheme) self.deleteAction = create_widget_action(self.menu,
self.deleteAction = context_menu_action( text=translate('OpenLP.ThemeManager', '&Delete Theme'),
self.menu, u':/general/general_delete.png', icon=u':/general/general_delete.png', triggers=self.onDeleteTheme)
translate('OpenLP.ThemeManager', '&Delete Theme'), self.menu.addSeparator()
self.onDeleteTheme) self.globalAction = create_widget_action(self.menu,
context_menu_separator(self.menu) text=translate('OpenLP.ThemeManager', 'Set As &Global Default'),
self.globalAction = context_menu_action( icon=u':/general/general_export.png',
self.menu, u':/general/general_export.png', triggers=self.changeGlobalFromScreen)
translate('OpenLP.ThemeManager', 'Set As &Global Default'), self.exportAction = create_widget_action(self.menu,
self.changeGlobalFromScreen) text=translate('OpenLP.ThemeManager', '&Export Theme'),
self.exportAction = context_menu_action( icon=u':/general/general_export.png', triggers=self.onExportTheme)
self.menu, u':/general/general_export.png',
translate('OpenLP.ThemeManager', '&Export Theme'),
self.onExportTheme)
# Signals # Signals
QtCore.QObject.connect(self.themeListWidget, QtCore.QObject.connect(self.themeListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
@ -140,13 +137,14 @@ class ThemeManager(QtGui.QWidget):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.configUpdated) QtCore.SIGNAL(u'config_updated'), self.configUpdated)
# Variables # Variables
self.themelist = [] self.theme_list = []
self.path = AppLocation.get_section_data_path(self.settingsSection) self.path = AppLocation.get_section_data_path(self.settingsSection)
check_directory_exists(self.path) check_directory_exists(self.path)
self.thumbPath = os.path.join(self.path, u'thumbnails') self.thumb_path = os.path.join(self.path, u'thumbnails')
check_directory_exists(self.thumbPath) check_directory_exists(self.thumb_path)
self.themeForm.path = self.path self.themeForm.path = self.path
self.oldBackgroundImage = None self.old_background_image = None
self.bad_v1_name_chars = re.compile(r'[%+\[\]]')
# Last little bits of setting up # Last little bits of setting up
self.configUpdated() self.configUpdated()
@ -155,10 +153,9 @@ class ThemeManager(QtGui.QWidget):
Import new themes downloaded by the first time wizard Import new themes downloaded by the first time wizard
""" """
Receiver.send_message(u'cursor_busy') Receiver.send_message(u'cursor_busy')
encoding = get_filesystem_encoding()
files = SettingsManager.get_files(self.settingsSection, u'.otz') files = SettingsManager.get_files(self.settingsSection, u'.otz')
for file in files: for file in files:
file = os.path.join(self.path, file).encode(encoding) file = os.path.join(self.path, file)
self.unzipTheme(file, self.path) self.unzipTheme(file, self.path)
delete_file(file) delete_file(file)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
@ -177,10 +174,10 @@ class ThemeManager(QtGui.QWidget):
""" """
if item is None: if item is None:
return return
realThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) real_theme_name = unicode(item.data(QtCore.Qt.UserRole).toString())
themeName = unicode(item.text()) theme_name = unicode(item.text())
# If default theme restrict actions # If default theme restrict actions
if realThemeName == themeName: if real_theme_name == theme_name:
self.deleteToolbarAction.setVisible(True) self.deleteToolbarAction.setVisible(True)
else: else:
self.deleteToolbarAction.setVisible(False) self.deleteToolbarAction.setVisible(False)
@ -193,35 +190,35 @@ class ThemeManager(QtGui.QWidget):
item = self.themeListWidget.itemAt(point) item = self.themeListWidget.itemAt(point)
if item is None: if item is None:
return return
realThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) real_theme_name = unicode(item.data(QtCore.Qt.UserRole).toString())
themeName = unicode(item.text()) theme_name = unicode(item.text())
self.deleteAction.setVisible(False) self.deleteAction.setVisible(False)
self.renameAction.setVisible(False) self.renameAction.setVisible(False)
self.globalAction.setVisible(False) self.globalAction.setVisible(False)
# If default theme restrict actions # If default theme restrict actions
if realThemeName == themeName: if real_theme_name == theme_name:
self.deleteAction.setVisible(True) self.deleteAction.setVisible(True)
self.renameAction.setVisible(True) self.renameAction.setVisible(True)
self.globalAction.setVisible(True) self.globalAction.setVisible(True)
self.menu.exec_(self.themeListWidget.mapToGlobal(point)) self.menu.exec_(self.themeListWidget.mapToGlobal(point))
def changeGlobalFromTab(self, themeName): def changeGlobalFromTab(self, theme_name):
""" """
Change the global theme when it is changed through the Themes settings Change the global theme when it is changed through the Themes settings
tab tab
""" """
log.debug(u'changeGlobalFromTab %s', themeName) log.debug(u'changeGlobalFromTab %s', theme_name)
for count in range (0, self.themeListWidget.count()): for count in range (0, self.themeListWidget.count()):
# reset the old name # reset the old name
item = self.themeListWidget.item(count) item = self.themeListWidget.item(count)
oldName = item.text() old_name = item.text()
newName = unicode(item.data(QtCore.Qt.UserRole).toString()) new_name = unicode(item.data(QtCore.Qt.UserRole).toString())
if oldName != newName: if old_name != new_name:
self.themeListWidget.item(count).setText(newName) self.themeListWidget.item(count).setText(new_name)
# Set the new name # Set the new name
if themeName == newName: if theme_name == new_name:
name = unicode(translate('OpenLP.ThemeManager', name = unicode(translate('OpenLP.ThemeManager',
'%s (default)')) % newName '%s (default)')) % new_name
self.themeListWidget.item(count).setText(name) self.themeListWidget.item(count).setText(name)
def changeGlobalFromScreen(self, index=-1): def changeGlobalFromScreen(self, index=-1):
@ -233,9 +230,9 @@ class ThemeManager(QtGui.QWidget):
selected_row = self.themeListWidget.currentRow() selected_row = self.themeListWidget.currentRow()
for count in range (0, self.themeListWidget.count()): for count in range (0, self.themeListWidget.count()):
item = self.themeListWidget.item(count) item = self.themeListWidget.item(count)
oldName = item.text() old_name = item.text()
# reset the old name # reset the old name
if oldName != unicode(item.data(QtCore.Qt.UserRole).toString()): if old_name != unicode(item.data(QtCore.Qt.UserRole).toString()):
self.themeListWidget.item(count).setText( self.themeListWidget.item(count).setText(
unicode(item.data(QtCore.Qt.UserRole).toString())) unicode(item.data(QtCore.Qt.UserRole).toString()))
# Set the new name # Set the new name
@ -271,19 +268,19 @@ class ThemeManager(QtGui.QWidget):
unicode(translate('OpenLP.ThemeManager', 'Rename %s theme?')), unicode(translate('OpenLP.ThemeManager', 'Rename %s theme?')),
False, False): False, False):
item = self.themeListWidget.currentItem() item = self.themeListWidget.currentItem()
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) old_theme_name = unicode(item.data(QtCore.Qt.UserRole).toString())
self.fileRenameForm.fileNameEdit.setText(oldThemeName) self.fileRenameForm.fileNameEdit.setText(old_theme_name)
if self.fileRenameForm.exec_(): if self.fileRenameForm.exec_():
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) new_theme_name = unicode(self.fileRenameForm.fileNameEdit.text())
if oldThemeName == newThemeName: if old_theme_name == new_theme_name:
return return
if self.checkIfThemeExists(newThemeName): if self.checkIfThemeExists(new_theme_name):
oldThemeData = self.getThemeData(oldThemeName) old_theme_data = self.getThemeData(old_theme_name)
self.cloneThemeData(oldThemeData, newThemeName) self.cloneThemeData(old_theme_data, new_theme_name)
self.deleteTheme(oldThemeName) self.deleteTheme(old_theme_name)
for plugin in self.mainwindow.pluginManager.plugins: for plugin in self.mainwindow.pluginManager.plugins:
if plugin.usesTheme(oldThemeName): if plugin.usesTheme(old_theme_name):
plugin.renameTheme(oldThemeName, newThemeName) plugin.renameTheme(old_theme_name, new_theme_name)
self.loadThemes() self.loadThemes()
def onCopyTheme(self): def onCopyTheme(self):
@ -291,30 +288,30 @@ class ThemeManager(QtGui.QWidget):
Copies an existing theme to a new name Copies an existing theme to a new name
""" """
item = self.themeListWidget.currentItem() item = self.themeListWidget.currentItem()
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) old_theme_name = unicode(item.data(QtCore.Qt.UserRole).toString())
self.fileRenameForm.fileNameEdit.setText( self.fileRenameForm.fileNameEdit.setText(
unicode(translate('OpenLP.ThemeManager', unicode(translate('OpenLP.ThemeManager',
'Copy of %s','Copy of <theme name>')) % oldThemeName) 'Copy of %s', 'Copy of <theme name>')) % old_theme_name)
if self.fileRenameForm.exec_(True): if self.fileRenameForm.exec_(True):
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) new_theme_name = unicode(self.fileRenameForm.fileNameEdit.text())
if self.checkIfThemeExists(newThemeName): if self.checkIfThemeExists(new_theme_name):
themeData = self.getThemeData(oldThemeName) theme_data = self.getThemeData(old_theme_name)
self.cloneThemeData(themeData, newThemeName) self.cloneThemeData(theme_data, new_theme_name)
def cloneThemeData(self, themeData, newThemeName): def cloneThemeData(self, theme_data, new_theme_name):
""" """
Takes a theme and makes a new copy of it as well as saving it. Takes a theme and makes a new copy of it as well as saving it.
""" """
log.debug(u'cloneThemeData') log.debug(u'cloneThemeData')
saveTo = None save_to = None
saveFrom = None save_from = None
if themeData.background_type == u'image': if theme_data.background_type == u'image':
saveTo = os.path.join(self.path, newThemeName, save_to = os.path.join(self.path, new_theme_name,
os.path.split(unicode(themeData.background_filename))[1]) os.path.split(unicode(theme_data.background_filename))[1])
saveFrom = themeData.background_filename save_from = theme_data.background_filename
themeData.theme_name = newThemeName theme_data.theme_name = new_theme_name
themeData.extend_image_filename(self.path) theme_data.extend_image_filename(self.path)
self.saveTheme(themeData, saveFrom, saveTo) self.saveTheme(theme_data, save_from, save_to)
def onEditTheme(self): def onEditTheme(self):
""" """
@ -328,10 +325,10 @@ class ThemeManager(QtGui.QWidget):
theme = self.getThemeData( theme = self.getThemeData(
unicode(item.data(QtCore.Qt.UserRole).toString())) unicode(item.data(QtCore.Qt.UserRole).toString()))
if theme.background_type == u'image': if theme.background_type == u'image':
self.oldBackgroundImage = theme.background_filename self.old_background_image = theme.background_filename
self.themeForm.theme = theme self.themeForm.theme = theme
self.themeForm.exec_(True) self.themeForm.exec_(True)
self.oldBackgroundImage = None self.old_background_image = None
def onDeleteTheme(self): def onDeleteTheme(self):
""" """
@ -357,10 +354,10 @@ class ThemeManager(QtGui.QWidget):
``theme`` ``theme``
The theme to delete. The theme to delete.
""" """
self.themelist.remove(theme) self.theme_list.remove(theme)
thumb = u'%s.png' % theme thumb = u'%s.png' % theme
delete_file(os.path.join(self.path, thumb)) delete_file(os.path.join(self.path, thumb))
delete_file(os.path.join(self.thumbPath, thumb)) delete_file(os.path.join(self.thumb_path, thumb))
try: try:
encoding = get_filesystem_encoding() encoding = get_filesystem_encoding()
shutil.rmtree(os.path.join(self.path, theme).encode(encoding)) shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
@ -385,10 +382,10 @@ class ThemeManager(QtGui.QWidget):
Receiver.send_message(u'cursor_busy') Receiver.send_message(u'cursor_busy')
if path: if path:
SettingsManager.set_last_dir(self.settingsSection, path, 1) SettingsManager.set_last_dir(self.settingsSection, path, 1)
themePath = os.path.join(path, theme + u'.otz') theme_path = os.path.join(path, theme + u'.otz')
zip = None zip = None
try: try:
zip = zipfile.ZipFile(themePath, u'w') zip = zipfile.ZipFile(theme_path, u'w')
source = os.path.join(self.path, theme) source = os.path.join(self.path, theme)
for files in os.walk(source): for files in os.walk(source):
for name in files[2]: for name in files[2]:
@ -438,9 +435,8 @@ class ThemeManager(QtGui.QWidget):
The plugins will call back in to get the real list if they want it. The plugins will call back in to get the real list if they want it.
""" """
log.debug(u'Load themes from dir') log.debug(u'Load themes from dir')
self.themelist = [] self.theme_list = []
self.themeListWidget.clear() self.themeListWidget.clear()
dirList = os.listdir(self.path)
files = SettingsManager.get_files(self.settingsSection, u'.png') files = SettingsManager.get_files(self.settingsSection, u'.png')
if firstTime: if firstTime:
self.firstTime() self.firstTime()
@ -457,29 +453,29 @@ class ThemeManager(QtGui.QWidget):
files = SettingsManager.get_files(self.settingsSection, u'.png') files = SettingsManager.get_files(self.settingsSection, u'.png')
# Sort the themes by its name considering language specific characters. # Sort the themes by its name considering language specific characters.
# lower() is needed for windows! # lower() is needed for windows!
files.sort(key=lambda filename: unicode(filename).lower(), files.sort(key=lambda file_name: unicode(file_name).lower(),
cmp=locale.strcoll) cmp=locale.strcoll)
# now process the file list of png files # now process the file list of png files
for name in files: for name in files:
# check to see file is in theme root directory # check to see file is in theme root directory
theme = os.path.join(self.path, name) theme = os.path.join(self.path, name)
if os.path.exists(theme): if os.path.exists(theme):
textName = os.path.splitext(name)[0] text_name = os.path.splitext(name)[0]
if textName == self.global_theme: if text_name == self.global_theme:
name = unicode(translate('OpenLP.ThemeManager', name = unicode(translate('OpenLP.ThemeManager',
'%s (default)')) % textName '%s (default)')) % text_name
else: else:
name = textName name = text_name
thumb = os.path.join(self.thumbPath, u'%s.png' % textName) thumb = os.path.join(self.thumb_path, u'%s.png' % text_name)
item_name = QtGui.QListWidgetItem(name) item_name = QtGui.QListWidgetItem(name)
if validate_thumb(theme, thumb): if validate_thumb(theme, thumb):
icon = build_icon(thumb) icon = build_icon(thumb)
else: else:
icon = create_thumb(theme, thumb) icon = create_thumb(theme, thumb)
item_name.setIcon(icon) item_name.setIcon(icon)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(textName)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(text_name))
self.themeListWidget.addItem(item_name) self.themeListWidget.addItem(item_name)
self.themelist.append(textName) self.theme_list.append(text_name)
self._pushThemes() self._pushThemes()
def _pushThemes(self): def _pushThemes(self):
@ -492,86 +488,111 @@ class ThemeManager(QtGui.QWidget):
""" """
Return the list of loaded themes Return the list of loaded themes
""" """
return self.themelist return self.theme_list
def getThemeData(self, themeName): def getThemeData(self, theme_name):
""" """
Returns a theme object from an XML file Returns a theme object from an XML file
``themeName`` ``theme_name``
Name of the theme to load from file Name of the theme to load from file
""" """
log.debug(u'getthemedata for theme %s', themeName) log.debug(u'getthemedata for theme %s', theme_name)
xmlFile = os.path.join(self.path, unicode(themeName), xml_file = os.path.join(self.path, unicode(theme_name),
unicode(themeName) + u'.xml') unicode(theme_name) + u'.xml')
xml = get_text_file_string(xmlFile) xml = get_text_file_string(xml_file)
if not xml: if not xml:
log.debug("No theme data - using default theme") log.debug("No theme data - using default theme")
return ThemeXML() return ThemeXML()
else: else:
return self._createThemeFromXml(xml, self.path) return self._createThemeFromXml(xml, self.path)
def unzipTheme(self, filename, dir): def overWriteMessageBox(self, theme_name):
ret = QtGui.QMessageBox.question(self,
translate('OpenLP.ThemeManager', 'Theme Already Exists'),
translate('OpenLP.ThemeManager',
'Theme %s already exists. Do you want to replace it?'
% theme_name),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
return ret == QtGui.QMessageBox.Yes
def unzipTheme(self, file_name, dir):
""" """
Unzip the theme, remove the preview file if stored Unzip the theme, remove the preview file if stored
Generate a new preview file. Check the XML theme version and upgrade if Generate a new preview file. Check the XML theme version and upgrade if
necessary. necessary.
""" """
log.debug(u'Unzipping theme %s', filename) log.debug(u'Unzipping theme %s', file_name)
filename = unicode(filename) file_name = unicode(file_name)
zip = None zip = None
outfile = None out_file = None
filexml = None file_xml = None
try: try:
zip = zipfile.ZipFile(filename) zip = zipfile.ZipFile(file_name)
themename = None xml_file = filter(lambda name:
for file in zip.namelist(): os.path.splitext(name)[1].lower() == u'.xml', zip.namelist())
# Handle UTF-8 files if len(xml_file) != 1:
ucsfile = file_is_unicode(file) log.exception(u'Theme contains "%s" XML files' % len(xml_file))
if not ucsfile: raise Exception(u'validation')
# Handle native Unicode files from Windows xml_tree = ElementTree(element=XML(zip.read(xml_file[0]))).getroot()
ucsfile = file v1_background = xml_tree.find(u'BackgroundType')
osfile = unicode(QtCore.QDir.toNativeSeparators(ucsfile)) if v1_background is not None:
theme_dir = None theme_name, file_xml, out_file, abort_import = self.unzipVersion122(dir, zip,
if osfile.endswith(os.path.sep): xml_file[0], xml_tree, v1_background, out_file)
theme_dir = os.path.join(dir, osfile)
check_directory_exists(theme_dir)
else: else:
fullpath = os.path.join(dir, osfile) theme_name = xml_tree.find(u'name').text.strip()
names = osfile.split(os.path.sep) theme_folder = os.path.join(dir, theme_name)
if len(names) > 1: theme_exists = os.path.exists(theme_folder)
# not preview file if theme_exists and not self.overWriteMessageBox(theme_name):
if themename is None: abort_import = True
themename = names[0] return
if theme_dir is None:
theme_dir = os.path.join(dir, names[0])
check_directory_exists(theme_dir)
if os.path.splitext(ucsfile)[1].lower() in [u'.xml']:
xml_data = zip.read(file)
xml_data = file_is_unicode(xml_data)
if not xml_data:
break
filexml = self._checkVersionAndConvert(xml_data)
outfile = open(fullpath, u'w')
outfile.write(filexml.encode(u'utf-8'))
else: else:
outfile = open(fullpath, u'wb') abort_import = False
outfile.write(zip.read(file)) for name in zip.namelist():
except (IOError, NameError, zipfile.BadZipfile): try:
critical_error_message_box( uname = unicode(name, u'utf-8')
translate('OpenLP.ThemeManager', 'Validation Error'), except UnicodeDecodeError:
translate('OpenLP.ThemeManager', 'File is not a valid theme.')) log.exception(u'Theme file contains non utf-8 filename'
log.exception(u'Importing theme from zip failed %s' % filename) u' "%s"' % name.decode(u'utf-8', u'replace'))
raise Exception(u'validation')
uname = uname.replace(u'/', os.path.sep)
split_name = uname.split(os.path.sep)
if split_name[-1] == u'' or len(split_name) == 1:
# is directory or preview file
continue
full_name = os.path.join(dir, uname)
check_directory_exists(os.path.dirname(full_name))
if os.path.splitext(uname)[1].lower() == u'.xml':
file_xml = unicode(zip.read(name), u'utf-8')
out_file = open(full_name, u'w')
out_file.write(file_xml.encode(u'utf-8'))
else:
out_file = open(full_name, u'wb')
out_file.write(zip.read(name))
out_file.close()
except (IOError, zipfile.BadZipfile):
log.exception(u'Importing theme from zip failed %s' % file_name)
raise Exception(u'validation')
except Exception as info:
if unicode(info) == u'validation':
critical_error_message_box(translate('OpenLP.ThemeManager',
'Validation Error'), translate('OpenLP.ThemeManager',
'File is not a valid theme.'))
else:
raise
finally: finally:
# Close the files, to be able to continue creating the theme. # Close the files, to be able to continue creating the theme.
if zip: if zip:
zip.close() zip.close()
if outfile: if out_file:
outfile.close() out_file.close()
if not abort_import:
# As all files are closed, we can create the Theme. # As all files are closed, we can create the Theme.
if filexml: if file_xml:
theme = self._createThemeFromXml(filexml, self.path) theme = self._createThemeFromXml(file_xml, self.path)
self.generateAndSaveImage(dir, themename, theme) self.generateAndSaveImage(dir, theme_name, theme)
# Only show the error message, when IOError was not raised (in this # Only show the error message, when IOError was not raised (in this
# case the error message has already been shown). # case the error message has already been shown).
elif zip is not None: elif zip is not None:
@ -580,16 +601,50 @@ class ThemeManager(QtGui.QWidget):
translate('OpenLP.ThemeManager', translate('OpenLP.ThemeManager',
'File is not a valid theme.')) 'File is not a valid theme.'))
log.exception(u'Theme file does not contain XML data %s' % log.exception(u'Theme file does not contain XML data %s' %
filename) file_name)
def checkIfThemeExists(self, themeName): def unzipVersion122(self, dir, zip, xml_file, xml_tree, background, out_file):
"""
Unzip openlp.org 1.2x theme file and upgrade the theme xml. When calling
this method, please keep in mind, that some parameters are redundant.
"""
theme_name = xml_tree.find(u'Name').text.strip()
theme_name = self.bad_v1_name_chars.sub(u'', theme_name)
theme_folder = os.path.join(dir, theme_name)
theme_exists = os.path.exists(theme_folder)
if theme_exists and not self.overWriteMessageBox(theme_name):
return '', '', '', True
themedir = os.path.join(dir, theme_name)
check_directory_exists(themedir)
file_xml = unicode(zip.read(xml_file), u'utf-8')
file_xml = self._migrateVersion122(file_xml)
out_file = open(os.path.join(themedir, theme_name + u'.xml'), u'w')
out_file.write(file_xml.encode(u'utf-8'))
out_file.close()
if background.text.strip() == u'2':
image_name = xml_tree.find(u'BackgroundParameter1').text.strip()
# image file has same extension and is in subfolder
imagefile = filter(lambda name: os.path.splitext(name)[1].lower()
== os.path.splitext(image_name)[1].lower() and name.find(r'/'),
zip.namelist())
if len(imagefile) >= 1:
out_file = open(os.path.join(themedir, image_name), u'wb')
out_file.write(zip.read(imagefile[0]))
out_file.close()
else:
log.exception(u'Theme file does not contain image file "%s"' %
image_name.decode(u'utf-8', u'replace'))
raise Exception(u'validation')
return theme_name, file_xml, out_file, False
def checkIfThemeExists(self, theme_name):
""" """
Check if theme already exists and displays error message Check if theme already exists and displays error message
``themeName`` ``theme_name``
Name of the Theme to test Name of the Theme to test
""" """
theme_dir = os.path.join(self.path, themeName) theme_dir = os.path.join(self.path, theme_name)
if os.path.exists(theme_dir): if os.path.exists(theme_dir):
critical_error_message_box( critical_error_message_box(
translate('OpenLP.ThemeManager', 'Validation Error'), translate('OpenLP.ThemeManager', 'Validation Error'),
@ -598,12 +653,12 @@ class ThemeManager(QtGui.QWidget):
return False return False
return True return True
def saveTheme(self, theme, imageFrom, imageTo): def saveTheme(self, theme, image_from, image_to):
""" """
Called by thememaintenance Dialog to save the theme Called by thememaintenance Dialog to save the theme
and to trigger the reload of the theme list and to trigger the reload of the theme list
""" """
self._writeTheme(theme, imageFrom, imageTo) self._writeTheme(theme, image_from, image_to)
if theme.background_type == \ if theme.background_type == \
BackgroundType.to_string(BackgroundType.Image): BackgroundType.to_string(BackgroundType.Image):
self.mainwindow.imageManager.update_image(theme.theme_name, self.mainwindow.imageManager.update_image(theme.theme_name,
@ -611,7 +666,7 @@ class ThemeManager(QtGui.QWidget):
self.mainwindow.imageManager.process_updates() self.mainwindow.imageManager.process_updates()
self.loadThemes() self.loadThemes()
def _writeTheme(self, theme, imageFrom, imageTo): def _writeTheme(self, theme, image_from, image_to):
""" """
Writes the theme to the disk and handles the background image if Writes the theme to the disk and handles the background image if
necessary necessary
@ -622,24 +677,24 @@ class ThemeManager(QtGui.QWidget):
theme_dir = os.path.join(self.path, name) theme_dir = os.path.join(self.path, name)
check_directory_exists(theme_dir) check_directory_exists(theme_dir)
theme_file = os.path.join(theme_dir, name + u'.xml') theme_file = os.path.join(theme_dir, name + u'.xml')
if self.oldBackgroundImage and \ if self.old_background_image and \
imageTo != self.oldBackgroundImage: image_to != self.old_background_image:
delete_file(self.oldBackgroundImage) delete_file(self.old_background_image)
outfile = None out_file = None
try: try:
outfile = open(theme_file, u'w') out_file = open(theme_file, u'w')
outfile.write(theme_pretty_xml) out_file.write(theme_pretty_xml)
except IOError: except IOError:
log.exception(u'Saving theme to file failed') log.exception(u'Saving theme to file failed')
finally: finally:
if outfile: if out_file:
outfile.close() out_file.close()
if imageFrom and imageFrom != imageTo: if image_from and image_from != image_to:
try: try:
encoding = get_filesystem_encoding() encoding = get_filesystem_encoding()
shutil.copyfile( shutil.copyfile(
unicode(imageFrom).encode(encoding), unicode(image_from).encode(encoding),
unicode(imageTo).encode(encoding)) unicode(image_to).encode(encoding))
except IOError: except IOError:
log.exception(u'Failed to save theme image') log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme) self.generateAndSaveImage(self.path, name, theme)
@ -647,39 +702,39 @@ class ThemeManager(QtGui.QWidget):
def generateAndSaveImage(self, dir, name, theme): def generateAndSaveImage(self, dir, name, theme):
log.debug(u'generateAndSaveImage %s %s', dir, name) log.debug(u'generateAndSaveImage %s %s', dir, name)
frame = self.generateImage(theme) frame = self.generateImage(theme)
samplepathname = os.path.join(self.path, name + u'.png') sample_path_name = os.path.join(self.path, name + u'.png')
if os.path.exists(samplepathname): if os.path.exists(sample_path_name):
os.unlink(samplepathname) os.unlink(sample_path_name)
frame.save(samplepathname, u'png') frame.save(sample_path_name, u'png')
thumb = os.path.join(self.thumbPath, u'%s.png' % name) thumb = os.path.join(self.thumb_path, u'%s.png' % name)
create_thumb(samplepathname, thumb, False) create_thumb(sample_path_name, thumb, False)
log.debug(u'Theme image written to %s', samplepathname) log.debug(u'Theme image written to %s', sample_path_name)
def updatePreviewImages(self): def updatePreviewImages(self):
""" """
Called to update the themes' preview images. Called to update the themes' preview images.
""" """
self.mainwindow.displayProgressBar(len(self.themelist)) self.mainwindow.displayProgressBar(len(self.theme_list))
for theme in self.themelist: for theme in self.theme_list:
self.mainwindow.incrementProgressBar() self.mainwindow.incrementProgressBar()
self.generateAndSaveImage( self.generateAndSaveImage(
self.path, theme, self.getThemeData(theme)) self.path, theme, self.getThemeData(theme))
self.mainwindow.finishedProgressBar() self.mainwindow.finishedProgressBar()
self.loadThemes() self.loadThemes()
def generateImage(self, themeData, forcePage=False): def generateImage(self, theme_data, forcePage=False):
""" """
Call the renderer to build a Sample Image Call the renderer to build a Sample Image
``themeData`` ``theme_data``
The theme to generated a preview for. The theme to generated a preview for.
``forcePage`` ``forcePage``
Flag to tell message lines per page need to be generated. Flag to tell message lines per page need to be generated.
""" """
log.debug(u'generateImage \n%s ', themeData) log.debug(u'generateImage \n%s ', theme_data)
return self.mainwindow.renderer.generate_preview( return self.mainwindow.renderer.generate_preview(
themeData, forcePage) theme_data, forcePage)
def getPreviewImage(self, theme): def getPreviewImage(self, theme):
""" """
@ -692,31 +747,15 @@ class ThemeManager(QtGui.QWidget):
image = os.path.join(self.path, theme + u'.png') image = os.path.join(self.path, theme + u'.png')
return image return image
def _checkVersionAndConvert(self, xml_data): def _createThemeFromXml(self, theme_xml, path):
"""
Check if a theme is from OpenLP version 1
``xml_data``
Theme XML to check the version of
"""
log.debug(u'checkVersion1 ')
theme = xml_data.encode(u'ascii', u'xmlcharrefreplace')
tree = ElementTree(element=XML(theme)).getroot()
# look for old version 1 tags
if tree.find(u'BackgroundType') is None:
return xml_data
else:
return self._migrateVersion122(xml_data)
def _createThemeFromXml(self, themeXml, path):
""" """
Return a theme object using information parsed from XML Return a theme object using information parsed from XML
``themeXml`` ``theme_xml``
The XML data to load into the theme The XML data to load into the theme
""" """
theme = ThemeXML() theme = ThemeXML()
theme.parse(themeXml) theme.parse(theme_xml)
theme.extend_image_filename(path) theme.extend_image_filename(path)
return theme return theme
@ -771,50 +810,53 @@ class ThemeManager(QtGui.QWidget):
Version 1 theme to convert Version 1 theme to convert
""" """
theme = Theme(xml_data) theme = Theme(xml_data)
newtheme = ThemeXML() new_theme = ThemeXML()
newtheme.theme_name = theme.Name new_theme.theme_name = self.bad_v1_name_chars.sub(u'', theme.Name)
if theme.BackgroundType == 0: if theme.BackgroundType == 0:
newtheme.background_type = \ new_theme.background_type = \
BackgroundType.to_string(BackgroundType.Solid) BackgroundType.to_string(BackgroundType.Solid)
newtheme.background_color = \ new_theme.background_color = \
unicode(theme.BackgroundParameter1.name()) unicode(theme.BackgroundParameter1.name())
elif theme.BackgroundType == 1: elif theme.BackgroundType == 1:
newtheme.background_type = \ new_theme.background_type = \
BackgroundType.to_string(BackgroundType.Gradient) BackgroundType.to_string(BackgroundType.Gradient)
newtheme.background_direction = \ new_theme.background_direction = \
BackgroundGradientType. \ BackgroundGradientType. \
to_string(BackgroundGradientType.Horizontal) to_string(BackgroundGradientType.Horizontal)
if theme.BackgroundParameter3.name() == 1: if theme.BackgroundParameter3.name() == 1:
newtheme.background_direction = \ new_theme.background_direction = \
BackgroundGradientType. \ BackgroundGradientType. \
to_string(BackgroundGradientType.Horizontal) to_string(BackgroundGradientType.Horizontal)
newtheme.background_start_color = \ new_theme.background_start_color = \
unicode(theme.BackgroundParameter1.name()) unicode(theme.BackgroundParameter1.name())
newtheme.background_end_color = \ new_theme.background_end_color = \
unicode(theme.BackgroundParameter2.name()) unicode(theme.BackgroundParameter2.name())
else: elif theme.BackgroundType == 2:
newtheme.background_type = \ new_theme.background_type = \
BackgroundType.to_string(BackgroundType.Image) BackgroundType.to_string(BackgroundType.Image)
newtheme.background_filename = unicode(theme.BackgroundParameter1) new_theme.background_filename = unicode(theme.BackgroundParameter1)
newtheme.font_main_name = theme.FontName elif theme.BackgroundType == 3:
newtheme.font_main_color = unicode(theme.FontColor.name()) new_theme.background_type = \
newtheme.font_main_size = theme.FontProportion * 3 BackgroundType.to_string(BackgroundType.Transparent)
newtheme.font_footer_name = theme.FontName new_theme.font_main_name = theme.FontName
newtheme.font_footer_color = unicode(theme.FontColor.name()) new_theme.font_main_color = unicode(theme.FontColor.name())
newtheme.font_main_shadow = False new_theme.font_main_size = theme.FontProportion * 3
new_theme.font_footer_name = theme.FontName
new_theme.font_footer_color = unicode(theme.FontColor.name())
new_theme.font_main_shadow = False
if theme.Shadow == 1: if theme.Shadow == 1:
newtheme.font_main_shadow = True new_theme.font_main_shadow = True
newtheme.font_main_shadow_color = unicode(theme.ShadowColor.name()) new_theme.font_main_shadow_color = unicode(theme.ShadowColor.name())
if theme.Outline == 1: if theme.Outline == 1:
newtheme.font_main_outline = True new_theme.font_main_outline = True
newtheme.font_main_outline_color = \ new_theme.font_main_outline_color = \
unicode(theme.OutlineColor.name()) unicode(theme.OutlineColor.name())
vAlignCorrection = VerticalType.Top vAlignCorrection = VerticalType.Top
if theme.VerticalAlign == 2: if theme.VerticalAlign == 2:
vAlignCorrection = VerticalType.Middle vAlignCorrection = VerticalType.Middle
elif theme.VerticalAlign == 1: elif theme.VerticalAlign == 1:
vAlignCorrection = VerticalType.Bottom vAlignCorrection = VerticalType.Bottom
newtheme.display_horizontal_align = theme.HorizontalAlign new_theme.display_horizontal_align = theme.HorizontalAlign
newtheme.display_vertical_align = vAlignCorrection new_theme.display_vertical_align = vAlignCorrection
return newtheme.extract_xml() return new_theme.extract_xml()

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -54,7 +54,7 @@ class Ui_ThemeWizard(object):
self.backgroundLabel = QtGui.QLabel(self.backgroundPage) self.backgroundLabel = QtGui.QLabel(self.backgroundPage)
self.backgroundLabel.setObjectName(u'BackgroundLabel') self.backgroundLabel.setObjectName(u'BackgroundLabel')
self.backgroundComboBox = QtGui.QComboBox(self.backgroundPage) self.backgroundComboBox = QtGui.QComboBox(self.backgroundPage)
self.backgroundComboBox.addItems([u'', u'', u'']) self.backgroundComboBox.addItems([u'', u'', u'', u''])
self.backgroundComboBox.setObjectName(u'BackgroundComboBox') self.backgroundComboBox.setObjectName(u'BackgroundComboBox')
self.backgroundTypeLayout.addRow(self.backgroundLabel, self.backgroundTypeLayout.addRow(self.backgroundLabel,
self.backgroundComboBox) self.backgroundComboBox)
@ -126,6 +126,12 @@ class Ui_ThemeWizard(object):
self.imageLayout.addRow(self.imageLabel, self.imageFileLayout) self.imageLayout.addRow(self.imageLabel, self.imageFileLayout)
self.imageLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.spacer) self.imageLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.imageWidget) self.backgroundStack.addWidget(self.imageWidget)
self.transparentWidget = QtGui.QWidget(self.backgroundPage)
self.transparentWidget.setObjectName(u'TransparentWidget')
self.transparentLayout = QtGui.QFormLayout(self.transparentWidget)
self.transparentLayout.setMargin(0)
self.transparentLayout.setObjectName(u'TransparentLayout')
self.backgroundStack.addWidget(self.transparentWidget)
self.backgroundLayout.addLayout(self.backgroundStack) self.backgroundLayout.addLayout(self.backgroundStack)
themeWizard.addPage(self.backgroundPage) themeWizard.addPage(self.backgroundPage)
# Main Area Page # Main Area Page
@ -432,6 +438,8 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'Gradient')) translate('OpenLP.ThemeWizard', 'Gradient'))
self.backgroundComboBox.setItemText( self.backgroundComboBox.setItemText(
BackgroundType.Image, UiStrings().Image) BackgroundType.Image, UiStrings().Image)
self.backgroundComboBox.setItemText(BackgroundType.Transparent,
translate('OpenLP.ThemeWizard', 'Transparent'))
self.colorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.colorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:'))
self.gradientStartLabel.setText( self.gradientStartLabel.setText(
translate(u'OpenLP.ThemeWizard', 'Starting color:')) translate(u'OpenLP.ThemeWizard', 'Starting color:'))

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -47,7 +47,7 @@ class WizardStrings(object):
CCLI = u'CCLI/SongSelect' CCLI = u'CCLI/SongSelect'
CSV = u'CSV' CSV = u'CSV'
EW = u'EasyWorship' EW = u'EasyWorship'
ES = u'EasiSlides' ES = u'EasySlides'
FP = u'Foilpresenter' FP = u'Foilpresenter'
OL = u'OpenLyrics' OL = u'OpenLyrics'
OS = u'OpenSong' OS = u'OpenSong'

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -53,6 +53,8 @@ APPLICATION_VERSION = {}
IMAGES_FILTER = None IMAGES_FILTER = None
UNO_CONNECTION_TYPE = u'pipe' UNO_CONNECTION_TYPE = u'pipe'
#UNO_CONNECTION_TYPE = u'socket' #UNO_CONNECTION_TYPE = u'socket'
CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
VERSION_SPLITTER = re.compile(r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?') VERSION_SPLITTER = re.compile(r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?')
class VersionThread(QtCore.QThread): class VersionThread(QtCore.QThread):
@ -400,7 +402,7 @@ def clean_filename(filename):
""" """
if not isinstance(filename, unicode): if not isinstance(filename, unicode):
filename = unicode(filename, u'utf-8') filename = unicode(filename, u'utf-8')
return re.sub(r'[/\\?*|<>\[\]":<>+%]+', u'_', filename).strip(u'_') return INVALID_FILE_CHARS.sub(u'_', CONTROL_CHARS.sub(u'', filename))
def delete_file(file_path_name): def delete_file(file_path_name):
""" """
@ -455,26 +457,6 @@ def get_web_page(url, header=None, update_openlp=False):
log.debug(page) log.debug(page)
return page return page
def file_is_unicode(filename):
"""
Checks if a file is valid unicode and returns the unicode decoded file or
None.
``filename``
File to check is valid unicode.
"""
if not filename:
return None
ucsfile = None
try:
ucsfile = filename.decode(u'utf-8')
except UnicodeDecodeError:
log.exception(u'Filename "%s" is not valid UTF-8' %
filename.decode(u'utf-8', u'replace'))
if not ucsfile:
return None
return ucsfile
def get_uno_command(): def get_uno_command():
""" """
Returns the UNO command to launch an openoffice.org instance. Returns the UNO command to launch an openoffice.org instance.
@ -507,5 +489,5 @@ from actions import ActionList
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version', __all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
u'ActionList', u'get_web_page', u'file_is_unicode', u'get_uno_command', u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance',
u'get_uno_instance', u'delete_file', u'clean_filename'] u'delete_file', u'clean_filename']

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -188,6 +188,7 @@ class ActionList(object):
actions or categories. actions or categories.
""" """
instance = None instance = None
shortcut_map = {}
def __init__(self): def __init__(self):
self.categories = CategoryList() self.categories = CategoryList()
@ -224,17 +225,45 @@ class ActionList(object):
self.categories[category].actions.append(action) self.categories[category].actions.append(action)
else: else:
self.categories[category].actions.add(action, weight) self.categories[category].actions.add(action, weight)
if not category:
# Stop here, as this action is not configurable.
return
# Load the shortcut from the config. # Load the shortcut from the config.
settings = QtCore.QSettings() settings = QtCore.QSettings()
settings.beginGroup(u'shortcuts') settings.beginGroup(u'shortcuts')
shortcuts = settings.value(action.objectName(), shortcuts = settings.value(action.objectName(),
QtCore.QVariant(action.shortcuts())).toStringList() QtCore.QVariant(action.shortcuts())).toStringList()
settings.endGroup()
if not shortcuts:
action.setShortcuts([])
return
# We have to do this to ensure that the loaded shortcut list e. g.
# STRG+O (German) is converted to CTRL+O, which is only done when we
# convert the strings in this way (QKeySequence -> QString -> unicode).
shortcuts = map(QtGui.QKeySequence, shortcuts)
shortcuts = map(unicode, map(QtGui.QKeySequence.toString, shortcuts))
# Check the alternate shortcut first, to avoid problems when the
# alternate shortcut becomes the primary shortcut after removing the
# (initial) primary shortcut due to conflicts.
if len(shortcuts) == 2:
existing_actions = ActionList.shortcut_map.get(shortcuts[1], [])
# Check for conflicts with other actions considering the shortcut
# context.
if self._is_shortcut_available(existing_actions, action):
actions = ActionList.shortcut_map.get(shortcuts[1], [])
actions.append(action)
ActionList.shortcut_map[shortcuts[1]] = actions
else:
shortcuts.remove(shortcuts[1])
# Check the primary shortcut.
existing_actions = ActionList.shortcut_map.get(shortcuts[0], [])
# Check for conflicts with other actions considering the shortcut
# context.
if self._is_shortcut_available(existing_actions, action):
actions = ActionList.shortcut_map.get(shortcuts[0], [])
actions.append(action)
ActionList.shortcut_map[shortcuts[0]] = actions
else:
shortcuts.remove(shortcuts[0])
action.setShortcuts( action.setShortcuts(
[QtGui.QKeySequence(shortcut) for shortcut in shortcuts]) [QtGui.QKeySequence(shortcut) for shortcut in shortcuts])
settings.endGroup()
def remove_action(self, action, category=None): def remove_action(self, action, category=None):
""" """
@ -242,7 +271,7 @@ class ActionList(object):
automatically removed. automatically removed.
``action`` ``action``
The QAction object to be removed. The ``QAction`` object to be removed.
``category`` ``category``
The name (unicode string) of the category, which contains the The name (unicode string) of the category, which contains the
@ -252,8 +281,17 @@ class ActionList(object):
return return
self.categories[category].actions.remove(action) self.categories[category].actions.remove(action)
# Remove empty categories. # Remove empty categories.
if len(self.categories[category].actions) == 0: if not self.categories[category].actions:
self.categories.remove(category) self.categories.remove(category)
shortcuts = map(unicode,
map(QtGui.QKeySequence.toString, action.shortcuts()))
for shortcut in shortcuts:
# Remove action from the list of actions which are using this
# shortcut.
ActionList.shortcut_map[shortcut].remove(action)
# Remove empty entries.
if not ActionList.shortcut_map[shortcut]:
del ActionList.shortcut_map[shortcut]
def add_category(self, name, weight): def add_category(self, name, weight):
""" """
@ -275,6 +313,73 @@ class ActionList(object):
return return
self.categories.add(name, weight) self.categories.add(name, weight)
def update_shortcut_map(self, action, old_shortcuts):
"""
Remove the action for the given ``old_shortcuts`` from the
``shortcut_map`` to ensure its up-to-dateness.
**Note**: The new action's shortcuts **must** be assigned to the given
``action`` **before** calling this method.
``action``
The action whose shortcuts are supposed to be updated in the
``shortcut_map``.
``old_shortcuts``
A list of unicode keysequences.
"""
for old_shortcut in old_shortcuts:
# Remove action from the list of actions which are using this
# shortcut.
ActionList.shortcut_map[old_shortcut].remove(action)
# Remove empty entries.
if not ActionList.shortcut_map[old_shortcut]:
del ActionList.shortcut_map[old_shortcut]
new_shortcuts = map(unicode,
map(QtGui.QKeySequence.toString, action.shortcuts()))
# Add the new shortcuts to the map.
for new_shortcut in new_shortcuts:
existing_actions = ActionList.shortcut_map.get(new_shortcut, [])
existing_actions.append(action)
ActionList.shortcut_map[new_shortcut] = existing_actions
def _is_shortcut_available(self, existing_actions, action):
"""
Checks if the given ``action`` may use its assigned shortcut(s) or not.
Returns ``True`` or ``False.
``existing_actions``
A list of actions which already use a particular shortcut.
``action``
The action which wants to use a particular shortcut.
"""
local = action.shortcutContext() in \
[QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]
affected_actions = filter(lambda a: isinstance(a, QtGui.QAction),
self.getAllChildObjects(action.parent())) if local else []
for existing_action in existing_actions:
if action is existing_action:
continue
if not local or existing_action in affected_actions:
return False
if existing_action.shortcutContext() \
in [QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
return False
elif action in self.getAllChildObjects(existing_action.parent()):
return False
return True
def getAllChildObjects(self, qobject):
"""
Goes recursively through the children of ``qobject`` and returns a list
of all child objects.
"""
children = [child for child in qobject.children()]
for child in qobject.children():
children.append(self.getAllChildObjects(child))
return children
class CategoryOrder(object): class CategoryOrder(object):
""" """

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -31,7 +31,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.db import Manager from openlp.core.lib.db import Manager
from openlp.core.lib.ui import icon_action, UiStrings from openlp.core.lib.ui import create_action, UiStrings
from openlp.core.lib.theme import VerticalType from openlp.core.lib.theme import VerticalType
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
@ -133,16 +133,12 @@ class AlertsPlugin(Plugin):
use it as their parent. use it as their parent.
""" """
log.info(u'add tools menu') log.info(u'add tools menu')
self.toolsAlertItem = icon_action(tools_menu, u'toolsAlertItem', self.toolsAlertItem = create_action(tools_menu, u'toolsAlertItem',
u':/plugins/plugin_alerts.png') text=translate('AlertsPlugin', '&Alert'),
self.toolsAlertItem.setText(translate('AlertsPlugin', '&Alert')) icon=u':/plugins/plugin_alerts.png',
self.toolsAlertItem.setStatusTip( statustip=translate('AlertsPlugin', 'Show an alert message.'),
translate('AlertsPlugin', 'Show an alert message.')) visible=False, shortcuts=[u'F7'], triggers=self.onAlertsTrigger)
self.toolsAlertItem.setShortcut(u'F7')
self.serviceManager.mainwindow.toolsMenu.addAction(self.toolsAlertItem) self.serviceManager.mainwindow.toolsMenu.addAction(self.toolsAlertItem)
QtCore.QObject.connect(self.toolsAlertItem,
QtCore.SIGNAL(u'triggered()'), self.onAlertsTrigger)
self.toolsAlertItem.setVisible(False)
def initialise(self): def initialise(self):
log.info(u'Alerts Initialising') log.info(u'Alerts Initialising')

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -27,10 +27,10 @@
import logging import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.ui import base_action, UiStrings from openlp.core.lib.ui import create_action, UiStrings
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
from openlp.plugins.bibles.forms import BibleUpgradeForm from openlp.plugins.bibles.forms import BibleUpgradeForm
@ -93,19 +93,16 @@ class BiblePlugin(Plugin):
self.onToolsUpgradeItemTriggered() self.onToolsUpgradeItemTriggered()
def addImportMenuItem(self, import_menu): def addImportMenuItem(self, import_menu):
self.importBibleItem = base_action(import_menu, u'importBibleItem') self.importBibleItem = create_action(import_menu, u'importBibleItem',
self.importBibleItem.setText(translate('BiblesPlugin', '&Bible')) text=translate('BiblesPlugin', '&Bible'), visible=False,
triggers=self.onBibleImportClick)
import_menu.addAction(self.importBibleItem) import_menu.addAction(self.importBibleItem)
# signals and slots
QtCore.QObject.connect(self.importBibleItem,
QtCore.SIGNAL(u'triggered()'), self.onBibleImportClick)
self.importBibleItem.setVisible(False)
def addExportMenuItem(self, export_menu): def addExportMenuItem(self, export_menu):
self.exportBibleItem = base_action(export_menu, u'exportBibleItem') self.exportBibleItem = create_action(export_menu, u'exportBibleItem',
self.exportBibleItem.setText(translate('BiblesPlugin', '&Bible')) text=translate('BiblesPlugin', '&Bible'),
visible=False)
export_menu.addAction(self.exportBibleItem) export_menu.addAction(self.exportBibleItem)
self.exportBibleItem.setVisible(False)
def addToolsMenuItem(self, tools_menu): def addToolsMenuItem(self, tools_menu):
""" """
@ -117,17 +114,12 @@ class BiblePlugin(Plugin):
use it as their parent. use it as their parent.
""" """
log.debug(u'add tools menu') log.debug(u'add tools menu')
self.toolsUpgradeItem = QtGui.QAction(tools_menu) self.toolsUpgradeItem = create_action(tools_menu, u'toolsUpgradeItem',
self.toolsUpgradeItem.setObjectName(u'toolsUpgradeItem') text=translate('BiblesPlugin', '&Upgrade older Bibles'),
self.toolsUpgradeItem.setText( statustip=translate('BiblesPlugin',
translate('BiblesPlugin', '&Upgrade older Bibles')) 'Upgrade the Bible databases to the latest format.'),
self.toolsUpgradeItem.setStatusTip( visible=False, triggers=self.onToolsUpgradeItemTriggered)
translate('BiblesPlugin', 'Upgrade the Bible databases to the '
'latest format.'))
tools_menu.addAction(self.toolsUpgradeItem) tools_menu.addAction(self.toolsUpgradeItem)
QtCore.QObject.connect(self.toolsUpgradeItem,
QtCore.SIGNAL(u'triggered()'), self.onToolsUpgradeItemTriggered)
self.toolsUpgradeItem.setVisible(False)
def onToolsUpgradeItemTriggered(self): def onToolsUpgradeItemTriggered(self):
""" """

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Portions copyright (c) 2008-2012 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, # # Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, # # Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund # # Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Portions copyright (c) 2008-2012 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # # Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # # Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund # # Tibble, Carsten Tinggaard, Frode Woldsund #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Portions copyright (c) 2008-2012 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # # Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # # Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund # # Tibble, Carsten Tinggaard, Frode Woldsund #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Portions copyright (c) 2008-2012 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # # Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # # Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund # # Tibble, Carsten Tinggaard, Frode Woldsund #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # # Portions copyright (c) 2008-2012 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # # Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # # Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund # # Tibble, Carsten Tinggaard, Frode Woldsund #

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -31,8 +31,16 @@ plugin.
import logging import logging
import re import re
from PyQt4 import QtCore
from openlp.core.lib import translate
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
REFERENCE_MATCHES = {}
REFERENCE_SEPARATORS = {}
class LayoutStyle(object): class LayoutStyle(object):
""" """
An enumeration for bible screen layout styles. An enumeration for bible screen layout styles.
@ -52,41 +60,198 @@ class DisplayStyle(object):
Square = 3 Square = 3
class LanguageSelection(object):
"""
An enumeration for bible bookname language.
And standard strings for use throughout the bibles plugin.
"""
Bible = 0
Application = 1
English = 2
class BibleStrings(object):
"""
Provide standard strings for objects to use.
"""
__instance__ = None
def __new__(cls):
"""
Override the default object creation method to return a single instance.
"""
if not cls.__instance__:
cls.__instance__ = object.__new__(cls)
return cls.__instance__
def __init__(self):
"""
These strings should need a good reason to be retranslated elsewhere.
"""
self.Booknames = {
u'Gen': translate('BiblesPlugin', 'Genesis'),
u'Exod': translate('BiblesPlugin', 'Exodus'),
u'Lev': translate('BiblesPlugin', 'Leviticus'),
u'Num': translate('BiblesPlugin', 'Numbers'),
u'Deut': translate('BiblesPlugin', 'Deuteronomy'),
u'Josh': translate('BiblesPlugin', 'Joshua'),
u'Judg': translate('BiblesPlugin', 'Judges'),
u'Ruth': translate('BiblesPlugin', 'Ruth'),
u'1Sam': translate('BiblesPlugin', '1 Samuel'),
u'2Sam': translate('BiblesPlugin', '2 Samuel'),
u'1Kgs': translate('BiblesPlugin', '1 Kings'),
u'2Kgs': translate('BiblesPlugin', '2 Kings'),
u'1Chr': translate('BiblesPlugin', '1 Chronicles'),
u'2Chr': translate('BiblesPlugin', '2 Chronicles'),
u'Esra': translate('BiblesPlugin', 'Ezra'),
u'Neh': translate('BiblesPlugin', 'Nehemiah'),
u'Esth': translate('BiblesPlugin', 'Esther'),
u'Job': translate('BiblesPlugin', 'Job'),
u'Ps': translate('BiblesPlugin', 'Psalms'),
u'Prov': translate('BiblesPlugin', 'Proverbs'),
u'Eccl': translate('BiblesPlugin', 'Ecclesiastes'),
u'Song': translate('BiblesPlugin', 'Song of Solomon'),
u'Isa': translate('BiblesPlugin', 'Isaiah'),
u'Jer': translate('BiblesPlugin', 'Jeremiah'),
u'Lam': translate('BiblesPlugin', 'Lamentations'),
u'Ezek': translate('BiblesPlugin', 'Ezekiel'),
u'Dan': translate('BiblesPlugin', 'Daniel'),
u'Hos': translate('BiblesPlugin', 'Hosea'),
u'Joel': translate('BiblesPlugin', 'Joel'),
u'Amos': translate('BiblesPlugin', 'Amos'),
u'Obad': translate('BiblesPlugin', 'Obadiah'),
u'Jonah': translate('BiblesPlugin', 'Jonah'),
u'Mic': translate('BiblesPlugin', 'Micah'),
u'Nah': translate('BiblesPlugin', 'Nahum'),
u'Hab': translate('BiblesPlugin', 'Habakkuk'),
u'Zeph': translate('BiblesPlugin', 'Zephaniah'),
u'Hag': translate('BiblesPlugin', 'Haggai'),
u'Zech': translate('BiblesPlugin', 'Zechariah'),
u'Mal': translate('BiblesPlugin', 'Malachi'),
u'Matt': translate('BiblesPlugin', 'Matthew'),
u'Mark': translate('BiblesPlugin', 'Mark'),
u'Luke': translate('BiblesPlugin', 'Luke'),
u'John': translate('BiblesPlugin', 'John'),
u'Acts': translate('BiblesPlugin', 'Acts'),
u'Rom': translate('BiblesPlugin', 'Romans'),
u'1Cor': translate('BiblesPlugin', '1 Corinthians'),
u'2Cor': translate('BiblesPlugin', '2 Corinthians'),
u'Gal': translate('BiblesPlugin', 'Galatians'),
u'Eph': translate('BiblesPlugin', 'Ephesians'),
u'Phil': translate('BiblesPlugin', 'Philippians'),
u'Col': translate('BiblesPlugin', 'Colossians'),
u'1Thess': translate('BiblesPlugin', '1 Thessalonians'),
u'2Thess': translate('BiblesPlugin', '2 Thessalonians'),
u'1Tim': translate('BiblesPlugin', '1 Timothy'),
u'2Tim': translate('BiblesPlugin', '2 Timothy'),
u'Titus': translate('BiblesPlugin', 'Titus'),
u'Phlm': translate('BiblesPlugin', 'Philemon'),
u'Heb': translate('BiblesPlugin', 'Hebrews'),
u'Jas': translate('BiblesPlugin', 'James'),
u'1Pet': translate('BiblesPlugin', '1 Peter'),
u'2Pet': translate('BiblesPlugin', '2 Peter'),
u'1John': translate('BiblesPlugin', '1 John'),
u'2John': translate('BiblesPlugin', '2 John'),
u'3John': translate('BiblesPlugin', '3 John'),
u'Jude': translate('BiblesPlugin', 'Jude'),
u'Rev': translate('BiblesPlugin', 'Revelation'),
u'Jdt': translate('BiblesPlugin', 'Judith'),
u'Wis': translate('BiblesPlugin', 'Wisdom'),
u'Tob': translate('BiblesPlugin', 'Tobit'),
u'Sir': translate('BiblesPlugin', 'Sirach'),
u'Bar': translate('BiblesPlugin', 'Baruch'),
u'1Macc': translate('BiblesPlugin', '1 Maccabees'),
u'2Macc': translate('BiblesPlugin', '2 Maccabees'),
u'3Macc': translate('BiblesPlugin', '3 Maccabees'),
u'4Macc': translate('BiblesPlugin', '4 Maccabees'),
u'AddDan': translate('BiblesPlugin', 'Rest of Daniel'),
u'AddEsth': translate('BiblesPlugin', 'Rest of Esther'),
u'PrMan': translate('BiblesPlugin', 'Prayer of Manasses'),
u'LetJer': translate('BiblesPlugin', 'Letter of Jeremiah'),
u'PrAza': translate('BiblesPlugin', 'Prayer of Azariah'),
u'Sus': translate('BiblesPlugin', 'Susanna'),
u'Bel': translate('BiblesPlugin', 'Bel'),
u'1Esdr': translate('BiblesPlugin', '1 Esdras'),
u'2Esdr': translate('BiblesPlugin', '2 Esdras')
}
def update_reference_separators():
"""
Updates separators and matches for parsing and formating scripture
references.
"""
default_separators = unicode(translate('BiblesPlugin',
':|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.beginGroup(u'bibles')
custom_separators = [
unicode(settings.value(u'verse separator').toString()),
unicode(settings.value(u'range separator').toString()),
unicode(settings.value(u'list separator').toString()),
unicode(settings.value(u'end separator').toString())]
settings.endGroup()
for index, role in enumerate([u'v', u'r', u'l', u'e']):
if custom_separators[index].strip(u'|') == u'':
source_string = default_separators[index].strip(u'|')
else:
source_string = custom_separators[index].strip(u'|')
while u'||' in source_string:
source_string = source_string.replace(u'||', u'|')
if role != u'e':
REFERENCE_SEPARATORS[u'sep_%s_display' % role] = \
source_string.split(u'|')[0]
# escape reserved characters
for character in u'\\.^$*+?{}[]()':
source_string = source_string.replace(character, u'\\' + character)
# add various unicode alternatives
source_string = source_string.replace(u'-',
u'(?:[-\u00AD\u2010\u2011\u2012\u2013\u2014\u2212\uFE63\uFF0D])')
source_string = source_string.replace(u',', u'(?:[,\u201A])')
REFERENCE_SEPARATORS[u'sep_%s' % role] = u'\s*(?:%s)\s*' % source_string
REFERENCE_SEPARATORS[u'sep_%s_default' % role] = \
default_separators[index]
# verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)?
range_regex = u'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?' \
u'(?P<from_verse>[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>' \
u'[0-9]+)%(sep_v)s)?(?P<to_verse>[0-9]+)|%(sep_e)s)?)?' % \
REFERENCE_SEPARATORS
REFERENCE_MATCHES[u'range'] = re.compile(u'^\s*%s\s*$' % range_regex,
re.UNICODE)
REFERENCE_MATCHES[u'range_separator'] = re.compile(
REFERENCE_SEPARATORS[u'sep_l'], re.UNICODE)
# full reference match: <book>(<range>(,(?!$)|(?=$)))+
REFERENCE_MATCHES[u'full'] = re.compile(
u'^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*'
u'(?P<ranges>(?:%(range_regex)s(?:%(sep_l)s(?!\s*$)|(?=\s*$)))+)\s*$' \
% dict(REFERENCE_SEPARATORS.items() + [(u'range_regex', range_regex)]),
re.UNICODE)
def get_reference_separator(separator_type):
"""
Provides separators for parsing and formatting scripture references.
``separator_type``
The role and format of the separator.
"""
if len(REFERENCE_SEPARATORS) == 0:
update_reference_separators()
return REFERENCE_SEPARATORS[separator_type]
def get_reference_match(match_type): def get_reference_match(match_type):
""" """
Provides the regexes and matches to use while parsing strings for bible Provides matches for parsing scripture references strings.
references.
``match_type`` ``match_type``
The type of reference information trying to be extracted in this call. The type of match is ``range_separator``, ``range`` or ``full``.
""" """
local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end' if len(REFERENCE_MATCHES) == 0:
).split(u';;') # English update_reference_separators()
# local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde' return REFERENCE_MATCHES[match_type]
# ).split(u';;') # German
separators = {
u'sep_v_display': local_separator[0], u'sep_v': local_separator[1],
u'sep_r_display': local_separator[2], u'sep_r': local_separator[3],
u'sep_l_display': local_separator[4], u'sep_l': local_separator[5],
u'sep_e': local_separator[6]}
# verse range match: (<chapter>:)?<verse>(-((<chapter>:)?<verse>|end)?)? def parse_reference(reference, bible, language_selection, book_ref_id=False):
range_string = str(r'(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?(?P<from_verse>'
r'[0-9]+)(?P<range_to>%(sep_r)s(?:(?:(?P<to_chapter>[0-9]+)%(sep_v)s)?'
r'(?P<to_verse>[0-9]+)|%(sep_e)s)?)?') % separators
if match_type == u'range':
return re.compile(r'^\s*' + range_string + r'\s*$', re.UNICODE)
elif match_type == u'range_separator':
return re.compile(separators[u'sep_l'])
elif match_type == u'full':
# full reference match: <book>(<range>(,|(?=$)))+
return re.compile(str(r'^\s*(?!\s)(?P<book>[\d]*[^\d]+)(?<!\s)\s*'
r'(?P<ranges>(?:' + range_string + r'(?:%(sep_l)s|(?=\s*$)))+)\s*$')
% separators, re.UNICODE)
else:
return separators[match_type]
def parse_reference(reference):
""" """
This is the next generation über-awesome function that takes a person's This is the next generation über-awesome function that takes a person's
typed in string and converts it to a list of references to be queried from typed in string and converts it to a list of references to be queried from
@ -95,6 +260,16 @@ def parse_reference(reference):
``reference`` ``reference``
A string. The Bible reference to parse. A string. The Bible reference to parse.
``bible``
A object. The Bible database object.
``language_selection``
An int. The language selection the user has choosen in settings
section.
``book_ref_id``
A string. The book reference id.
Returns ``None`` or a reference list. Returns ``None`` or a reference list.
The reference list is a list of tuples, with each tuple structured like The reference list is a list of tuples, with each tuple structured like
@ -140,7 +315,7 @@ def parse_reference(reference):
If there is a range separator without further verse declaration the last If there is a range separator without further verse declaration the last
refered chapter is addressed until the end. refered chapter is addressed until the end.
``range_string`` is a regular expression which matches for verse range ``range_regex`` is a regular expression which matches for verse range
declarations: declarations:
``(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?`` ``(?:(?P<from_chapter>[0-9]+)%(sep_v)s)?``
@ -169,9 +344,9 @@ def parse_reference(reference):
are optional leading digits followed by non-digits. The group ends are optional leading digits followed by non-digits. The group ends
before the whitspace in front of the next digit. before the whitspace in front of the next digit.
``(?P<ranges>(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$`` ``(?P<ranges>(?:%(range_regex)s(?:%(sep_l)s(?!\s*$)|(?=\s*$)))+)\s*$``
The second group contains all ``ranges``. This can be multiple The second group contains all ``ranges``. This can be multiple
declarations of a range_string separated by a list separator. declarations of range_regex separated by a list separator.
""" """
log.debug(u'parse_reference("%s")', reference) log.debug(u'parse_reference("%s")', reference)
@ -179,6 +354,51 @@ def parse_reference(reference):
if match: if match:
log.debug(u'Matched reference %s' % reference) log.debug(u'Matched reference %s' % reference)
book = match.group(u'book') book = match.group(u'book')
if not book_ref_id:
booknames = BibleStrings().Booknames
# escape reserved characters
book_escaped = book
for character in u'\\.^$*+?{}[]()':
book_escaped = book_escaped.replace(
character, u'\\' + character)
regex_book = re.compile(u'\s*%s\s*' % u'\s*'.join(
book_escaped.split()), re.UNICODE | re.IGNORECASE)
if language_selection == LanguageSelection.Bible:
db_book = bible.get_book(book)
if db_book:
book_ref_id = db_book.book_reference_id
elif language_selection == LanguageSelection.Application:
book_list = []
for key, value in booknames.iteritems():
if regex_book.match(unicode(value)):
book_list.append(key)
books = []
if book_list:
for value in book_list:
item = BiblesResourcesDB.get_book(value)
if item:
books.append(item)
if books:
for value in books:
if bible.get_book_by_book_ref_id(value[u'id']):
book_ref_id = value[u'id']
break
elif language_selection == LanguageSelection.English:
books = BiblesResourcesDB.get_books_like(book)
if books:
book_list = []
for value in books:
if regex_book.match(value[u'name']):
book_list.append(value)
if not book_list:
book_list = books
for value in book_list:
if bible.get_book_by_book_ref_id(value[u'id']):
book_ref_id = value[u'id']
break
else:
if not bible.get_book_by_book_ref_id(book_ref_id):
book_ref_id = False
ranges = match.group(u'ranges') ranges = match.group(u'ranges')
range_list = get_reference_match(u'range_separator').split(ranges) range_list = get_reference_match(u'range_separator').split(ranges)
ref_list = [] ref_list = []
@ -224,16 +444,18 @@ def parse_reference(reference):
if not to_verse: if not to_verse:
to_verse = -1 to_verse = -1
if to_chapter > from_chapter: if to_chapter > from_chapter:
ref_list.append((book, from_chapter, from_verse, -1)) ref_list.append((book_ref_id, from_chapter, from_verse, -1))
for i in range(from_chapter + 1, to_chapter): for i in range(from_chapter + 1, to_chapter):
ref_list.append((book, i, 1, -1)) ref_list.append((book_ref_id, i, 1, -1))
ref_list.append((book, to_chapter, 1, to_verse)) ref_list.append((book_ref_id, to_chapter, 1, to_verse))
elif to_verse >= from_verse or to_verse == -1: elif to_verse >= from_verse or to_verse == -1:
ref_list.append((book, from_chapter, from_verse, to_verse)) ref_list.append((book_ref_id, from_chapter,
from_verse, to_verse))
elif from_verse: elif from_verse:
ref_list.append((book, from_chapter, from_verse, from_verse)) ref_list.append((book_ref_id, from_chapter,
from_verse, from_verse))
else: else:
ref_list.append((book, from_chapter, 1, -1)) ref_list.append((book_ref_id, from_chapter, 1, -1))
return ref_list return ref_list
else: else:
log.debug(u'Invalid reference: %s' % reference) log.debug(u'Invalid reference: %s' % reference)

View File

@ -4,8 +4,8 @@
############################################################################### ###############################################################################
# OpenLP - Open Source Lyrics Projection # # OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman # # Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Gerald Britton, Jonathan # # Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, # # Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, #
# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias # # Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias #
# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, # # Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
@ -30,8 +30,9 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsTab, translate from openlp.core.lib import Receiver, SettingsTab, translate
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle
from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \
update_reference_separators, get_reference_separator, LanguageSelection
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -90,9 +91,74 @@ class BiblesTab(SettingsTab):
self.changeNoteLabel.setObjectName(u'changeNoteLabel') self.changeNoteLabel.setObjectName(u'changeNoteLabel')
self.verseDisplayLayout.addRow(self.changeNoteLabel) self.verseDisplayLayout.addRow(self.changeNoteLabel)
self.leftLayout.addWidget(self.verseDisplayGroupBox) self.leftLayout.addWidget(self.verseDisplayGroupBox)
self.leftLayout.addStretch() self.scriptureReferenceGroupBox = QtGui.QGroupBox(self.leftColumn)
self.scriptureReferenceGroupBox.setObjectName(
u'scriptureReferenceGroupBox')
self.scriptureReferenceLayout = QtGui.QGridLayout(
self.scriptureReferenceGroupBox)
self.verseSeparatorCheckBox = QtGui.QCheckBox(
self.scriptureReferenceGroupBox)
self.verseSeparatorCheckBox.setObjectName(u'verseSeparatorCheckBox')
self.scriptureReferenceLayout.addWidget(self.verseSeparatorCheckBox, 0,
0)
self.verseSeparatorLineEdit = QtGui.QLineEdit(
self.scriptureReferenceGroupBox)
# self.verseSeparatorLineEdit.setPalette
self.verseSeparatorLineEdit.setObjectName(u'verseSeparatorLineEdit')
self.scriptureReferenceLayout.addWidget(self.verseSeparatorLineEdit, 0,
1)
self.rangeSeparatorCheckBox = QtGui.QCheckBox(
self.scriptureReferenceGroupBox)
self.rangeSeparatorCheckBox.setObjectName(u'rangeSeparatorCheckBox')
self.scriptureReferenceLayout.addWidget(self.rangeSeparatorCheckBox, 1,
0)
self.rangeSeparatorLineEdit = QtGui.QLineEdit(
self.scriptureReferenceGroupBox)
self.rangeSeparatorLineEdit.setObjectName(u'rangeSeparatorLineEdit')
self.scriptureReferenceLayout.addWidget(self.rangeSeparatorLineEdit, 1,
1)
self.listSeparatorCheckBox = QtGui.QCheckBox(
self.scriptureReferenceGroupBox)
self.listSeparatorCheckBox.setObjectName(u'listSeparatorCheckBox')
self.scriptureReferenceLayout.addWidget(self.listSeparatorCheckBox, 2,
0)
self.listSeparatorLineEdit = QtGui.QLineEdit(
self.scriptureReferenceGroupBox)
self.listSeparatorLineEdit.setObjectName(u'listSeparatorLineEdit')
self.scriptureReferenceLayout.addWidget(self.listSeparatorLineEdit, 2,
1)
self.endSeparatorCheckBox = QtGui.QCheckBox(
self.scriptureReferenceGroupBox)
self.endSeparatorCheckBox.setObjectName(u'endSeparatorCheckBox')
self.scriptureReferenceLayout.addWidget(self.endSeparatorCheckBox, 3,
0)
self.endSeparatorLineEdit = QtGui.QLineEdit(
self.scriptureReferenceGroupBox)
self.endSeparatorLineEdit.setObjectName(u'endSeparatorLineEdit')
self.endSeparatorLineEdit.setValidator(QtGui.QRegExpValidator(
QtCore.QRegExp(r'[^0-9]*'), self.endSeparatorLineEdit))
self.scriptureReferenceLayout.addWidget(self.endSeparatorLineEdit, 3,
1)
self.leftLayout.addWidget(self.scriptureReferenceGroupBox)
self.rightColumn.setSizePolicy( self.rightColumn.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
self.languageSelectionGroupBox = QtGui.QGroupBox(self.rightColumn)
self.languageSelectionGroupBox.setObjectName(
u'languageSelectionGroupBox')
self.languageSelectionLayout = QtGui.QVBoxLayout(
self.languageSelectionGroupBox)
self.languageSelectionLabel = QtGui.QLabel(
self.languageSelectionGroupBox)
self.languageSelectionLabel.setObjectName(u'languageSelectionLabel')
self.languageSelectionComboBox = QtGui.QComboBox(
self.languageSelectionGroupBox)
self.languageSelectionComboBox.setObjectName(
u'languageSelectionComboBox')
self.languageSelectionComboBox.addItems([u'', u'', u''])
self.languageSelectionLayout.addWidget(self.languageSelectionLabel)
self.languageSelectionLayout.addWidget(self.languageSelectionComboBox)
self.rightLayout.addWidget(self.languageSelectionGroupBox)
self.leftLayout.addStretch()
self.rightLayout.addStretch() self.rightLayout.addStretch()
# Signals and slots # Signals and slots
QtCore.QObject.connect( QtCore.QObject.connect(
@ -110,8 +176,47 @@ class BiblesTab(SettingsTab):
QtCore.QObject.connect( QtCore.QObject.connect(
self.bibleSecondCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.bibleSecondCheckBox, QtCore.SIGNAL(u'stateChanged(int)'),
self.onBibleSecondCheckBox) self.onBibleSecondCheckBox)
QtCore.QObject.connect(
self.verseSeparatorCheckBox, QtCore.SIGNAL(u'clicked(bool)'),
self.onVerseSeparatorCheckBoxClicked)
QtCore.QObject.connect(
self.verseSeparatorLineEdit, QtCore.SIGNAL(u'textEdited(QString)'),
self.onVerseSeparatorLineEditEdited)
QtCore.QObject.connect(
self.verseSeparatorLineEdit, QtCore.SIGNAL(u'editingFinished()'),
self.onVerseSeparatorLineEditFinished)
QtCore.QObject.connect(
self.rangeSeparatorCheckBox, QtCore.SIGNAL(u'clicked(bool)'),
self.onRangeSeparatorCheckBoxClicked)
QtCore.QObject.connect(
self.rangeSeparatorLineEdit, QtCore.SIGNAL(u'textEdited(QString)'),
self.onRangeSeparatorLineEditEdited)
QtCore.QObject.connect(
self.rangeSeparatorLineEdit, QtCore.SIGNAL(u'editingFinished()'),
self.onRangeSeparatorLineEditFinished)
QtCore.QObject.connect(
self.listSeparatorCheckBox, QtCore.SIGNAL(u'clicked(bool)'),
self.onListSeparatorCheckBoxClicked)
QtCore.QObject.connect(
self.listSeparatorLineEdit, QtCore.SIGNAL(u'textEdited(QString)'),
self.onListSeparatorLineEditEdited)
QtCore.QObject.connect(
self.listSeparatorLineEdit, QtCore.SIGNAL(u'editingFinished()'),
self.onListSeparatorLineEditFinished)
QtCore.QObject.connect(
self.endSeparatorCheckBox, QtCore.SIGNAL(u'clicked(bool)'),
self.onEndSeparatorCheckBoxClicked)
QtCore.QObject.connect(
self.endSeparatorLineEdit, QtCore.SIGNAL(u'textEdited(QString)'),
self.onEndSeparatorLineEditEdited)
QtCore.QObject.connect(
self.endSeparatorLineEdit, QtCore.SIGNAL(u'editingFinished()'),
self.onEndSeparatorLineEditFinished)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList) QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList)
QtCore.QObject.connect(
self.languageSelectionComboBox, QtCore.SIGNAL(u'activated(int)'),
self.onLanguageSelectionComboBoxChanged)
def retranslateUi(self): def retranslateUi(self):
self.verseDisplayGroupBox.setTitle( self.verseDisplayGroupBox.setTitle(
@ -141,6 +246,53 @@ class BiblesTab(SettingsTab):
'Note:\nChanges do not affect verses already in the service.')) 'Note:\nChanges do not affect verses already in the service.'))
self.bibleSecondCheckBox.setText( self.bibleSecondCheckBox.setText(
translate('BiblesPlugin.BiblesTab', 'Display second Bible verses')) translate('BiblesPlugin.BiblesTab', 'Display second Bible verses'))
self.scriptureReferenceGroupBox.setTitle(
translate('BiblesPlugin.BiblesTab', 'Custom Scripture References'))
self.verseSeparatorCheckBox.setText(
translate('BiblesPlugin.BiblesTab', 'Verse Separator:'))
self.rangeSeparatorCheckBox.setText(
translate('BiblesPlugin.BiblesTab', 'Range Separator:'))
self.listSeparatorCheckBox.setText(
translate('BiblesPlugin.BiblesTab', 'List Separator:'))
self.endSeparatorCheckBox.setText(
translate('BiblesPlugin.BiblesTab', 'End Mark:'))
self.verseSeparatorLineEdit.setToolTip(
translate('BiblesPlugin.BiblesTab', 'Multiple alternative '
'verse separators may be defined.\nThey have to be separated '
'by a vertical bar "|".\nPlease clear this edit line to use '
'the default value.'))
self.rangeSeparatorLineEdit.setToolTip(
translate('BiblesPlugin.BiblesTab', 'Multiple alternative '
'range separators may be defined.\nThey have to be separated '
'by a vertical bar "|".\nPlease clear this edit line to use '
'the default value.'))
self.listSeparatorLineEdit.setToolTip(
translate('BiblesPlugin.BiblesTab', 'Multiple alternative '
'list separators may be defined.\nThey have to be separated '
'by a vertical bar "|".\nPlease clear this edit line to use '
'the default value.'))
self.endSeparatorLineEdit.setToolTip(
translate('BiblesPlugin.BiblesTab', 'Multiple alternative '
'end marks may be defined.\nThey have to be separated by a '
'vertical bar "|".\nPlease clear this edit line to use the '
'default value.'))
self.languageSelectionGroupBox.setTitle(
translate('BiblesPlugin.BiblesTab', 'Preferred Bookname Language'))
self.languageSelectionLabel.setText(translate('BiblesPlugin.BiblesTab',
'Choose the language in which the book names of the\nBible should '
'be displayed in the Bible search:'))
self.languageSelectionComboBox.setItemText(LanguageSelection.Bible,
translate('BiblesPlugin.BiblesTab', 'Bible language'))
self.languageSelectionComboBox.setItemText(
LanguageSelection.Application,
translate('BiblesPlugin.BiblesTab', 'Application language'))
self.languageSelectionComboBox.setItemText(LanguageSelection.English,
translate('BiblesPlugin.BiblesTab', 'English'))
self.languageSelectionComboBox.setToolTip(
translate('BiblesPlugin.BiblesTab', 'Multiple options:\n '
'Bible language - the language in which the Bible book names '
'were imported\n Application language - the language you have '
'chosen for OpenLP\n English - always use English book names'))
def onBibleThemeComboBoxChanged(self): def onBibleThemeComboBoxChanged(self):
self.bible_theme = self.bibleThemeComboBox.currentText() self.bible_theme = self.bibleThemeComboBox.currentText()
@ -151,6 +303,9 @@ class BiblesTab(SettingsTab):
def onLayoutStyleComboBoxChanged(self): def onLayoutStyleComboBoxChanged(self):
self.layout_style = self.layoutStyleComboBox.currentIndex() self.layout_style = self.layoutStyleComboBox.currentIndex()
def onLanguageSelectionComboBoxChanged(self):
self.language_selection = self.languageSelectionComboBox.currentIndex()
def onNewChaptersCheckBoxChanged(self, check_state): def onNewChaptersCheckBoxChanged(self, check_state):
self.show_new_chapters = False self.show_new_chapters = False
# We have a set value convert to True/False. # We have a set value convert to True/False.
@ -163,6 +318,106 @@ class BiblesTab(SettingsTab):
if check_state == QtCore.Qt.Checked: if check_state == QtCore.Qt.Checked:
self.second_bibles = True self.second_bibles = True
def onVerseSeparatorCheckBoxClicked(self, checked):
if checked:
self.verseSeparatorLineEdit.setFocus()
else:
self.verseSeparatorLineEdit.setText(
get_reference_separator(u'sep_v_default'))
self.verseSeparatorLineEdit.setPalette(
self.getGreyTextPalette(not checked))
def onVerseSeparatorLineEditEdited(self, text):
self.verseSeparatorCheckBox.setChecked(True)
self.verseSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
def onVerseSeparatorLineEditFinished(self):
if self.verseSeparatorLineEdit.isModified():
text = self.verseSeparatorLineEdit.text()
if text == get_reference_separator(u'sep_v_default') or \
text.remove(u'|').isEmpty():
self.verseSeparatorCheckBox.setChecked(False)
self.verseSeparatorLineEdit.setText(
get_reference_separator(u'sep_v_default'))
self.verseSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
def onRangeSeparatorCheckBoxClicked(self, checked):
if checked:
self.rangeSeparatorLineEdit.setFocus()
else:
self.rangeSeparatorLineEdit.setText(
get_reference_separator(u'sep_r_default'))
self.rangeSeparatorLineEdit.setPalette(
self.getGreyTextPalette(not checked))
def onRangeSeparatorLineEditEdited(self, text):
self.rangeSeparatorCheckBox.setChecked(True)
self.rangeSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
def onRangeSeparatorLineEditFinished(self):
if self.rangeSeparatorLineEdit.isModified():
text = self.rangeSeparatorLineEdit.text()
if text == get_reference_separator(u'sep_r_default') or \
text.remove(u'|').isEmpty():
self.rangeSeparatorCheckBox.setChecked(False)
self.rangeSeparatorLineEdit.setText(
get_reference_separator(u'sep_r_default'))
self.rangeSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
def onListSeparatorCheckBoxClicked(self, checked):
if checked:
self.listSeparatorLineEdit.setFocus()
else:
self.listSeparatorLineEdit.setText(
get_reference_separator(u'sep_l_default'))
self.listSeparatorLineEdit.setPalette(
self.getGreyTextPalette(not checked))
def onListSeparatorLineEditEdited(self, text):
self.listSeparatorCheckBox.setChecked(True)
self.listSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
def onListSeparatorLineEditFinished(self):
if self.listSeparatorLineEdit.isModified():
text = self.listSeparatorLineEdit.text()
if text == get_reference_separator(u'sep_l_default') or \
text.remove(u'|').isEmpty():
self.listSeparatorCheckBox.setChecked(False)
self.listSeparatorLineEdit.setText(
get_reference_separator(u'sep_l_default'))
self.listSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
def onEndSeparatorCheckBoxClicked(self, checked):
if checked:
self.endSeparatorLineEdit.setFocus()
else:
self.endSeparatorLineEdit.setText(
get_reference_separator(u'sep_e_default'))
self.endSeparatorLineEdit.setPalette(
self.getGreyTextPalette(not checked))
def onEndSeparatorLineEditEdited(self, text):
self.endSeparatorCheckBox.setChecked(True)
self.endSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
def onEndSeparatorLineEditFinished(self):
if self.endSeparatorLineEdit.isModified():
text = self.endSeparatorLineEdit.text()
if text == get_reference_separator(u'sep_e_default') or \
text.remove(u'|').isEmpty():
self.endSeparatorCheckBox.setChecked(False)
self.endSeparatorLineEdit.setText(
get_reference_separator(u'sep_e_default'))
self.endSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
def load(self): def load(self):
settings = QtCore.QSettings() settings = QtCore.QSettings()
settings.beginGroup(self.settingsSection) settings.beginGroup(self.settingsSection)
@ -180,6 +435,61 @@ class BiblesTab(SettingsTab):
self.displayStyleComboBox.setCurrentIndex(self.display_style) self.displayStyleComboBox.setCurrentIndex(self.display_style)
self.layoutStyleComboBox.setCurrentIndex(self.layout_style) self.layoutStyleComboBox.setCurrentIndex(self.layout_style)
self.bibleSecondCheckBox.setChecked(self.second_bibles) self.bibleSecondCheckBox.setChecked(self.second_bibles)
verse_separator = unicode(settings.value(u'verse separator').toString())
if (verse_separator.strip(u'|') == u'') or \
(verse_separator == get_reference_separator(u'sep_v_default')):
self.verseSeparatorLineEdit.setText(
get_reference_separator(u'sep_v_default'))
self.verseSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
self.verseSeparatorCheckBox.setChecked(False)
else:
self.verseSeparatorLineEdit.setText(verse_separator)
self.verseSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
self.verseSeparatorCheckBox.setChecked(True)
range_separator = unicode(settings.value(u'range separator').toString())
if (range_separator.strip(u'|') == u'') or \
(range_separator == get_reference_separator(u'sep_r_default')):
self.rangeSeparatorLineEdit.setText(
get_reference_separator(u'sep_r_default'))
self.rangeSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
self.rangeSeparatorCheckBox.setChecked(False)
else:
self.rangeSeparatorLineEdit.setText(range_separator)
self.rangeSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
self.rangeSeparatorCheckBox.setChecked(True)
list_separator = unicode(settings.value(u'list separator').toString())
if (list_separator.strip(u'|') == u'') or \
(list_separator == get_reference_separator(u'sep_l_default')):
self.listSeparatorLineEdit.setText(
get_reference_separator(u'sep_l_default'))
self.listSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
self.listSeparatorCheckBox.setChecked(False)
else:
self.listSeparatorLineEdit.setText(list_separator)
self.listSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
self.listSeparatorCheckBox.setChecked(True)
end_separator = unicode(settings.value(u'end separator').toString())
if (end_separator.strip(u'|') == u'') or \
(end_separator == get_reference_separator(u'sep_e_default')):
self.endSeparatorLineEdit.setText(
get_reference_separator(u'sep_e_default'))
self.endSeparatorLineEdit.setPalette(
self.getGreyTextPalette(True))
self.endSeparatorCheckBox.setChecked(False)
else:
self.endSeparatorLineEdit.setText(end_separator)
self.endSeparatorLineEdit.setPalette(
self.getGreyTextPalette(False))
self.endSeparatorCheckBox.setChecked(True)
self.language_selection = settings.value(
u'bookname language', QtCore.QVariant(0)).toInt()[0]
self.languageSelectionComboBox.setCurrentIndex(self.language_selection)
settings.endGroup() settings.endGroup()
def save(self): def save(self):
@ -191,8 +501,32 @@ class BiblesTab(SettingsTab):
QtCore.QVariant(self.display_style)) QtCore.QVariant(self.display_style))
settings.setValue(u'verse layout style', settings.setValue(u'verse layout style',
QtCore.QVariant(self.layout_style)) QtCore.QVariant(self.layout_style))
settings.setValue(u'bookname language',
QtCore.QVariant(self.language_selection))
settings.setValue(u'second bibles', QtCore.QVariant(self.second_bibles)) settings.setValue(u'second bibles', QtCore.QVariant(self.second_bibles))
settings.setValue(u'bible theme', QtCore.QVariant(self.bible_theme)) settings.setValue(u'bible theme', QtCore.QVariant(self.bible_theme))
if self.verseSeparatorCheckBox.isChecked():
settings.setValue(u'verse separator',
self.verseSeparatorLineEdit.text())
else:
settings.remove(u'verse separator')
if self.rangeSeparatorCheckBox.isChecked():
settings.setValue(u'range separator',
self.rangeSeparatorLineEdit.text())
else:
settings.remove(u'range separator')
if self.listSeparatorCheckBox.isChecked():
settings.setValue(u'list separator',
self.listSeparatorLineEdit.text())
else:
settings.remove(u'list separator')
if self.endSeparatorCheckBox.isChecked():
settings.setValue(u'end separator',
self.endSeparatorLineEdit.text())
else:
settings.remove(u'end separator')
update_reference_separators()
Receiver.send_message(u'bibles_load_list')
settings.endGroup() settings.endGroup()
def updateThemeList(self, theme_list): def updateThemeList(self, theme_list):
@ -209,3 +543,15 @@ class BiblesTab(SettingsTab):
for theme in theme_list: for theme in theme_list:
self.bibleThemeComboBox.addItem(theme) self.bibleThemeComboBox.addItem(theme)
find_and_set_in_combo_box(self.bibleThemeComboBox, self.bible_theme) find_and_set_in_combo_box(self.bibleThemeComboBox, self.bible_theme)
def getGreyTextPalette(self, greyed):
"""
Returns a QPalette with greyed out text as used for placeholderText.
"""
palette = QtGui.QPalette()
color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Text)
if greyed:
color.setAlpha(128)
palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color)
return palette

Some files were not shown because too many files have changed in this diff Show More