forked from openlp/openlp
HEAD
This commit is contained in:
commit
15fee17827
@ -23,3 +23,7 @@ resources/windows/warnOpenLP.txt
|
||||
openlp.cfg
|
||||
.idea
|
||||
openlp.pro
|
||||
.kdev4
|
||||
tests.kdev4
|
||||
*.nja
|
||||
*.orig
|
||||
|
@ -1 +1 @@
|
||||
2.0
|
||||
2.1.0-bzr2141
|
||||
|
@ -34,4 +34,3 @@ import core
|
||||
import plugins
|
||||
|
||||
__all__ = [u'core', u'plugins']
|
||||
|
||||
|
@ -43,16 +43,14 @@ from traceback import format_exception
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, Settings, check_directory_exists
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib import Receiver, Settings, ScreenList, UiStrings, Registry, check_directory_exists
|
||||
from openlp.core.resources import qInitResources
|
||||
from openlp.core.ui.mainwindow import MainWindow
|
||||
from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
|
||||
from openlp.core.ui.firsttimeform import FirstTimeForm
|
||||
from openlp.core.ui.exceptionform import ExceptionForm
|
||||
from openlp.core.ui import SplashScreen, ScreenList
|
||||
from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \
|
||||
get_application_version
|
||||
from openlp.core.ui import SplashScreen
|
||||
from openlp.core.utils import AppLocation, LanguageManager, VersionThread, get_application_version
|
||||
|
||||
|
||||
__all__ = [u'OpenLP', u'main']
|
||||
@ -94,15 +92,16 @@ class OpenLP(QtGui.QApplication):
|
||||
"""
|
||||
Override exec method to allow the shared memory to be released on exit
|
||||
"""
|
||||
self.eventLoopIsActive = True
|
||||
QtGui.QApplication.exec_()
|
||||
self.sharedMemory.detach()
|
||||
self.is_event_loop_active = True
|
||||
result = QtGui.QApplication.exec_()
|
||||
self.shared_memory.detach()
|
||||
return result
|
||||
|
||||
def run(self, args, testing=False):
|
||||
def run(self, args):
|
||||
"""
|
||||
Run the OpenLP application.
|
||||
"""
|
||||
self.eventLoopIsActive = False
|
||||
self.is_event_loop_active = False
|
||||
# On Windows, the args passed into the constructor are ignored. Not
|
||||
# very handy, so set the ones we want to use. On Linux and FreeBSD, in
|
||||
# order to set the WM_CLASS property for X11, we pass "OpenLP" in as a
|
||||
@ -111,90 +110,114 @@ class OpenLP(QtGui.QApplication):
|
||||
if 'OpenLP' in args:
|
||||
args.remove('OpenLP')
|
||||
self.args.extend(args)
|
||||
# provide a listener for widgets to reqest a screen update.
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'cursor_busy'), self.setBusyCursor)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'cursor_normal'), self.setNormalCursor)
|
||||
# Decide how many screens we have and their size
|
||||
screens = ScreenList.create(self.desktop())
|
||||
# First time checks in settings
|
||||
has_run_wizard = Settings().value(u'general/has run wizard', False)
|
||||
has_run_wizard = Settings().value(u'general/has run wizard')
|
||||
if not has_run_wizard:
|
||||
if FirstTimeForm(screens).exec_() == QtGui.QDialog.Accepted:
|
||||
Settings().setValue(u'general/has run wizard', True)
|
||||
# Correct stylesheet bugs
|
||||
if os.name == u'nt':
|
||||
application_stylesheet = u''
|
||||
if not Settings().value(u'advanced/alternate rows'):
|
||||
base_color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Base)
|
||||
application_stylesheet = \
|
||||
alternate_rows_repair_stylesheet = \
|
||||
u'QTableWidget, QListWidget, QTreeWidget {alternate-background-color: ' + base_color.name() + ';}\n'
|
||||
application_stylesheet += alternate_rows_repair_stylesheet
|
||||
if os.name == u'nt':
|
||||
application_stylesheet += nt_repair_stylesheet
|
||||
if application_stylesheet:
|
||||
self.setStyleSheet(application_stylesheet)
|
||||
show_splash = Settings().value(u'general/show splash', True)
|
||||
show_splash = Settings().value(u'general/show splash')
|
||||
if show_splash:
|
||||
self.splash = SplashScreen()
|
||||
self.splash.show()
|
||||
# make sure Qt really display the splash screen
|
||||
self.processEvents()
|
||||
# start the main app window
|
||||
self.mainWindow = MainWindow(self)
|
||||
self.mainWindow.show()
|
||||
self.main_window = MainWindow()
|
||||
self.main_window.show()
|
||||
if show_splash:
|
||||
# now kill the splashscreen
|
||||
self.splash.finish(self.mainWindow)
|
||||
self.splash.finish(self.main_window)
|
||||
log.debug(u'Splashscreen closed')
|
||||
# make sure Qt really display the splash screen
|
||||
self.processEvents()
|
||||
self.mainWindow.repaint()
|
||||
self.main_window.repaint()
|
||||
self.processEvents()
|
||||
if not has_run_wizard:
|
||||
self.mainWindow.firstTime()
|
||||
update_check = Settings().value(u'general/update check', True)
|
||||
self.main_window.first_time()
|
||||
update_check = Settings().value(u'general/update check')
|
||||
if update_check:
|
||||
VersionThread(self.mainWindow).start()
|
||||
VersionThread(self.main_window).start()
|
||||
Receiver.send_message(u'live_display_blank_check')
|
||||
self.mainWindow.appStartup()
|
||||
# Skip exec_() for gui tests
|
||||
if not testing:
|
||||
self.main_window.app_startup()
|
||||
return self.exec_()
|
||||
|
||||
def isAlreadyRunning(self):
|
||||
def close_splash_screen(self):
|
||||
"""
|
||||
Close the splash screen when requested.
|
||||
"""
|
||||
self.splash.close()
|
||||
|
||||
def is_already_running(self):
|
||||
"""
|
||||
Look to see if OpenLP is already running and ask if a 2nd copy
|
||||
is to be started.
|
||||
"""
|
||||
self.sharedMemory = QtCore.QSharedMemory('OpenLP')
|
||||
if self.sharedMemory.attach():
|
||||
self.shared_memory = QtCore.QSharedMemory('OpenLP')
|
||||
if self.shared_memory.attach():
|
||||
status = QtGui.QMessageBox.critical(None, UiStrings().Error, UiStrings().OpenLPStart,
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
|
||||
if status == QtGui.QMessageBox.No:
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
self.sharedMemory.create(1)
|
||||
self.shared_memory.create(1)
|
||||
return False
|
||||
|
||||
def hookException(self, exctype, value, traceback):
|
||||
def hook_exception(self, exctype, value, traceback):
|
||||
"""
|
||||
Add an exception hook so that any uncaught exceptions are displayed in this window rather than somewhere where
|
||||
users cannot see it and cannot report when we encounter these problems.
|
||||
|
||||
``exctype``
|
||||
The class of exception.
|
||||
|
||||
``value``
|
||||
The actual exception object.
|
||||
|
||||
``traceback``
|
||||
A traceback object with the details of where the exception occurred.
|
||||
"""
|
||||
if not hasattr(self, u'mainWindow'):
|
||||
log.exception(''.join(format_exception(exctype, value, traceback)))
|
||||
return
|
||||
if not hasattr(self, u'exceptionForm'):
|
||||
self.exceptionForm = ExceptionForm(self.mainWindow)
|
||||
self.exceptionForm.exceptionTextEdit.setPlainText(''.join(format_exception(exctype, value, traceback)))
|
||||
self.setNormalCursor()
|
||||
self.exceptionForm.exec_()
|
||||
self.exception_form = ExceptionForm(self.main_window)
|
||||
self.exception_form.exceptionTextEdit.setPlainText(''.join(format_exception(exctype, value, traceback)))
|
||||
self.set_normal_cursor()
|
||||
self.exception_form.exec_()
|
||||
|
||||
def setBusyCursor(self):
|
||||
def process_events(self):
|
||||
"""
|
||||
Wrapper to make ProcessEvents visible and named correctly
|
||||
"""
|
||||
self.processEvents()
|
||||
|
||||
def set_busy_cursor(self):
|
||||
"""
|
||||
Sets the Busy Cursor for the Application
|
||||
"""
|
||||
self.setOverrideCursor(QtCore.Qt.BusyCursor)
|
||||
self.processEvents()
|
||||
|
||||
def setNormalCursor(self):
|
||||
def set_normal_cursor(self):
|
||||
"""
|
||||
Sets the Normal Cursor for the Application
|
||||
"""
|
||||
self.restoreOverrideCursor()
|
||||
self.processEvents()
|
||||
|
||||
def event(self, event):
|
||||
"""
|
||||
@ -213,13 +236,13 @@ def set_up_logging(log_path):
|
||||
"""
|
||||
Setup our logging using log_path
|
||||
"""
|
||||
check_directory_exists(log_path)
|
||||
check_directory_exists(log_path, True)
|
||||
filename = os.path.join(log_path, u'openlp.log')
|
||||
logfile = logging.FileHandler(filename, u'w')
|
||||
logfile.setFormatter(logging.Formatter(u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
|
||||
log.addHandler(logfile)
|
||||
if log.isEnabledFor(logging.DEBUG):
|
||||
print 'Logging to:', filename
|
||||
print('Logging to: %s' % filename)
|
||||
|
||||
|
||||
def main(args=None):
|
||||
@ -239,16 +262,9 @@ def main(args=None):
|
||||
parser.add_option('-d', '--dev-version', dest='dev_version', action='store_true',
|
||||
help='Ignore the version file and pull the version directly from Bazaar')
|
||||
parser.add_option('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).')
|
||||
parser.add_option('--testing', dest='testing', action='store_true', help='Run by testing framework')
|
||||
# Parse command line options and deal with them.
|
||||
# Use args supplied programatically if possible.
|
||||
(options, args) = parser.parse_args(args) if args else parser.parse_args()
|
||||
if options.portable:
|
||||
app_path = AppLocation.get_directory(AppLocation.AppDir)
|
||||
set_up_logging(os.path.abspath(os.path.join(app_path, u'..', u'..', u'Other')))
|
||||
log.info(u'Running portable')
|
||||
else:
|
||||
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
|
||||
qt_args = []
|
||||
if options.loglevel.lower() in ['d', 'debug']:
|
||||
log.setLevel(logging.DEBUG)
|
||||
@ -266,54 +282,52 @@ def main(args=None):
|
||||
# Initialise the resources
|
||||
qInitResources()
|
||||
# Now create and actually run the application.
|
||||
app = OpenLP(qt_args)
|
||||
app.setOrganizationName(u'OpenLP')
|
||||
app.setOrganizationDomain(u'openlp.org')
|
||||
application = OpenLP(qt_args)
|
||||
application.setOrganizationName(u'OpenLP')
|
||||
application.setOrganizationDomain(u'openlp.org')
|
||||
if options.portable:
|
||||
app.setApplicationName(u'OpenLPPortable')
|
||||
application.setApplicationName(u'OpenLPPortable')
|
||||
Settings.setDefaultFormat(Settings.IniFormat)
|
||||
# Get location OpenLPPortable.ini
|
||||
portable_settings_file = os.path.abspath(os.path.join(app_path, u'..', u'..', u'Data', u'OpenLP.ini'))
|
||||
application_path = AppLocation.get_directory(AppLocation.AppDir)
|
||||
set_up_logging(os.path.abspath(os.path.join(application_path, u'..', u'..', u'Other')))
|
||||
log.info(u'Running portable')
|
||||
portable_settings_file = os.path.abspath(os.path.join(application_path, u'..', u'..', u'Data', u'OpenLP.ini'))
|
||||
# Make this our settings file
|
||||
log.info(u'INI file: %s', portable_settings_file)
|
||||
Settings.setFilename(portable_settings_file)
|
||||
Settings.set_filename(portable_settings_file)
|
||||
portable_settings = Settings()
|
||||
# Set our data path
|
||||
data_path = os.path.abspath(os.path.join(app_path,
|
||||
u'..', u'..', u'Data',))
|
||||
data_path = os.path.abspath(os.path.join(application_path, u'..', u'..', u'Data',))
|
||||
log.info(u'Data path: %s', data_path)
|
||||
# Point to our data path
|
||||
portable_settings.setValue(u'advanced/data path', data_path)
|
||||
portable_settings.setValue(u'advanced/is portable', True)
|
||||
portable_settings.sync()
|
||||
else:
|
||||
app.setApplicationName(u'OpenLP')
|
||||
app.setApplicationVersion(get_application_version()[u'version'])
|
||||
application.setApplicationName(u'OpenLP')
|
||||
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
|
||||
Registry.create()
|
||||
Registry().register(u'application', application)
|
||||
application.setApplicationVersion(get_application_version()[u'version'])
|
||||
# Instance check
|
||||
if not options.testing:
|
||||
# Instance check
|
||||
if app.isAlreadyRunning():
|
||||
if application.is_already_running():
|
||||
sys.exit()
|
||||
# First time checks in settings
|
||||
if not Settings().value(u'general/has run wizard', False):
|
||||
if not Settings().value(u'general/has run wizard'):
|
||||
if not FirstTimeLanguageForm().exec_():
|
||||
# if cancel then stop processing
|
||||
sys.exit()
|
||||
# i18n Set Language
|
||||
language = LanguageManager.get_language()
|
||||
app_translator, default_translator = LanguageManager.get_translator(language)
|
||||
if not app_translator.isEmpty():
|
||||
app.installTranslator(app_translator)
|
||||
application_translator, default_translator = LanguageManager.get_translator(language)
|
||||
if not application_translator.isEmpty():
|
||||
application.installTranslator(application_translator)
|
||||
if not default_translator.isEmpty():
|
||||
app.installTranslator(default_translator)
|
||||
application.installTranslator(default_translator)
|
||||
else:
|
||||
log.debug(u'Could not find default_translator.')
|
||||
if not options.no_error_form:
|
||||
sys.excepthook = app.hookException
|
||||
# Do not run method app.exec_() when running gui tests
|
||||
if options.testing:
|
||||
app.run(qt_args, testing=True)
|
||||
# For gui tests we need access to window instances and their components
|
||||
return app
|
||||
else:
|
||||
sys.exit(app.run(qt_args))
|
||||
sys.excepthook = application.hook_exception
|
||||
sys.exit(application.run(qt_args))
|
||||
|
||||
|
@ -90,85 +90,7 @@ class ServiceItemAction(object):
|
||||
Next = 3
|
||||
|
||||
|
||||
class Settings(QtCore.QSettings):
|
||||
"""
|
||||
Class to wrap QSettings.
|
||||
|
||||
* Exposes all the methods of QSettings.
|
||||
* Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to
|
||||
``IniFormat``, and the path to the Ini file is set using ``setFilename``,
|
||||
then the Settings constructor (without any arguments) will create a Settings
|
||||
object for accessing settings stored in that Ini file.
|
||||
"""
|
||||
__filePath__ = u''
|
||||
|
||||
@staticmethod
|
||||
def setFilename(iniFile):
|
||||
"""
|
||||
Sets the complete path to an Ini file to be used by Settings objects.
|
||||
|
||||
Does not affect existing Settings objects.
|
||||
"""
|
||||
Settings.__filePath__ = iniFile
|
||||
|
||||
def __init__(self, *args):
|
||||
if not args and Settings.__filePath__ and \
|
||||
Settings.defaultFormat() == Settings.IniFormat:
|
||||
QtCore.QSettings.__init__(self, Settings.__filePath__, Settings.IniFormat)
|
||||
else:
|
||||
QtCore.QSettings.__init__(self, *args)
|
||||
|
||||
def value(self, key, defaultValue):
|
||||
"""
|
||||
Returns the value for the given ``key``. The returned ``value`` is
|
||||
of the same type as the ``defaultValue``.
|
||||
|
||||
``key``
|
||||
The key to return the value from.
|
||||
|
||||
``defaultValue``
|
||||
The value to be returned if the given ``key`` is not present in the
|
||||
config. Note, the ``defaultValue``'s type defines the type the
|
||||
returned is converted to. In other words, if the ``defaultValue`` is
|
||||
a boolean, then the returned value will be converted to a boolean.
|
||||
|
||||
**Note**, this method only converts a few types and might need to be
|
||||
extended if a certain type is missing!
|
||||
"""
|
||||
# Check for none as u'' is passed as default and is valid! This is
|
||||
# needed because the settings export does not know the default values,
|
||||
# thus just passes None.
|
||||
if defaultValue is None and not super(Settings, self).contains(key):
|
||||
return None
|
||||
setting = super(Settings, self).value(key, defaultValue)
|
||||
# On OS X (and probably on other platforms too) empty value from QSettings
|
||||
# is represented as type PyQt4.QtCore.QPyNullVariant. This type has to be
|
||||
# converted to proper 'None' Python type.
|
||||
if isinstance(setting, QtCore.QPyNullVariant) and setting.isNull():
|
||||
setting = None
|
||||
# Handle 'None' type (empty value) properly.
|
||||
if setting is None:
|
||||
# An empty string saved to the settings results in a None type being
|
||||
# returned. Convert it to empty unicode string.
|
||||
if isinstance(defaultValue, unicode):
|
||||
return u''
|
||||
# An empty list saved to the settings results in a None type being
|
||||
# returned.
|
||||
else:
|
||||
return []
|
||||
# Convert the setting to the correct type.
|
||||
if isinstance(defaultValue, bool):
|
||||
if isinstance(setting, bool):
|
||||
return setting
|
||||
# Sometimes setting is string instead of a boolean.
|
||||
return setting == u'true'
|
||||
if isinstance(defaultValue, int):
|
||||
return int(setting)
|
||||
return setting
|
||||
|
||||
|
||||
def translate(context, text, comment=None,
|
||||
encoding=QtCore.QCoreApplication.CodecForTr, n=-1,
|
||||
def translate(context, text, comment=None, encoding=QtCore.QCoreApplication.CodecForTr, n=-1,
|
||||
translate=QtCore.QCoreApplication.translate):
|
||||
"""
|
||||
A special shortcut method to wrap around the Qt4 translation functions.
|
||||
@ -415,17 +337,21 @@ def expand_tags(text):
|
||||
return text
|
||||
|
||||
|
||||
def check_directory_exists(dir):
|
||||
def check_directory_exists(directory, do_not_log=False):
|
||||
"""
|
||||
Check a theme directory exists and if not create it
|
||||
|
||||
``dir``
|
||||
Theme directory to make sure exists
|
||||
``directory``
|
||||
The directory to make sure exists
|
||||
|
||||
``do_not_log``
|
||||
To not log anything. This is need for the start up, when the log isn't ready.
|
||||
"""
|
||||
log.debug(u'check_directory_exists %s' % dir)
|
||||
if not do_not_log:
|
||||
log.debug(u'check_directory_exists %s' % directory)
|
||||
try:
|
||||
if not os.path.exists(dir):
|
||||
os.makedirs(dir)
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
@ -459,7 +385,11 @@ def create_separated_list(stringlist):
|
||||
u'Locale list separator: start') % (stringlist[0], merged)
|
||||
|
||||
|
||||
from registry import Registry
|
||||
from uistrings import UiStrings
|
||||
from eventreceiver import Receiver
|
||||
from screen import ScreenList
|
||||
from settings import Settings
|
||||
from listwidgetwithdnd import ListWidgetWithDnD
|
||||
from formattingtags import FormattingTags
|
||||
from spelltextedit import SpellTextEdit
|
||||
@ -468,8 +398,7 @@ from plugin import PluginStatus, StringContent, Plugin
|
||||
from pluginmanager import PluginManager
|
||||
from settingstab import SettingsTab
|
||||
from serviceitem import ServiceItem, ServiceItemType, ItemCapabilities
|
||||
from htmlbuilder import build_html, build_lyrics_format_css, \
|
||||
build_lyrics_outline_css
|
||||
from htmlbuilder import build_html, build_lyrics_format_css, build_lyrics_outline_css
|
||||
from toolbar import OpenLPToolbar
|
||||
from dockwidget import OpenLPDockWidget
|
||||
from imagemanager import ImageManager
|
||||
|
@ -34,7 +34,6 @@ import logging
|
||||
import os
|
||||
from urllib import quote_plus as urlquote
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from sqlalchemy import Table, MetaData, Column, types, create_engine
|
||||
from sqlalchemy.exc import SQLAlchemyError, InvalidRequestError, DBAPIError, OperationalError
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker, mapper
|
||||
@ -46,6 +45,7 @@ from openlp.core.utils import AppLocation, delete_file
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def init_db(url, auto_flush=True, auto_commit=False):
|
||||
"""
|
||||
Initialise and return the session and metadata for a database
|
||||
@ -61,8 +61,7 @@ def init_db(url, auto_flush=True, auto_commit=False):
|
||||
"""
|
||||
engine = create_engine(url, poolclass=NullPool)
|
||||
metadata = MetaData(bind=engine)
|
||||
session = scoped_session(sessionmaker(autoflush=auto_flush,
|
||||
autocommit=auto_commit, bind=engine))
|
||||
session = scoped_session(sessionmaker(autoflush=auto_flush, autocommit=auto_commit, bind=engine))
|
||||
return session, metadata
|
||||
|
||||
|
||||
@ -110,17 +109,19 @@ def upgrade_db(url, upgrade):
|
||||
while hasattr(upgrade, u'upgrade_%d' % version):
|
||||
log.debug(u'Running upgrade_%d', version)
|
||||
try:
|
||||
getattr(upgrade, u'upgrade_%d' % version) (session, metadata, tables)
|
||||
upgrade_func = getattr(upgrade, u'upgrade_%d' % version)
|
||||
upgrade_func(session, metadata, tables)
|
||||
session.commit()
|
||||
# Update the version number AFTER a commit so that we are sure the previous transaction happened
|
||||
version_meta.value = unicode(version)
|
||||
session.commit()
|
||||
version += 1
|
||||
except (SQLAlchemyError, DBAPIError):
|
||||
log.exception(u'Could not run database upgrade script '
|
||||
'"upgrade_%s", upgrade process has been halted.', version)
|
||||
break
|
||||
version_meta.value = unicode(version)
|
||||
session.commit()
|
||||
version += 1
|
||||
else:
|
||||
version_meta = Metadata.populate(key=u'version',
|
||||
value=int(upgrade.__version__))
|
||||
version_meta = Metadata.populate(key=u'version', value=int(upgrade.__version__))
|
||||
session.commit()
|
||||
return int(version_meta.value), upgrade.__version__
|
||||
|
||||
@ -158,6 +159,7 @@ class BaseModel(object):
|
||||
instance.__setattr__(key, value)
|
||||
return instance
|
||||
|
||||
|
||||
class Manager(object):
|
||||
"""
|
||||
Provide generic object persistence management
|
||||
@ -186,7 +188,7 @@ class Manager(object):
|
||||
self.db_url = u''
|
||||
self.is_dirty = False
|
||||
self.session = None
|
||||
db_type = settings.value(u'db type', u'sqlite')
|
||||
db_type = settings.value(u'db type')
|
||||
if db_type == u'sqlite':
|
||||
if db_file_name:
|
||||
self.db_url = u'sqlite:///%s/%s' % (AppLocation.get_section_data_path(plugin_name), db_file_name)
|
||||
@ -194,12 +196,12 @@ class Manager(object):
|
||||
self.db_url = u'sqlite:///%s/%s.sqlite' % (AppLocation.get_section_data_path(plugin_name), plugin_name)
|
||||
else:
|
||||
self.db_url = u'%s://%s:%s@%s/%s' % (db_type,
|
||||
urlquote(settings.value(u'db username', u'')),
|
||||
urlquote(settings.value(u'db password', u'')),
|
||||
urlquote(settings.value(u'db hostname', u'')),
|
||||
urlquote(settings.value(u'db database', u'')))
|
||||
urlquote(settings.value(u'db username')),
|
||||
urlquote(settings.value(u'db password')),
|
||||
urlquote(settings.value(u'db hostname')),
|
||||
urlquote(settings.value(u'db database')))
|
||||
if db_type == u'mysql':
|
||||
db_encoding = settings.value(u'db encoding', u'utf8')
|
||||
db_encoding = settings.value(u'db encoding')
|
||||
self.db_url += u'?charset=%s' % urlquote(db_encoding)
|
||||
settings.endGroup()
|
||||
if upgrade_mod:
|
||||
@ -207,19 +209,17 @@ class Manager(object):
|
||||
if db_ver > up_ver:
|
||||
critical_error_message_box(
|
||||
translate('OpenLP.Manager', 'Database Error'),
|
||||
translate('OpenLP.Manager', 'The database being '
|
||||
'loaded was created in a more recent version of '
|
||||
'OpenLP. The database is version %d, while OpenLP '
|
||||
'expects version %d. The database will not be loaded.'
|
||||
'\n\nDatabase: %s') % \
|
||||
(db_ver, up_ver, self.db_url)
|
||||
translate('OpenLP.Manager', 'The database being loaded was created in a more recent version of '
|
||||
'OpenLP. The database is version %d, while OpenLP expects version %d. The database will not '
|
||||
'be loaded.\n\nDatabase: %s') % (db_ver, up_ver, self.db_url)
|
||||
)
|
||||
return
|
||||
try:
|
||||
self.session = init_schema(self.db_url)
|
||||
except (SQLAlchemyError, DBAPIError):
|
||||
log.exception(u'Error loading database: %s', self.db_url)
|
||||
critical_error_message_box(translate('OpenLP.Manager', 'Database Error'),
|
||||
critical_error_message_box(
|
||||
translate('OpenLP.Manager', 'Database Error'),
|
||||
translate('OpenLP.Manager', 'OpenLP cannot load your database.\n\nDatabase: %s') % self.db_url
|
||||
)
|
||||
|
||||
|
@ -35,11 +35,11 @@ import logging
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import build_icon
|
||||
from openlp.core.ui import ScreenList
|
||||
from openlp.core.lib import ScreenList, build_icon
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpenLPDockWidget(QtGui.QDockWidget):
|
||||
"""
|
||||
Custom DockWidget class to handle events
|
||||
|
@ -35,6 +35,7 @@ from PyQt4 import QtCore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EventReceiver(QtCore.QObject):
|
||||
"""
|
||||
Class to allow events to be passed from different parts of the system. This
|
||||
@ -46,24 +47,12 @@ class EventReceiver(QtCore.QObject):
|
||||
``mainwindow_status_text``
|
||||
Changes the bottom status bar text on the mainwindow.
|
||||
|
||||
``openlp_warning_message``
|
||||
Displays a standalone Warning Message.
|
||||
|
||||
``openlp_error_message``
|
||||
Displays a standalone Error Message.
|
||||
|
||||
``openlp_information_message``
|
||||
Displays a standalone Information Message.
|
||||
|
||||
``cursor_busy``
|
||||
Makes the cursor got to a busy form.
|
||||
|
||||
``cursor_normal``
|
||||
Resets the cursor to default.
|
||||
|
||||
``openlp_process_events``
|
||||
Requests the Application to flush the events queue.
|
||||
|
||||
``openlp_version_check``
|
||||
Version has changed so pop up window.
|
||||
|
||||
@ -120,29 +109,6 @@ class EventReceiver(QtCore.QObject):
|
||||
``slidecontroller_live_stop_loop``
|
||||
Stop the loop on the main display.
|
||||
|
||||
|
||||
**Servicemanager related signals**
|
||||
|
||||
``servicemanager_new_service``
|
||||
A new service is being loaded or created.
|
||||
|
||||
``servicemanager_previous_item``
|
||||
Display the previous item in the service.
|
||||
|
||||
``servicemanager_preview_live``
|
||||
Requests a Preview item from the Service Manager to update live and add
|
||||
a new item to the preview panel.
|
||||
|
||||
``servicemanager_next_item``
|
||||
Display the next item in the service.
|
||||
|
||||
``servicemanager_set_item``
|
||||
Go live on a specific item, by index.
|
||||
|
||||
``service_item_update``
|
||||
Passes back to the service manager the service item after it has been
|
||||
processed by the plugin.
|
||||
|
||||
**Display signals**
|
||||
|
||||
``update_display_css``
|
||||
@ -200,12 +166,6 @@ class EventReceiver(QtCore.QObject):
|
||||
``{plugin}_unblank``
|
||||
Requests a plugin to handle an unblank screen event.
|
||||
|
||||
``{plugin}_edit``
|
||||
Requests a plugin edit a database item with the key as the payload.
|
||||
|
||||
``{plugin}_edit_clear``
|
||||
Editing has been completed.
|
||||
|
||||
``{plugin}_load_list``
|
||||
Tells the the plugin to reload the media manager list.
|
||||
|
||||
|
@ -31,9 +31,8 @@ Provide HTML Tag management and Formatting Tag access class
|
||||
"""
|
||||
import cPickle
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from openlp.core.lib import Settings, translate
|
||||
|
||||
from openlp.core.lib import translate, Settings
|
||||
|
||||
class FormattingTags(object):
|
||||
"""
|
||||
@ -164,7 +163,7 @@ class FormattingTags(object):
|
||||
FormattingTags.add_html_tags(temporary_tags)
|
||||
|
||||
# Formatting Tags were also known as display tags.
|
||||
user_expands = Settings().value(u'displayTags/html_tags', u'')
|
||||
user_expands = Settings().value(u'displayTags/html_tags')
|
||||
# cPickle only accepts str not unicode strings
|
||||
user_expands_string = str(user_expands)
|
||||
if user_expands_string:
|
||||
|
@ -207,8 +207,8 @@ sup {
|
||||
</html>
|
||||
"""
|
||||
|
||||
def build_html(item, screen, islive, background, image=None,
|
||||
plugins=None):
|
||||
|
||||
def build_html(item, screen, is_live, background, image=None, plugins=None):
|
||||
"""
|
||||
Build the full web paged structure for display
|
||||
|
||||
@ -233,7 +233,7 @@ def build_html(item, screen, islive, background, image=None,
|
||||
width = screen[u'size'].width()
|
||||
height = screen[u'size'].height()
|
||||
theme = item.themedata
|
||||
webkitvers = webkit_version()
|
||||
webkit_ver = webkit_version()
|
||||
# Image generated and poked in
|
||||
if background:
|
||||
bgimage_src = u'src="data:image/png;base64,%s"' % background
|
||||
@ -253,28 +253,32 @@ def build_html(item, screen, islive, background, image=None,
|
||||
css_additions += plugin.getDisplayCss()
|
||||
js_additions += plugin.getDisplayJavaScript()
|
||||
html_additions += plugin.getDisplayHtml()
|
||||
html = HTMLSRC % (build_background_css(item, width, height),
|
||||
html = HTMLSRC % (
|
||||
build_background_css(item, width, height),
|
||||
css_additions,
|
||||
build_footer_css(item, height),
|
||||
build_lyrics_css(item, webkitvers),
|
||||
u'true' if theme and theme.display_slide_transition and islive else u'false',
|
||||
build_lyrics_css(item, webkit_ver),
|
||||
u'true' if theme and theme.display_slide_transition and is_live else u'false',
|
||||
js_additions,
|
||||
bgimage_src, image_src,
|
||||
html_additions,
|
||||
build_lyrics_html(item, webkitvers))
|
||||
build_lyrics_html(item, webkit_ver)
|
||||
)
|
||||
return html
|
||||
|
||||
|
||||
def webkit_version():
|
||||
"""
|
||||
Return the Webkit version in use.
|
||||
Note method added relatively recently, so return 0 if prior to this
|
||||
"""
|
||||
try:
|
||||
webkitvers = float(QtWebKit.qWebKitVersion())
|
||||
log.debug(u'Webkit version = %s' % webkitvers)
|
||||
webkit_ver = float(QtWebKit.qWebKitVersion())
|
||||
log.debug(u'Webkit version = %s' % webkit_ver)
|
||||
except AttributeError:
|
||||
webkitvers = 0
|
||||
return webkitvers
|
||||
webkit_ver = 0
|
||||
return webkit_ver
|
||||
|
||||
|
||||
def build_background_css(item, width, height):
|
||||
"""
|
||||
@ -310,7 +314,8 @@ def build_background_css(item, width, height):
|
||||
% (width, width, width, theme.background_start_color, theme.background_end_color)
|
||||
return background
|
||||
|
||||
def build_lyrics_css(item, webkitvers):
|
||||
|
||||
def build_lyrics_css(item, webkit_ver):
|
||||
"""
|
||||
Build the lyrics display css
|
||||
|
||||
@ -367,12 +372,12 @@ def build_lyrics_css(item, webkitvers):
|
||||
# Up to 534.3 the text-shadow didn't get displayed when
|
||||
# webkit-text-stroke was used. So use an offset text layer underneath.
|
||||
# https://bugs.webkit.org/show_bug.cgi?id=19728
|
||||
if webkitvers >= 533.3:
|
||||
if webkit_ver >= 533.3:
|
||||
lyricsmain += build_lyrics_outline_css(theme)
|
||||
else:
|
||||
outline = build_lyrics_outline_css(theme)
|
||||
if theme.font_main_shadow:
|
||||
if theme.font_main_outline and webkitvers <= 534.3:
|
||||
if theme.font_main_outline and webkit_ver <= 534.3:
|
||||
shadow = u'padding-left: %spx; padding-top: %spx;' % \
|
||||
(int(theme.font_main_shadow_size) + (int(theme.font_main_outline_size) * 2),
|
||||
theme.font_main_shadow_size)
|
||||
@ -384,6 +389,7 @@ def build_lyrics_css(item, webkitvers):
|
||||
lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow)
|
||||
return lyrics_css
|
||||
|
||||
|
||||
def build_lyrics_outline_css(theme, is_shadow=False):
|
||||
"""
|
||||
Build the css which controls the theme outline
|
||||
@ -407,6 +413,7 @@ def build_lyrics_outline_css(theme, is_shadow=False):
|
||||
else:
|
||||
return u''
|
||||
|
||||
|
||||
def build_lyrics_format_css(theme, width, height):
|
||||
"""
|
||||
Build the css which controls the theme format
|
||||
@ -451,6 +458,7 @@ def build_lyrics_format_css(theme, width, height):
|
||||
lyrics += u' font-weight:bold; '
|
||||
return lyrics
|
||||
|
||||
|
||||
def build_lyrics_html(item, webkitvers):
|
||||
"""
|
||||
Build the HTML required to show the lyrics
|
||||
@ -480,6 +488,7 @@ def build_lyrics_html(item, webkitvers):
|
||||
u'class="lyricscell lyricsmain"></div></div>'
|
||||
return lyrics
|
||||
|
||||
|
||||
def build_footer_css(item, height):
|
||||
"""
|
||||
Build the display of the item footer
|
||||
|
@ -39,25 +39,31 @@ import Queue
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import resize_image, image_to_byte, Receiver
|
||||
from openlp.core.ui import ScreenList
|
||||
from openlp.core.lib import Receiver, Registry, ScreenList, resize_image, image_to_byte
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ImageThread(QtCore.QThread):
|
||||
"""
|
||||
A special Qt thread class to speed up the display of images. This is
|
||||
threaded so it loads the frames and generates byte stream in background.
|
||||
"""
|
||||
def __init__(self, manager):
|
||||
"""
|
||||
Constructor for the thread class.
|
||||
|
||||
``manager``
|
||||
The image manager.
|
||||
"""
|
||||
QtCore.QThread.__init__(self, None)
|
||||
self.imageManager = manager
|
||||
self.image_manager = manager
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run the thread.
|
||||
"""
|
||||
self.imageManager._process()
|
||||
self.image_manager._process()
|
||||
|
||||
|
||||
class Priority(object):
|
||||
@ -182,71 +188,75 @@ class ImageManager(QtCore.QObject):
|
||||
log.info(u'Image Manager loaded')
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor for the image manager.
|
||||
"""
|
||||
QtCore.QObject.__init__(self)
|
||||
currentScreen = ScreenList().current
|
||||
self.width = currentScreen[u'size'].width()
|
||||
self.height = currentScreen[u'size'].height()
|
||||
Registry().register(u'image_manager', self)
|
||||
current_screen = ScreenList().current
|
||||
self.width = current_screen[u'size'].width()
|
||||
self.height = current_screen[u'size'].height()
|
||||
self._cache = {}
|
||||
self.imageThread = ImageThread(self)
|
||||
self._conversionQueue = PriorityQueue()
|
||||
self.stopManager = False
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.processUpdates)
|
||||
self.image_thread = ImageThread(self)
|
||||
self._conversion_queue = PriorityQueue()
|
||||
self.stop_manager = False
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.process_updates)
|
||||
|
||||
def updateDisplay(self):
|
||||
def update_display(self):
|
||||
"""
|
||||
Screen has changed size so rebuild the cache to new size.
|
||||
"""
|
||||
log.debug(u'updateDisplay')
|
||||
currentScreen = ScreenList().current
|
||||
self.width = currentScreen[u'size'].width()
|
||||
self.height = currentScreen[u'size'].height()
|
||||
log.debug(u'update_display')
|
||||
current_screen = ScreenList().current
|
||||
self.width = current_screen[u'size'].width()
|
||||
self.height = current_screen[u'size'].height()
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for image in self._cache.values():
|
||||
self._resetImage(image)
|
||||
self._reset_image(image)
|
||||
|
||||
def updateImagesBorder(self, source, background):
|
||||
def update_images_border(self, source, background):
|
||||
"""
|
||||
Border has changed so update all the images affected.
|
||||
"""
|
||||
log.debug(u'updateImages')
|
||||
log.debug(u'update_images_border')
|
||||
# Mark the images as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
for image in self._cache.values():
|
||||
if image.source == source:
|
||||
image.background = background
|
||||
self._resetImage(image)
|
||||
self._reset_image(image)
|
||||
|
||||
def updateImageBorder(self, path, source, background):
|
||||
def update_image_border(self, path, source, background):
|
||||
"""
|
||||
Border has changed so update the image affected.
|
||||
"""
|
||||
log.debug(u'updateImage')
|
||||
log.debug(u'update_image_border')
|
||||
# Mark the image as dirty for a rebuild by setting the image and byte
|
||||
# stream to None.
|
||||
image = self._cache[(path, source)]
|
||||
if image.source == source:
|
||||
image.background = background
|
||||
self._resetImage(image)
|
||||
self._reset_image(image)
|
||||
|
||||
def _resetImage(self, image):
|
||||
def _reset_image(self, image):
|
||||
"""
|
||||
Mark the given :class:`Image` instance as dirty by setting its ``image``
|
||||
and ``image_bytes`` attributes to None.
|
||||
"""
|
||||
image.image = None
|
||||
image.image_bytes = None
|
||||
self._conversionQueue.modify_priority(image, Priority.Normal)
|
||||
self._conversion_queue.modify_priority(image, Priority.Normal)
|
||||
|
||||
def processUpdates(self):
|
||||
def process_updates(self):
|
||||
"""
|
||||
Flush the queue to updated any data to update
|
||||
"""
|
||||
# We want only one thread.
|
||||
if not self.imageThread.isRunning():
|
||||
self.imageThread.start()
|
||||
if not self.image_thread.isRunning():
|
||||
self.image_thread.start()
|
||||
|
||||
def getImage(self, path, source):
|
||||
def get_image(self, path, source):
|
||||
"""
|
||||
Return the ``QImage`` from the cache. If not present wait for the
|
||||
background thread to process it.
|
||||
@ -254,9 +264,9 @@ class ImageManager(QtCore.QObject):
|
||||
log.debug(u'getImage %s' % path)
|
||||
image = self._cache[(path, source)]
|
||||
if image.image is None:
|
||||
self._conversionQueue.modify_priority(image, Priority.High)
|
||||
self._conversion_queue.modify_priority(image, Priority.High)
|
||||
# make sure we are running and if not give it a kick
|
||||
self.processUpdates()
|
||||
self.process_updates()
|
||||
while image.image is None:
|
||||
log.debug(u'getImage - waiting')
|
||||
time.sleep(0.1)
|
||||
@ -265,74 +275,74 @@ class ImageManager(QtCore.QObject):
|
||||
# byte stream was not generated yet. However, we only need to do
|
||||
# this, when the image was generated before it was requested
|
||||
# (otherwise this is already taken care of).
|
||||
self._conversionQueue.modify_priority(image, Priority.Low)
|
||||
self._conversion_queue.modify_priority(image, Priority.Low)
|
||||
return image.image
|
||||
|
||||
def getImageBytes(self, path, source):
|
||||
def get_image_bytes(self, path, source):
|
||||
"""
|
||||
Returns the byte string for an image. If not present wait for the
|
||||
background thread to process it.
|
||||
"""
|
||||
log.debug(u'getImageBytes %s' % path)
|
||||
log.debug(u'get_image_bytes %s' % path)
|
||||
image = self._cache[(path, source)]
|
||||
if image.image_bytes is None:
|
||||
self._conversionQueue.modify_priority(image, Priority.Urgent)
|
||||
self._conversion_queue.modify_priority(image, Priority.Urgent)
|
||||
# make sure we are running and if not give it a kick
|
||||
self.processUpdates()
|
||||
self.process_updates()
|
||||
while image.image_bytes is None:
|
||||
log.debug(u'getImageBytes - waiting')
|
||||
time.sleep(0.1)
|
||||
return image.image_bytes
|
||||
|
||||
def addImage(self, path, source, background):
|
||||
def add_image(self, path, source, background):
|
||||
"""
|
||||
Add image to cache if it is not already there.
|
||||
"""
|
||||
log.debug(u'addImage %s' % path)
|
||||
log.debug(u'add_image %s' % path)
|
||||
if not (path, source) in self._cache:
|
||||
image = Image(path, source, background)
|
||||
self._cache[(path, source)] = image
|
||||
self._conversionQueue.put((image.priority, image.secondary_priority, image))
|
||||
self._conversion_queue.put((image.priority, image.secondary_priority, image))
|
||||
# Check if the there are any images with the same path and check if the
|
||||
# timestamp has changed.
|
||||
for image in self._cache.values():
|
||||
if os.path.exists(path):
|
||||
if image.path == path and image.timestamp != os.stat(path).st_mtime:
|
||||
image.timestamp = os.stat(path).st_mtime
|
||||
self._resetImage(image)
|
||||
self._reset_image(image)
|
||||
# We want only one thread.
|
||||
if not self.imageThread.isRunning():
|
||||
self.imageThread.start()
|
||||
if not self.image_thread.isRunning():
|
||||
self.image_thread.start()
|
||||
|
||||
def _process(self):
|
||||
"""
|
||||
Controls the processing called from a ``QtCore.QThread``.
|
||||
"""
|
||||
log.debug(u'_process - started')
|
||||
while not self._conversionQueue.empty() and not self.stopManager:
|
||||
self._processCache()
|
||||
while not self._conversion_queue.empty() and not self.stop_manager:
|
||||
self._process_cache()
|
||||
log.debug(u'_process - ended')
|
||||
|
||||
def _processCache(self):
|
||||
def _process_cache(self):
|
||||
"""
|
||||
Actually does the work.
|
||||
"""
|
||||
log.debug(u'_processCache')
|
||||
image = self._conversionQueue.get()[2]
|
||||
image = self._conversion_queue.get()[2]
|
||||
# Generate the QImage for the image.
|
||||
if image.image is None:
|
||||
image.image = resize_image(image.path, self.width, self.height, image.background)
|
||||
# Set the priority to Lowest and stop here as we need to process
|
||||
# more important images first.
|
||||
if image.priority == Priority.Normal:
|
||||
self._conversionQueue.modify_priority(image, Priority.Lowest)
|
||||
self._conversion_queue.modify_priority(image, Priority.Lowest)
|
||||
return
|
||||
# For image with high priority we set the priority to Low, as the
|
||||
# byte stream might be needed earlier the byte stream of image with
|
||||
# Normal priority. We stop here as we need to process more important
|
||||
# images first.
|
||||
elif image.priority == Priority.High:
|
||||
self._conversionQueue.modify_priority(image, Priority.Low)
|
||||
self._conversion_queue.modify_priority(image, Priority.Low)
|
||||
return
|
||||
# Generate the byte stream for the image.
|
||||
if image.image_bytes is None:
|
||||
|
@ -35,6 +35,7 @@ from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver
|
||||
|
||||
|
||||
class ListWidgetWithDnD(QtGui.QListWidget):
|
||||
"""
|
||||
Provide a list widget to store objects and handle drag and drop events
|
||||
@ -58,9 +59,8 @@ class ListWidgetWithDnD(QtGui.QListWidget):
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
"""
|
||||
Drag and drop event does not care what data is selected
|
||||
as the recipient will use events to request the data move
|
||||
just tell it what plugin to call
|
||||
Drag and drop event does not care what data is selected as the recipient will use events to request the data
|
||||
move just tell it what plugin to call
|
||||
"""
|
||||
if event.buttons() != QtCore.Qt.LeftButton:
|
||||
event.ignore()
|
||||
@ -75,12 +75,18 @@ class ListWidgetWithDnD(QtGui.QListWidget):
|
||||
drag.start(QtCore.Qt.CopyAction)
|
||||
|
||||
def dragEnterEvent(self, event):
|
||||
"""
|
||||
When something is dragged into this object, check if you should be able to drop it in here.
|
||||
"""
|
||||
if event.mimeData().hasUrls():
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
|
||||
def dragMoveEvent(self, event):
|
||||
"""
|
||||
Make an object droppable, and set it to copy the contents of the object, not move it.
|
||||
"""
|
||||
if event.mimeData().hasUrls():
|
||||
event.setDropAction(QtCore.Qt.CopyAction)
|
||||
event.accept()
|
||||
|
@ -35,13 +35,14 @@ import re
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, translate, \
|
||||
Receiver, ListWidgetWithDnD, ServiceItemContext, Settings
|
||||
from openlp.core.lib import OpenLPToolbar, ServiceItem, StringContent, Receiver, ListWidgetWithDnD, \
|
||||
ServiceItemContext, Settings, Registry, UiStrings, build_icon, translate
|
||||
from openlp.core.lib.searchedit import SearchEdit
|
||||
from openlp.core.lib.ui import UiStrings, create_widget_action, critical_error_message_box
|
||||
from openlp.core.lib.ui import create_widget_action, critical_error_message_box
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
MediaManagerItem is a helper widget for plugins.
|
||||
@ -98,6 +99,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.plugin = plugin
|
||||
visible_title = self.plugin.getString(StringContent.VisibleName)
|
||||
self.title = unicode(visible_title[u'title'])
|
||||
Registry().register(self.plugin.name, self)
|
||||
self.settingsSection = self.plugin.name
|
||||
self.icon = None
|
||||
if icon:
|
||||
@ -327,32 +329,31 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
Add a file to the list widget to make it available for showing
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(self, self.onNewPrompt,
|
||||
SettingsManager.get_last_dir(self.settingsSection), self.onNewFileMasks)
|
||||
Settings().value(self.settingsSection + u'/last directory'), self.onNewFileMasks)
|
||||
log.info(u'New files(s) %s', files)
|
||||
if files:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
self.validateAndLoad(files)
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def loadFile(self, files):
|
||||
"""
|
||||
Turn file from Drag and Drop into an array so the Validate code
|
||||
can run it.
|
||||
Turn file from Drag and Drop into an array so the Validate code can run it.
|
||||
|
||||
``files``
|
||||
The list of files to be loaded
|
||||
"""
|
||||
new_files = []
|
||||
error_shown = False
|
||||
for file in files:
|
||||
type = file.split(u'.')[-1]
|
||||
if type.lower() not in self.onNewFileMasks:
|
||||
for file_name in files:
|
||||
file_type = file_name.split(u'.')[-1]
|
||||
if file_type.lower() not in self.onNewFileMasks:
|
||||
if not error_shown:
|
||||
critical_error_message_box(translate('OpenLP.MediaManagerItem', 'Invalid File Type'),
|
||||
translate('OpenLP.MediaManagerItem', 'Invalid File %s.\nSuffix not supported') % file)
|
||||
translate('OpenLP.MediaManagerItem', 'Invalid File %s.\nSuffix not supported') % file_name)
|
||||
error_shown = True
|
||||
else:
|
||||
new_files.append(file)
|
||||
new_files.append(file_name)
|
||||
if new_files:
|
||||
self.validateAndLoad(new_files)
|
||||
|
||||
@ -382,14 +383,16 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.listView.clear()
|
||||
self.loadList(full_list)
|
||||
last_dir = os.path.split(unicode(files[0]))[0]
|
||||
SettingsManager.set_last_dir(self.settingsSection, last_dir)
|
||||
SettingsManager.set_list(self.settingsSection,
|
||||
self.settingsSection, self.getFileList())
|
||||
Settings().setValue(self.settingsSection + u'/last directory', last_dir)
|
||||
Settings().setValue(u'%s/%s files' % (self.settingsSection, self.settingsSection), self.getFileList())
|
||||
if duplicates_found:
|
||||
critical_error_message_box(UiStrings().Duplicate,
|
||||
translate('OpenLP.MediaManagerItem', 'Duplicate files were found on import and were ignored.'))
|
||||
|
||||
def contextMenu(self, point):
|
||||
"""
|
||||
Display a context menu
|
||||
"""
|
||||
item = self.listView.itemAt(point)
|
||||
# Decide if we have to show the context menu or not.
|
||||
if item is None:
|
||||
@ -412,6 +415,9 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
return file_list
|
||||
|
||||
def loadList(self, list):
|
||||
"""
|
||||
Load a list. Needs to be implemented by the plugin.
|
||||
"""
|
||||
raise NotImplementedError(u'MediaManagerItem.loadList needs to be defined by the plugin')
|
||||
|
||||
def onNewClick(self):
|
||||
@ -427,6 +433,9 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
pass
|
||||
|
||||
def onDeleteClick(self):
|
||||
"""
|
||||
Delete an item. Needs to be implemented by the plugin.
|
||||
"""
|
||||
raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to be defined by the plugin')
|
||||
|
||||
def onFocus(self):
|
||||
@ -436,15 +445,18 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
pass
|
||||
|
||||
def generateSlideData(self, serviceItem, item=None, xmlVersion=False,
|
||||
remote=False, context=ServiceItemContext.Live):
|
||||
def generateSlideData(self, serviceItem, item=None, xmlVersion=False, remote=False,
|
||||
context=ServiceItemContext.Live):
|
||||
"""
|
||||
Generate the slide data. Needs to be implemented by the plugin.
|
||||
"""
|
||||
raise NotImplementedError(u'MediaManagerItem.generateSlideData needs to be defined by the plugin')
|
||||
|
||||
def onDoubleClicked(self):
|
||||
"""
|
||||
Allows the list click action to be determined dynamically
|
||||
"""
|
||||
if Settings().value(u'advanced/double click live', False):
|
||||
if Settings().value(u'advanced/double click live'):
|
||||
self.onLiveClick()
|
||||
else:
|
||||
self.onPreviewClick()
|
||||
@ -453,7 +465,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
Allows the change of current item in the list to be actioned
|
||||
"""
|
||||
if Settings().value(u'advanced/single click preview', False) and self.quickPreviewAllowed \
|
||||
if Settings().value(u'advanced/single click preview') and self.quickPreviewAllowed \
|
||||
and self.listView.selectedIndexes() and self.autoSelectId == -1:
|
||||
self.onPreviewClick(True)
|
||||
|
||||
@ -470,7 +482,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
serviceItem = self.buildServiceItem()
|
||||
if serviceItem:
|
||||
serviceItem.from_plugin = True
|
||||
self.plugin.previewController.addServiceItem(serviceItem)
|
||||
self.preview_controller.add_service_item(serviceItem)
|
||||
if keepFocus:
|
||||
self.listView.setFocus()
|
||||
|
||||
@ -486,6 +498,9 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.goLive()
|
||||
|
||||
def goLive(self, item_id=None, remote=False):
|
||||
"""
|
||||
Make the currently selected item go live.
|
||||
"""
|
||||
log.debug(u'%s Live requested', self.plugin.name)
|
||||
item = None
|
||||
if item_id:
|
||||
@ -496,9 +511,12 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
serviceItem.from_plugin = True
|
||||
if remote:
|
||||
serviceItem.will_auto_start = True
|
||||
self.plugin.liveController.addServiceItem(serviceItem)
|
||||
self.live_controller.add_service_item(serviceItem)
|
||||
|
||||
def createItemFromId(self, item_id):
|
||||
"""
|
||||
Create a media item from an item id.
|
||||
"""
|
||||
item = QtGui.QListWidgetItem()
|
||||
item.setData(QtCore.Qt.UserRole, item_id)
|
||||
return item
|
||||
@ -507,13 +525,13 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
Add a selected item to the current service
|
||||
"""
|
||||
if not self.listView.selectedIndexes() and not self.remoteTriggered:
|
||||
if not self.listView.selectedIndexes():
|
||||
QtGui.QMessageBox.information(self, UiStrings().NISp,
|
||||
translate('OpenLP.MediaManagerItem', 'You must select one or more items to add.'))
|
||||
else:
|
||||
# Is it posssible to process multiple list items to generate
|
||||
# Is it possible to process multiple list items to generate
|
||||
# multiple service items?
|
||||
if self.singleServiceItem or self.remoteTriggered:
|
||||
if self.singleServiceItem:
|
||||
log.debug(u'%s Add requested', self.plugin.name)
|
||||
self.addToService(replace=self.remoteTriggered)
|
||||
else:
|
||||
@ -522,10 +540,13 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.addToService(item)
|
||||
|
||||
def addToService(self, item=None, replace=None, remote=False):
|
||||
"""
|
||||
Add this item to the current service.
|
||||
"""
|
||||
serviceItem = self.buildServiceItem(item, True, remote=remote, context=ServiceItemContext.Service)
|
||||
if serviceItem:
|
||||
serviceItem.from_plugin = False
|
||||
self.plugin.serviceManager.addServiceItem(serviceItem, replace=replace)
|
||||
self.service_manager.add_service_item(serviceItem, replace=replace)
|
||||
|
||||
def onAddEditClick(self):
|
||||
"""
|
||||
@ -536,13 +557,13 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
translate('OpenLP.MediaManagerItem', 'You must select one or more items.'))
|
||||
else:
|
||||
log.debug(u'%s Add requested', self.plugin.name)
|
||||
serviceItem = self.plugin.serviceManager.getServiceItem()
|
||||
serviceItem = self.service_manager.get_service_item()
|
||||
if not serviceItem:
|
||||
QtGui.QMessageBox.information(self, UiStrings().NISs,
|
||||
translate('OpenLP.MediaManagerItem', 'You must select an existing service item to add to.'))
|
||||
elif self.plugin.name == serviceItem.name:
|
||||
self.generateSlideData(serviceItem)
|
||||
self.plugin.serviceManager.addServiceItem(serviceItem, replace=True)
|
||||
self.service_manager.add_service_item(serviceItem, replace=True)
|
||||
else:
|
||||
# Turn off the remote edit update message indicator
|
||||
QtGui.QMessageBox.information(self, translate('OpenLP.MediaManagerItem', 'Invalid Service Item'),
|
||||
@ -554,8 +575,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
serviceItem = ServiceItem(self.plugin)
|
||||
serviceItem.add_icon(self.plugin.iconPath)
|
||||
if self.generateSlideData(serviceItem, item, xmlVersion, remote,
|
||||
context):
|
||||
if self.generateSlideData(serviceItem, item, xmlVersion, remote, context):
|
||||
return serviceItem
|
||||
else:
|
||||
return None
|
||||
@ -618,3 +638,93 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
Performs a plugin specific search for items containing ``string``
|
||||
"""
|
||||
raise NotImplementedError(u'Plugin.search needs to be defined by the plugin')
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
||||
def _get_renderer(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_renderer'):
|
||||
self._renderer = Registry().get(u'renderer')
|
||||
return self._renderer
|
||||
|
||||
renderer = property(_get_renderer)
|
||||
|
||||
def _get_live_controller(self):
|
||||
"""
|
||||
Adds the live controller to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_live_controller'):
|
||||
self._live_controller = Registry().get(u'live_controller')
|
||||
return self._live_controller
|
||||
|
||||
live_controller = property(_get_live_controller)
|
||||
|
||||
def _get_preview_controller(self):
|
||||
"""
|
||||
Adds the preview controller to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_preview_controller'):
|
||||
self._preview_controller = Registry().get(u'preview_controller')
|
||||
return self._preview_controller
|
||||
|
||||
preview_controller = property(_get_preview_controller)
|
||||
|
||||
def _get_plugin_manager(self):
|
||||
"""
|
||||
Adds the plugin manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_plugin_manager'):
|
||||
self._plugin_manager = Registry().get(u'plugin_manager')
|
||||
return self._plugin_manager
|
||||
|
||||
plugin_manager = property(_get_plugin_manager)
|
||||
|
||||
def _get_media_controller(self):
|
||||
"""
|
||||
Adds the media controller to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_media_controller'):
|
||||
self._media_controller = Registry().get(u'media_controller')
|
||||
return self._media_controller
|
||||
|
||||
media_controller = property(_get_media_controller)
|
||||
|
||||
def _get_service_manager(self):
|
||||
"""
|
||||
Adds the service manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_service_manager'):
|
||||
self._service_manager = Registry().get(u'service_manager')
|
||||
return self._service_manager
|
||||
|
||||
service_manager = property(_get_service_manager)
|
||||
|
||||
def _get_theme_manager(self):
|
||||
"""
|
||||
Adds the theme manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_theme_manager'):
|
||||
self._theme_manager = Registry().get(u'theme_manager')
|
||||
return self._theme_manager
|
||||
|
||||
theme_manager = property(_get_theme_manager)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -33,12 +33,12 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Receiver, Settings
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib import Receiver, Settings, Registry, UiStrings
|
||||
from openlp.core.utils import get_application_version
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PluginStatus(object):
|
||||
"""
|
||||
Defines the status of the plugin
|
||||
@ -119,8 +119,7 @@ class Plugin(QtCore.QObject):
|
||||
"""
|
||||
log.info(u'loaded')
|
||||
|
||||
def __init__(self, name, plugin_helpers=None, media_item_class=None,
|
||||
settings_tab_class=None, version=None):
|
||||
def __init__(self, name, default_settings, media_item_class=None, settings_tab_class=None, version=None):
|
||||
"""
|
||||
This is the constructor for the plugin object. This provides an easy
|
||||
way for descendent plugins to populate common data. This method *must*
|
||||
@ -133,17 +132,17 @@ class Plugin(QtCore.QObject):
|
||||
``name``
|
||||
Defaults to *None*. The name of the plugin.
|
||||
|
||||
``version``
|
||||
Defaults to *None*. The version of the plugin.
|
||||
|
||||
``plugin_helpers``
|
||||
Defaults to *None*. A list of helper objects.
|
||||
``default_settings``
|
||||
A dict containing the plugin's settings. The value to each key is the default value to be used.
|
||||
|
||||
``media_item_class``
|
||||
The class name of the plugin's media item.
|
||||
|
||||
``settings_tab_class``
|
||||
The class name of the plugin's settings tab.
|
||||
|
||||
``version``
|
||||
Defaults to *None*, which means that the same version number is used as OpenLP's version number.
|
||||
"""
|
||||
log.debug(u'Plugin %s initialised' % name)
|
||||
QtCore.QObject.__init__(self)
|
||||
@ -163,15 +162,15 @@ class Plugin(QtCore.QObject):
|
||||
self.mediaItem = None
|
||||
self.weight = 0
|
||||
self.status = PluginStatus.Inactive
|
||||
self.previewController = plugin_helpers[u'preview']
|
||||
self.liveController = plugin_helpers[u'live']
|
||||
self.renderer = plugin_helpers[u'renderer']
|
||||
self.serviceManager = plugin_helpers[u'service']
|
||||
self.settingsForm = plugin_helpers[u'settings form']
|
||||
self.mediaDock = plugin_helpers[u'toolbox']
|
||||
self.pluginManager = plugin_helpers[u'pluginmanager']
|
||||
self.formParent = plugin_helpers[u'formparent']
|
||||
self.mediaController = plugin_helpers[u'mediacontroller']
|
||||
# Add the default status to the default settings.
|
||||
default_settings[name + u'/status'] = PluginStatus.Inactive
|
||||
default_settings[name + u'/last directory'] = u''
|
||||
# Append a setting for files in the mediamanager (note not all plugins
|
||||
# which have a mediamanager need this).
|
||||
if media_item_class is not None:
|
||||
default_settings[u'%s/%s files' % (name, name)] = []
|
||||
# Add settings to the dict of all settings.
|
||||
Settings.extend_default_settings(default_settings)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_add_service_item' % self.name),
|
||||
self.processAddServiceEvent)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_config_updated' % self.name),
|
||||
@ -190,7 +189,7 @@ class Plugin(QtCore.QObject):
|
||||
"""
|
||||
Sets the status of the plugin
|
||||
"""
|
||||
self.status = Settings().value(self.settingsSection + u'/status', PluginStatus.Inactive)
|
||||
self.status = Settings().value(self.settingsSection + u'/status')
|
||||
|
||||
def toggleStatus(self, new_status):
|
||||
"""
|
||||
@ -217,7 +216,7 @@ class Plugin(QtCore.QObject):
|
||||
you need, and return it for integration into OpenLP.
|
||||
"""
|
||||
if self.mediaItemClass:
|
||||
self.mediaItem = self.mediaItemClass(self.mediaDock.media_dock, self, self.icon)
|
||||
self.mediaItem = self.mediaItemClass(self.main_window.mediaDockManager.media_dock, self, self.icon)
|
||||
|
||||
def addImportMenuItem(self, importMenu):
|
||||
"""
|
||||
@ -287,20 +286,40 @@ class Plugin(QtCore.QObject):
|
||||
"""
|
||||
if self.mediaItem:
|
||||
self.mediaItem.initialise()
|
||||
self.mediaDock.insert_dock(self.mediaItem, self.icon, self.weight)
|
||||
self.main_window.mediaDockManager.insert_dock(self.mediaItem, self.icon, self.weight)
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Called by the plugin Manager to cleanup things.
|
||||
"""
|
||||
if self.mediaItem:
|
||||
self.mediaDock.remove_dock(self.mediaItem)
|
||||
self.main_window.mediaDockManager.remove_dock(self.mediaItem)
|
||||
|
||||
def appStartup(self):
|
||||
def app_startup(self):
|
||||
"""
|
||||
Perform tasks on application startup
|
||||
"""
|
||||
pass
|
||||
# FIXME: Remove after 2.2 release.
|
||||
# This is needed to load the list of images/media/presentation from the config saved
|
||||
# before the settings rewrite.
|
||||
if self.mediaItemClass is not None:
|
||||
# We need QSettings instead of Settings here to bypass our central settings dict.
|
||||
# Do NOT do this anywhere else!
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
if settings.contains(u'%s count' % self.name):
|
||||
list_count = int(settings.value(u'%s count' % self.name, 0))
|
||||
loaded_list = []
|
||||
if list_count:
|
||||
for counter in range(list_count):
|
||||
item = settings.value(u'%s %d' % (self.name, counter), u'')
|
||||
if item:
|
||||
loaded_list.append(item)
|
||||
settings.remove(u'%s %d' % (self.name, counter))
|
||||
settings.remove(u'%s count' % self.name)
|
||||
# Now save the list to the config using our Settings class.
|
||||
Settings().setValue(u'%s/%s files' % (self.settingsSection, self.name), loaded_list)
|
||||
settings.endGroup()
|
||||
|
||||
def usesTheme(self, theme):
|
||||
"""
|
||||
@ -389,3 +408,29 @@ class Plugin(QtCore.QObject):
|
||||
The plugin's config has changed
|
||||
"""
|
||||
pass
|
||||
|
||||
def new_service_created(self):
|
||||
"""
|
||||
The plugin's needs to handle a new song creation
|
||||
"""
|
||||
pass
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -33,23 +33,17 @@ import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Plugin, PluginStatus
|
||||
from openlp.core.lib import Plugin, PluginStatus, Registry
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PluginManager(object):
|
||||
"""
|
||||
This is the Plugin manager, which loads all the plugins,
|
||||
and executes all the hooks, as and when necessary.
|
||||
"""
|
||||
log.info(u'Plugin manager loaded')
|
||||
__instance__ = None
|
||||
@staticmethod
|
||||
def get_instance():
|
||||
"""
|
||||
Obtain a single instance of class.
|
||||
"""
|
||||
return PluginManager.__instance__
|
||||
|
||||
def __init__(self, plugin_dir):
|
||||
"""
|
||||
@ -60,7 +54,7 @@ class PluginManager(object):
|
||||
The directory to search for plugins.
|
||||
"""
|
||||
log.info(u'Plugin manager Initialising')
|
||||
PluginManager.__instance__ = self
|
||||
Registry().register(u'plugin_manager', self)
|
||||
if not plugin_dir in sys.path:
|
||||
log.debug(u'Inserting %s into sys.path', plugin_dir)
|
||||
sys.path.insert(0, plugin_dir)
|
||||
@ -69,7 +63,7 @@ class PluginManager(object):
|
||||
self.plugins = []
|
||||
log.info(u'Plugin manager Initialised')
|
||||
|
||||
def find_plugins(self, plugin_dir, plugin_helpers):
|
||||
def find_plugins(self, plugin_dir):
|
||||
"""
|
||||
Scan the directory ``plugin_dir`` for objects inheriting from the
|
||||
``Plugin`` class.
|
||||
@ -77,9 +71,6 @@ class PluginManager(object):
|
||||
``plugin_dir``
|
||||
The directory to scan.
|
||||
|
||||
``plugin_helpers``
|
||||
A list of helper objects to pass to the plugins.
|
||||
|
||||
"""
|
||||
log.info(u'Finding plugins')
|
||||
startdepth = len(os.path.abspath(plugin_dir).split(os.sep))
|
||||
@ -117,7 +108,7 @@ class PluginManager(object):
|
||||
plugin_objects = []
|
||||
for p in plugin_classes:
|
||||
try:
|
||||
plugin = p(plugin_helpers)
|
||||
plugin = p()
|
||||
log.debug(u'Loaded plugin %s', unicode(p))
|
||||
plugin_objects.append(plugin)
|
||||
except TypeError:
|
||||
@ -221,3 +212,13 @@ class PluginManager(object):
|
||||
if plugin.name == name:
|
||||
return plugin
|
||||
return None
|
||||
|
||||
def new_service_created(self):
|
||||
"""
|
||||
Loop through all the plugins and give them an opportunity to handle a new service
|
||||
"""
|
||||
log.info(u'plugins - new service created')
|
||||
for plugin in self.plugins:
|
||||
if plugin.isActive():
|
||||
plugin.new_service_created()
|
||||
|
||||
|
98
openlp/core/lib/registry.py
Normal file
98
openlp/core/lib/registry.py
Normal file
@ -0,0 +1,98 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
Provide Registry Services
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Registry(object):
|
||||
"""
|
||||
This is the Component Registry. It is a singleton object and is used to provide a
|
||||
look up service for common objects.
|
||||
"""
|
||||
log.info(u'Registry loaded')
|
||||
__instance__ = None
|
||||
|
||||
def __new__(cls):
|
||||
"""
|
||||
Re-implement the __new__ method to make sure we create a true singleton.
|
||||
"""
|
||||
if not cls.__instance__:
|
||||
cls.__instance__ = object.__new__(cls)
|
||||
return cls.__instance__
|
||||
|
||||
@classmethod
|
||||
def create(cls):
|
||||
"""
|
||||
The constructor for the component registry providing a single registry of objects.
|
||||
"""
|
||||
log.info(u'Registry Initialising')
|
||||
registry = cls()
|
||||
registry.service_list = {}
|
||||
registry.running_under_test = False
|
||||
# Allow the tests to remove Registry entries but not the live system
|
||||
if u'nosetest' in sys.argv[0]:
|
||||
registry.running_under_test = True
|
||||
return registry
|
||||
|
||||
def get(self, key):
|
||||
"""
|
||||
Extracts the registry value from the list based on the key passed in
|
||||
"""
|
||||
if key in self.service_list:
|
||||
return self.service_list[key]
|
||||
else:
|
||||
log.error(u'Service %s not found in list' % key)
|
||||
raise KeyError(u'Service %s not found in list' % key)
|
||||
|
||||
def register(self, key, reference):
|
||||
"""
|
||||
Registers a component against a key.
|
||||
"""
|
||||
if key in self.service_list:
|
||||
log.error(u'Duplicate service exception %s' % key)
|
||||
raise KeyError(u'Duplicate service exception %s' % key)
|
||||
else:
|
||||
self.service_list[key] = reference
|
||||
|
||||
def remove(self, key):
|
||||
"""
|
||||
Removes the registry value from the list based on the key passed in
|
||||
(Only valid and active for testing framework)
|
||||
"""
|
||||
if self.running_under_test is False:
|
||||
log.error(u'Invalid Method call for key %s' % key)
|
||||
raise KeyError(u'Invalid Method call for key %s' % key)
|
||||
return
|
||||
if key in self.service_list:
|
||||
del self.service_list[key]
|
@ -31,10 +31,10 @@ import logging
|
||||
|
||||
from PyQt4 import QtGui, QtCore, QtWebKit
|
||||
|
||||
from openlp.core.lib import ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css, Receiver, \
|
||||
ItemCapabilities, FormattingTags, ImageSource
|
||||
from openlp.core.lib import FormattingTags, ImageSource, ItemCapabilities, Receiver, Registry, ScreenList, \
|
||||
ServiceItem, expand_tags, build_lyrics_format_css, build_lyrics_outline_css
|
||||
from openlp.core.lib.theme import ThemeLevel
|
||||
from openlp.core.ui import MainDisplay, ScreenList
|
||||
from openlp.core.ui import MainDisplay
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -48,6 +48,7 @@ VERSE = u'The Lord said to {r}Noah{/r}: \n' \
|
||||
VERSE_FOR_LINE_COUNT = u'\n'.join(map(unicode, xrange(50)))
|
||||
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
|
||||
|
||||
|
||||
class Renderer(object):
|
||||
"""
|
||||
Class to pull all Renderer interactions into one place. The plugins will
|
||||
@ -56,7 +57,7 @@ class Renderer(object):
|
||||
"""
|
||||
log.info(u'Renderer Loaded')
|
||||
|
||||
def __init__(self, image_manager, theme_manager):
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise the renderer.
|
||||
|
||||
@ -68,15 +69,14 @@ class Renderer(object):
|
||||
The theme_manager instance, used to get the current theme details.
|
||||
"""
|
||||
log.debug(u'Initialisation started')
|
||||
self.theme_manager = theme_manager
|
||||
self.image_manager = image_manager
|
||||
self.screens = ScreenList()
|
||||
Registry().register(u'renderer', self)
|
||||
self.theme_level = ThemeLevel.Global
|
||||
self.global_theme_name = u''
|
||||
self.service_theme_name = u''
|
||||
self.item_theme_name = u''
|
||||
self.force_page = False
|
||||
self.display = MainDisplay(None, self.image_manager, False, self)
|
||||
self.display = MainDisplay(None, False, self)
|
||||
self.display.setup()
|
||||
self._theme_dimensions = {}
|
||||
self._calculate_default()
|
||||
@ -93,7 +93,7 @@ class Renderer(object):
|
||||
self._calculate_default()
|
||||
if self.display:
|
||||
self.display.close()
|
||||
self.display = MainDisplay(None, self.image_manager, False, self)
|
||||
self.display = MainDisplay(None, False, self)
|
||||
self.display.setup()
|
||||
self._theme_dimensions = {}
|
||||
|
||||
@ -128,7 +128,7 @@ class Renderer(object):
|
||||
The theme name.
|
||||
"""
|
||||
if theme_name not in self._theme_dimensions:
|
||||
theme_data = self.theme_manager.getThemeData(theme_name)
|
||||
theme_data = self.theme_manager.get_theme_data(theme_name)
|
||||
main_rect = self.get_main_rectangle(theme_data)
|
||||
footer_rect = self.get_footer_rectangle(theme_data)
|
||||
self._theme_dimensions[theme_name] = [theme_data, main_rect, footer_rect]
|
||||
@ -136,7 +136,7 @@ class Renderer(object):
|
||||
theme_data, main_rect, footer_rect = self._theme_dimensions[theme_name]
|
||||
# if No file do not update cache
|
||||
if theme_data.background_filename:
|
||||
self.image_manager.addImage(theme_data.background_filename,
|
||||
self.image_manager.add_image(theme_data.background_filename,
|
||||
ImageSource.Theme, QtGui.QColor(theme_data.background_border_color))
|
||||
|
||||
def pre_render(self, override_theme_data=None):
|
||||
@ -235,11 +235,10 @@ class Renderer(object):
|
||||
serviceItem.add_from_text(VERSE_FOR_LINE_COUNT)
|
||||
else:
|
||||
serviceItem.add_from_text(VERSE)
|
||||
serviceItem.renderer = self
|
||||
serviceItem.raw_footer = FOOTER
|
||||
# if No file do not update cache
|
||||
if theme_data.background_filename:
|
||||
self.image_manager.addImage(theme_data.background_filename,
|
||||
self.image_manager.add_image(theme_data.background_filename,
|
||||
ImageSource.Theme,
|
||||
QtGui.QColor(theme_data.background_border_color))
|
||||
theme_data, main, footer = self.pre_render(theme_data)
|
||||
@ -643,3 +642,24 @@ class Renderer(object):
|
||||
# this parse we are to be wordy
|
||||
line = line.replace(u'\n', u' ')
|
||||
return line.split(u' ')
|
||||
|
||||
def _get_image_manager(self):
|
||||
"""
|
||||
Adds the image manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_image_manager'):
|
||||
self._image_manager = Registry().get(u'image_manager')
|
||||
return self._image_manager
|
||||
|
||||
image_manager = property(_get_image_manager)
|
||||
|
||||
def _get_theme_manager(self):
|
||||
"""
|
||||
Adds the theme manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_theme_manager'):
|
||||
self._theme_manager = Registry().get(u'theme_manager')
|
||||
return self._theme_manager
|
||||
|
||||
theme_manager = property(_get_theme_manager)
|
||||
|
||||
|
@ -35,10 +35,11 @@ import copy
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Receiver, translate, Settings
|
||||
from openlp.core.lib import Receiver, translate
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ScreenList(object):
|
||||
"""
|
||||
Wrapper to handle the parameters of the display screen.
|
||||
@ -49,6 +50,9 @@ class ScreenList(object):
|
||||
__instance__ = None
|
||||
|
||||
def __new__(cls):
|
||||
"""
|
||||
Re-implement __new__ to create a true singleton.
|
||||
"""
|
||||
if not cls.__instance__:
|
||||
cls.__instance__ = object.__new__(cls)
|
||||
return cls.__instance__
|
||||
@ -69,7 +73,7 @@ class ScreenList(object):
|
||||
screen_list.screen_list = []
|
||||
screen_list.display_count = 0
|
||||
screen_list.screen_count_changed()
|
||||
screen_list._load_screen_settings()
|
||||
screen_list.load_screen_settings()
|
||||
QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'resized(int)'), screen_list.screen_resolution_changed)
|
||||
QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'screenCountChanged(int)'), screen_list.screen_count_changed)
|
||||
return screen_list
|
||||
@ -135,8 +139,7 @@ class ScreenList(object):
|
||||
"""
|
||||
screen_list = []
|
||||
for screen in self.screen_list:
|
||||
screen_name = u'%s %d' % (translate('OpenLP.ScreenList', 'Screen'),
|
||||
screen[u'number'] + 1)
|
||||
screen_name = u'%s %d' % (translate('OpenLP.ScreenList', 'Screen'), screen[u'number'] + 1)
|
||||
if screen[u'primary']:
|
||||
screen_name = u'%s (%s)' % (screen_name, translate('OpenLP.ScreenList', 'primary'))
|
||||
screen_list.append(screen_name)
|
||||
@ -233,23 +236,34 @@ class ScreenList(object):
|
||||
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()):
|
||||
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.
|
||||
"""
|
||||
from openlp.core.lib import Settings
|
||||
# Add the screen settings to the settings dict. This has to be done here due to crycle dependency.
|
||||
# Do not do this anywhere else.
|
||||
screen_settings = {
|
||||
u'general/x position': self.current[u'size'].x(),
|
||||
u'general/y position': self.current[u'size'].y(),
|
||||
u'general/monitor': self.display_count - 1,
|
||||
u'general/height': self.current[u'size'].height(),
|
||||
u'general/width': self.current[u'size'].width()
|
||||
}
|
||||
Settings.extend_default_settings(screen_settings)
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'general')
|
||||
self.set_current_display(settings.value(u'monitor', self.display_count - 1))
|
||||
self.display = settings.value(u'display on monitor', True)
|
||||
override_display = settings.value(u'override position', False)
|
||||
x = settings.value(u'x position', self.current[u'size'].x())
|
||||
y = settings.value(u'y position', self.current[u'size'].y())
|
||||
width = settings.value(u'width', self.current[u'size'].width())
|
||||
height = settings.value(u'height', self.current[u'size'].height())
|
||||
monitor = settings.value(u'monitor')
|
||||
self.set_current_display(monitor)
|
||||
self.display = settings.value(u'display on monitor')
|
||||
override_display = settings.value(u'override position')
|
||||
x = settings.value(u'x position')
|
||||
y = settings.value(u'y position')
|
||||
width = settings.value(u'width')
|
||||
height = settings.value(u'height')
|
||||
self.override[u'size'] = QtCore.QRect(x, y, width, height)
|
||||
self.override[u'primary'] = False
|
||||
settings.endGroup()
|
@ -36,6 +36,7 @@ from openlp.core.lib.ui import create_widget_action
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SearchEdit(QtGui.QLineEdit):
|
||||
"""
|
||||
This is a specialised QLineEdit with a "clear" button inside for searches.
|
||||
|
@ -37,10 +37,13 @@ import logging
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from openlp.core.lib import build_icon, clean_tags, expand_tags, translate, ImageSource
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import ImageSource, Settings, Registry, build_icon, clean_tags, expand_tags, translate
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ServiceItemType(object):
|
||||
"""
|
||||
Defines the type of service item
|
||||
@ -146,7 +149,6 @@ class ServiceItem(object):
|
||||
The plugin that this service item belongs to.
|
||||
"""
|
||||
if plugin:
|
||||
self.renderer = plugin.renderer
|
||||
self.name = plugin.name
|
||||
self.title = u''
|
||||
self.shortname = u''
|
||||
@ -159,7 +161,7 @@ class ServiceItem(object):
|
||||
self.service_item_type = None
|
||||
self._raw_frames = []
|
||||
self._display_frames = []
|
||||
self._uuid = 0
|
||||
self.unique_identifier = 0
|
||||
self.notes = u''
|
||||
self.from_plugin = False
|
||||
self.capabilities = []
|
||||
@ -181,7 +183,11 @@ class ServiceItem(object):
|
||||
self.background_audio = []
|
||||
self.theme_overwritten = False
|
||||
self.temporary_edit = False
|
||||
self.auto_play_slides_once = False
|
||||
self.auto_play_slides_loop = False
|
||||
self.timed_slide_interval = 0
|
||||
self.will_auto_start = False
|
||||
self.has_original_files = True
|
||||
self._new_item()
|
||||
|
||||
def _new_item(self):
|
||||
@ -189,7 +195,8 @@ class ServiceItem(object):
|
||||
Method to set the internal id of the item. This is used to compare
|
||||
service items to see if they are the same.
|
||||
"""
|
||||
self._uuid = unicode(uuid.uuid1())
|
||||
self.unique_identifier = unicode(uuid.uuid1())
|
||||
self.validate_item()
|
||||
|
||||
def add_capability(self, capability):
|
||||
"""
|
||||
@ -286,7 +293,7 @@ class ServiceItem(object):
|
||||
self.image_border = background
|
||||
self.service_item_type = ServiceItemType.Image
|
||||
self._raw_frames.append({u'title': title, u'path': path})
|
||||
self.renderer.image_manager.addImage(path, ImageSource.ImagePlugin, self.image_border)
|
||||
self.image_manager.add_image(path, ImageSource.ImagePlugin, self.image_border)
|
||||
self._new_item()
|
||||
|
||||
def add_from_text(self, raw_slide, verse_tag=None):
|
||||
@ -340,6 +347,9 @@ class ServiceItem(object):
|
||||
u'search': self.search_string,
|
||||
u'data': self.data_string,
|
||||
u'xml_version': self.xml_version,
|
||||
u'auto_play_slides_once': self.auto_play_slides_once,
|
||||
u'auto_play_slides_loop': self.auto_play_slides_loop,
|
||||
u'timed_slide_interval': self.timed_slide_interval,
|
||||
u'start_time': self.start_time,
|
||||
u'end_time': self.end_time,
|
||||
u'media_length': self.media_length,
|
||||
@ -394,7 +404,11 @@ class ServiceItem(object):
|
||||
self.start_time = header.get(u'start_time', 0)
|
||||
self.end_time = header.get(u'end_time', 0)
|
||||
self.media_length = header.get(u'media_length', 0)
|
||||
self.auto_play_slides_once = header.get(u'auto_play_slides_once', False)
|
||||
self.auto_play_slides_loop = header.get(u'auto_play_slides_loop', False)
|
||||
self.timed_slide_interval = header.get(u'timed_slide_interval', 0)
|
||||
self.will_auto_start = header.get(u'will_auto_start', False)
|
||||
self.has_original_files = True
|
||||
if u'background_audio' in header:
|
||||
self.background_audio = []
|
||||
for filename in header[u'background_audio']:
|
||||
@ -405,20 +419,23 @@ class ServiceItem(object):
|
||||
for slide in serviceitem[u'serviceitem'][u'data']:
|
||||
self._raw_frames.append(slide)
|
||||
elif self.service_item_type == ServiceItemType.Image:
|
||||
settingsSection = serviceitem[u'serviceitem'][u'header'][u'name']
|
||||
background = QtGui.QColor(Settings().value(settingsSection + u'/background color'))
|
||||
if path:
|
||||
self.has_original_files = False
|
||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||
filename = os.path.join(path, text_image)
|
||||
self.add_from_image(filename, text_image)
|
||||
self.add_from_image(filename, text_image, background)
|
||||
else:
|
||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||
self.add_from_image(text_image[u'path'], text_image[u'title'])
|
||||
self.add_from_image(text_image[u'path'], text_image[u'title'], background)
|
||||
elif self.service_item_type == ServiceItemType.Command:
|
||||
for text_image in serviceitem[u'serviceitem'][u'data']:
|
||||
if path:
|
||||
self.has_original_files = False
|
||||
self.add_from_command(path, text_image[u'title'], text_image[u'image'])
|
||||
else:
|
||||
self.add_from_command(text_image[u'path'], text_image[u'title'], text_image[u'image'])
|
||||
|
||||
self._new_item()
|
||||
|
||||
def get_display_title(self):
|
||||
@ -437,14 +454,14 @@ class ServiceItem(object):
|
||||
|
||||
def merge(self, other):
|
||||
"""
|
||||
Updates the _uuid with the value from the original one
|
||||
The _uuid is unique for a given service item but this allows one to
|
||||
Updates the unique_identifier with the value from the original one
|
||||
The unique_identifier is unique for a given service item but this allows one to
|
||||
replace an original version.
|
||||
|
||||
``other``
|
||||
The service item to be merged with
|
||||
"""
|
||||
self._uuid = other._uuid
|
||||
self.unique_identifier = other.unique_identifier
|
||||
self.notes = other.notes
|
||||
self.temporary_edit = other.temporary_edit
|
||||
# Copy theme over if present.
|
||||
@ -461,13 +478,13 @@ class ServiceItem(object):
|
||||
"""
|
||||
if not other:
|
||||
return False
|
||||
return self._uuid == other._uuid
|
||||
return self.unique_identifier == other.unique_identifier
|
||||
|
||||
def __ne__(self, other):
|
||||
"""
|
||||
Confirms the service items are not for the same instance
|
||||
"""
|
||||
return self._uuid != other._uuid
|
||||
return self.unique_identifier != other.unique_identifier
|
||||
|
||||
def is_media(self):
|
||||
"""
|
||||
@ -591,7 +608,7 @@ class ServiceItem(object):
|
||||
``theme``
|
||||
The new theme to be replaced in the service item
|
||||
"""
|
||||
self.theme_overwritten = (theme == None)
|
||||
self.theme_overwritten = (theme is None)
|
||||
self.theme = theme
|
||||
self._new_item()
|
||||
self.render()
|
||||
@ -605,8 +622,45 @@ class ServiceItem(object):
|
||||
if self.get_frame_path(frame=frame) in invalid_paths:
|
||||
self.remove_frame(frame)
|
||||
|
||||
def validate(self):
|
||||
def missing_frames(self):
|
||||
"""
|
||||
Validates this service item
|
||||
Returns if there are any frames in the service item
|
||||
"""
|
||||
return bool(self._raw_frames)
|
||||
return not bool(self._raw_frames)
|
||||
|
||||
def validate_item(self, suffix_list=None):
|
||||
"""
|
||||
Validates a service item to make sure it is valid
|
||||
"""
|
||||
self.is_valid = True
|
||||
for frame in self._raw_frames:
|
||||
if self.is_image() and not os.path.exists((frame[u'path'])):
|
||||
self.is_valid = False
|
||||
elif self.is_command():
|
||||
file_name = os.path.join(frame[u'path'], frame[u'title'])
|
||||
if not os.path.exists(file_name):
|
||||
self.is_valid = False
|
||||
if suffix_list and not self.is_text():
|
||||
file_suffix = frame[u'title'].split(u'.')[-1]
|
||||
if file_suffix.lower() not in suffix_list:
|
||||
self.is_valid = False
|
||||
|
||||
def _get_renderer(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_renderer'):
|
||||
self._renderer = Registry().get(u'renderer')
|
||||
return self._renderer
|
||||
|
||||
renderer = property(_get_renderer)
|
||||
|
||||
def _get_image_manager(self):
|
||||
"""
|
||||
Adds the image manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_image_manager'):
|
||||
self._image_manager = Registry().get(u'image_manager')
|
||||
return self._image_manager
|
||||
|
||||
image_manager = property(_get_image_manager)
|
||||
|
365
openlp/core/lib/settings.py
Normal file
365
openlp/core/lib/settings.py
Normal file
@ -0,0 +1,365 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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 #
|
||||
###############################################################################
|
||||
"""
|
||||
This class contains the core default settings.
|
||||
"""
|
||||
import datetime
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SlideLimits
|
||||
from openlp.core.lib.theme import ThemeLevel
|
||||
from openlp.core.lib import UiStrings
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Fix for bug #1014422.
|
||||
X11_BYPASS_DEFAULT = True
|
||||
if sys.platform.startswith(u'linux'):
|
||||
# Default to False on Gnome.
|
||||
X11_BYPASS_DEFAULT = bool(not os.environ.get(u'GNOME_DESKTOP_SESSION_ID'))
|
||||
# Default to False on Xfce.
|
||||
if os.environ.get(u'DESKTOP_SESSION') == u'xfce':
|
||||
X11_BYPASS_DEFAULT = False
|
||||
|
||||
|
||||
class Settings(QtCore.QSettings):
|
||||
"""
|
||||
Class to wrap QSettings.
|
||||
|
||||
* Exposes all the methods of QSettings.
|
||||
* Adds functionality for OpenLP Portable. If the ``defaultFormat`` is set to
|
||||
``IniFormat``, and the path to the Ini file is set using ``set_filename``,
|
||||
then the Settings constructor (without any arguments) will create a Settings
|
||||
object for accessing settings stored in that Ini file.
|
||||
|
||||
``__default_settings__``
|
||||
This dict contains all core settings with their default values.
|
||||
|
||||
``__obsolete_settings__``
|
||||
Each entry is structured in the following way::
|
||||
|
||||
(u'general/enable slide loop', u'advanced/slide limits', [(SlideLimits.Wrap, True), (SlideLimits.End, False)])
|
||||
|
||||
The first entry is the *old key*; it will be removed.
|
||||
|
||||
The second entry is the *new key*; we will add it to the config. If this is just an empty string, we just remove
|
||||
the old key.
|
||||
|
||||
The last entry is a list containing two-pair tuples. If the list is empty, no conversion is made. Otherwise each
|
||||
pair describes how to convert the old setting's value::
|
||||
|
||||
(SlideLimits.Wrap, True)
|
||||
|
||||
This means, that if the value of ``general/enable slide loop`` is equal (``==``) ``True`` then we set
|
||||
``advanced/slide limits`` to ``SlideLimits.Wrap``. **NOTE**, this means that the rules have to cover all cases!
|
||||
So, if the type of the old value is bool, then there must be two rules.
|
||||
"""
|
||||
__default_settings__ = {
|
||||
u'advanced/add page break': False,
|
||||
u'advanced/alternate rows': not sys.platform.startswith(u'win'),
|
||||
u'advanced/current media plugin': -1,
|
||||
u'advanced/data path': u'',
|
||||
u'advanced/default color': u'#ffffff',
|
||||
u'advanced/default image': u':/graphics/openlp-splash-screen.png',
|
||||
# 7 stands for now, 0 to 6 is Monday to Sunday.
|
||||
u'advanced/default service day': 7,
|
||||
u'advanced/default service enabled': True,
|
||||
u'advanced/default service hour': 11,
|
||||
u'advanced/default service minute': 0,
|
||||
u'advanced/default service name': UiStrings().DefaultServiceName,
|
||||
u'advanced/display size': 0,
|
||||
u'advanced/double click live': False,
|
||||
u'advanced/enable exit confirmation': True,
|
||||
u'advanced/expand service item': False,
|
||||
u'advanced/hide mouse': True,
|
||||
u'advanced/is portable': False,
|
||||
u'advanced/max recent files': 20,
|
||||
u'advanced/print file meta data': False,
|
||||
u'advanced/print notes': False,
|
||||
u'advanced/print slide text': False,
|
||||
u'advanced/recent file count': 4,
|
||||
u'advanced/save current plugin': False,
|
||||
u'advanced/slide limits': SlideLimits.End,
|
||||
u'advanced/single click preview': False,
|
||||
u'advanced/x11 bypass wm': X11_BYPASS_DEFAULT,
|
||||
u'crashreport/last directory': u'',
|
||||
u'displayTags/html_tags': u'',
|
||||
u'general/audio repeat list': False,
|
||||
u'general/auto open': False,
|
||||
u'general/auto preview': False,
|
||||
u'general/audio start paused': True,
|
||||
u'general/auto unblank': False,
|
||||
u'general/blank warning': False,
|
||||
u'general/ccli number': u'',
|
||||
u'general/has run wizard': False,
|
||||
u'general/language': u'[en]',
|
||||
# This defaults to yesterday in order to force the update check to run when you've never run it before.
|
||||
u'general/last version test': datetime.datetime.now().date() - datetime.timedelta(days=1),
|
||||
u'general/loop delay': 5,
|
||||
u'general/recent files': [],
|
||||
u'general/save prompt': False,
|
||||
u'general/screen blank': False,
|
||||
u'general/show splash': True,
|
||||
u'general/songselect password': u'',
|
||||
u'general/songselect username': u'',
|
||||
u'general/update check': True,
|
||||
u'general/view mode': u'default',
|
||||
# The other display settings (display position and dimensions) are defined in the ScreenList class due to a
|
||||
# circular dependency.
|
||||
u'general/display on monitor': True,
|
||||
u'general/override position': False,
|
||||
u'media/players': u'webkit',
|
||||
u'media/override player': QtCore.Qt.Unchecked,
|
||||
u'players/background color': u'#000000',
|
||||
u'servicemanager/last directory': u'',
|
||||
u'servicemanager/last file': u'',
|
||||
u'servicemanager/service theme': u'',
|
||||
u'SettingsImport/file_date_created': datetime.datetime.now().strftime("%Y-%m-%d %H:%M"),
|
||||
u'SettingsImport/Make_Changes': u'At_Own_RISK',
|
||||
u'SettingsImport/type': u'OpenLP_settings_export',
|
||||
u'SettingsImport/version': u'',
|
||||
u'shortcuts/aboutItem': [QtGui.QKeySequence(u'Ctrl+F1')],
|
||||
u'shortcuts/audioPauseItem': [],
|
||||
u'shortcuts/displayTagItem': [],
|
||||
u'shortcuts/blankScreen': [QtCore.Qt.Key_Period],
|
||||
u'shortcuts/collapse': [QtCore.Qt.Key_Minus],
|
||||
u'shortcuts/desktopScreen': [QtGui.QKeySequence(u'D')],
|
||||
u'shortcuts/down': [QtCore.Qt.Key_Down],
|
||||
u'shortcuts/escapeItem': [QtCore.Qt.Key_Escape],
|
||||
u'shortcuts/expand': [QtCore.Qt.Key_Plus],
|
||||
u'shortcuts/exportThemeItem': [],
|
||||
u'shortcuts/fileNewItem': [QtGui.QKeySequence(u'Ctrl+N')],
|
||||
u'shortcuts/fileSaveAsItem': [QtGui.QKeySequence(u'Ctrl+Shift+S')],
|
||||
u'shortcuts/fileExitItem': [QtGui.QKeySequence(u'Alt+F4')],
|
||||
u'shortcuts/fileSaveItem': [QtGui.QKeySequence(u'Ctrl+S')],
|
||||
u'shortcuts/fileOpenItem': [QtGui.QKeySequence(u'Ctrl+O')],
|
||||
u'shortcuts/importThemeItem': [],
|
||||
u'shortcuts/importBibleItem': [],
|
||||
u'shortcuts/modeDefaultItem': [],
|
||||
u'shortcuts/modeLiveItem': [],
|
||||
u'shortcuts/make_live': [QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return],
|
||||
u'shortcuts/moveUp': [QtCore.Qt.Key_PageUp],
|
||||
u'shortcuts/moveTop': [QtCore.Qt.Key_Home],
|
||||
u'shortcuts/modeSetupItem': [],
|
||||
u'shortcuts/moveBottom': [QtCore.Qt.Key_End],
|
||||
u'shortcuts/moveDown': [QtCore.Qt.Key_PageDown],
|
||||
u'shortcuts/nextTrackItem': [],
|
||||
u'shortcuts/nextItem_live': [QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown],
|
||||
u'shortcuts/nextService': [QtCore.Qt.Key_Right],
|
||||
u'shortcuts/offlineHelpItem': [],
|
||||
u'shortcuts/onlineHelpItem': [QtGui.QKeySequence(u'Alt+F1')],
|
||||
u'shortcuts/previousItem_live': [QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp],
|
||||
u'shortcuts/playSlidesLoop': [],
|
||||
u'shortcuts/playSlidesOnce': [],
|
||||
u'shortcuts/previousService': [QtCore.Qt.Key_Left],
|
||||
u'shortcuts/printServiceItem': [QtGui.QKeySequence(u'Ctrl+P')],
|
||||
u'shortcuts/songExportItem': [],
|
||||
u'shortcuts/songUsageStatus': [QtCore.Qt.Key_F4],
|
||||
u'shortcuts/settingsShortcutsItem': [],
|
||||
u'shortcuts/settingsImportItem': [],
|
||||
u'shortcuts/settingsPluginListItem': [QtGui.QKeySequence(u'Alt+F7')],
|
||||
u'shortcuts/songUsageDelete': [],
|
||||
u'shortcuts/settingsConfigureItem': [],
|
||||
u'shortcuts/shortcutAction_B': [QtGui.QKeySequence(u'B')],
|
||||
u'shortcuts/shortcutAction_C': [QtGui.QKeySequence(u'C')],
|
||||
u'shortcuts/shortcutAction_E': [QtGui.QKeySequence(u'E')],
|
||||
u'shortcuts/shortcutAction_I': [QtGui.QKeySequence(u'I')],
|
||||
u'shortcuts/shortcutAction_O': [QtGui.QKeySequence(u'O')],
|
||||
u'shortcuts/shortcutAction_P': [QtGui.QKeySequence(u'P')],
|
||||
u'shortcuts/shortcutAction_V': [QtGui.QKeySequence(u'V')],
|
||||
u'shortcuts/settingsExportItem': [],
|
||||
u'shortcuts/songUsageReport': [],
|
||||
u'shortcuts/songImportItem': [],
|
||||
u'shortcuts/themeScreen': [QtGui.QKeySequence(u'T')],
|
||||
u'shortcuts/toolsReindexItem': [],
|
||||
u'shortcuts/toolsAlertItem': [u'F7'],
|
||||
u'shortcuts/toolsFirstTimeWizard': [],
|
||||
u'shortcuts/toolsOpenDataFolder': [],
|
||||
u'shortcuts/toolsAddToolItem': [],
|
||||
u'shortcuts/updateThemeImages': [],
|
||||
u'shortcuts/up': [QtCore.Qt.Key_Up],
|
||||
u'shortcuts/viewThemeManagerItem': [QtGui.QKeySequence(u'F10')],
|
||||
u'shortcuts/viewMediaManagerItem': [QtGui.QKeySequence(u'F8')],
|
||||
u'shortcuts/viewPreviewPanel': [QtGui.QKeySequence(u'F11')],
|
||||
u'shortcuts/viewLivePanel': [QtGui.QKeySequence(u'F12')],
|
||||
u'shortcuts/viewServiceManagerItem': [QtGui.QKeySequence(u'F9')],
|
||||
u'shortcuts/webSiteItem': [],
|
||||
u'themes/global theme': u'',
|
||||
u'themes/last directory': u'',
|
||||
u'themes/last directory export': u'',
|
||||
u'themes/last directory import': u'',
|
||||
u'themes/theme level': ThemeLevel.Song,
|
||||
u'user interface/live panel': True,
|
||||
u'user interface/live splitter geometry': QtCore.QByteArray(),
|
||||
u'user interface/lock panel': False,
|
||||
u'user interface/main window geometry': QtCore.QByteArray(),
|
||||
u'user interface/main window position': QtCore.QPoint(0, 0),
|
||||
u'user interface/main window splitter geometry': QtCore.QByteArray(),
|
||||
u'user interface/main window state': QtCore.QByteArray(),
|
||||
u'user interface/preview panel': True,
|
||||
u'user interface/preview splitter geometry': QtCore.QByteArray()
|
||||
}
|
||||
__file_path__ = u''
|
||||
__obsolete_settings__ = [
|
||||
# Changed during 1.9.x development.
|
||||
(u'bibles/bookname language', u'bibles/book name language', []),
|
||||
(u'general/enable slide loop', u'advanced/slide limits', [(SlideLimits.Wrap, True), (SlideLimits.End, False)]),
|
||||
(u'songs/ccli number', u'general/ccli number', []),
|
||||
# Changed during 2.1.x development.
|
||||
(u'advanced/stylesheet fix', u'', []),
|
||||
(u'bibles/last directory 1', u'bibles/last directory import', []),
|
||||
(u'media/background color', u'players/background color', []),
|
||||
(u'themes/last directory', u'themes/last directory import', []),
|
||||
(u'themes/last directory 1', u'themes/last directory export', []),
|
||||
(u'songs/last directory 1', u'songs/last directory import', []),
|
||||
(u'songusage/last directory 1', u'songusage/last directory export', []),
|
||||
(u'user interface/mainwindow splitter geometry', u'user interface/main window splitter geometry', []),
|
||||
(u'shortcuts/makeLive', u'shortcuts/make_live', [])
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def extend_default_settings(default_values):
|
||||
"""
|
||||
Static method to merge the given ``default_values`` with the ``Settings.__default_settings__``.
|
||||
|
||||
``default_values``
|
||||
A dict with setting keys and their default values.
|
||||
"""
|
||||
Settings.__default_settings__ = dict(default_values.items() + Settings.__default_settings__.items())
|
||||
|
||||
@staticmethod
|
||||
def set_filename(ini_file):
|
||||
"""
|
||||
Sets the complete path to an Ini file to be used by Settings objects.
|
||||
|
||||
Does not affect existing Settings objects.
|
||||
"""
|
||||
Settings.__file_path__ = ini_file
|
||||
|
||||
@staticmethod
|
||||
def set_up_default_values():
|
||||
"""
|
||||
This static method is called on start up. It is used to perform any operation on the __default_settings__ dict.
|
||||
"""
|
||||
# Make sure the string is translated (when building the dict the string is not translated because the translate
|
||||
# function was not set up as this stage).
|
||||
Settings.__default_settings__[u'advanced/default service name'] = UiStrings().DefaultServiceName
|
||||
|
||||
def __init__(self, *args):
|
||||
"""
|
||||
Constructor which checks if this should be a native settings object, or an INI file.
|
||||
"""
|
||||
if not args and Settings.__file_path__ and Settings.defaultFormat() == Settings.IniFormat:
|
||||
QtCore.QSettings.__init__(self, Settings.__file_path__, Settings.IniFormat)
|
||||
else:
|
||||
QtCore.QSettings.__init__(self, *args)
|
||||
|
||||
def remove_obsolete_settings(self):
|
||||
"""
|
||||
This method is only called to clean up the config. It removes old settings and it renames settings. See
|
||||
``__obsolete_settings__`` for more details.
|
||||
"""
|
||||
for old_key, new_key, rules in Settings.__obsolete_settings__:
|
||||
# Once removed we don't have to do this again.
|
||||
if self.contains(old_key):
|
||||
if new_key:
|
||||
# Get the value of the old_key.
|
||||
old_value = super(Settings, self).value(old_key)
|
||||
# When we want to convert the value, we have to figure out the default value (because we cannot get
|
||||
# the default value from the central settings dict.
|
||||
if rules:
|
||||
default_value = rules[0][1]
|
||||
old_value = self._convert_value(old_value, default_value)
|
||||
# Iterate over our rules and check what the old_value should be "converted" to.
|
||||
for new, old in rules:
|
||||
# If the value matches with the condition (rule), then use the provided value. This is used to
|
||||
# convert values. E. g. an old value 1 results in True, and 0 in False.
|
||||
if old == old_value:
|
||||
old_value = new
|
||||
break
|
||||
self.setValue(new_key, old_value)
|
||||
self.remove(old_key)
|
||||
|
||||
def value(self, key):
|
||||
"""
|
||||
Returns the value for the given ``key``. The returned ``value`` is of the same type as the default value in the
|
||||
*Settings.__default_settings__* dict.
|
||||
|
||||
``key``
|
||||
The key to return the value from.
|
||||
"""
|
||||
# if group() is not empty the group has not been specified together with the key.
|
||||
if self.group():
|
||||
default_value = Settings.__default_settings__[self.group() + u'/' + key]
|
||||
else:
|
||||
default_value = Settings.__default_settings__[key]
|
||||
setting = super(Settings, self).value(key, default_value)
|
||||
return self._convert_value(setting, default_value)
|
||||
|
||||
def _convert_value(self, setting, default_value):
|
||||
"""
|
||||
This converts the given ``setting`` to the type of the given ``default_value``.
|
||||
|
||||
``setting``
|
||||
The setting to convert. This could be ``true`` for example.Settings()
|
||||
|
||||
``default_value``
|
||||
Indication the type the setting should be converted to. For example ``True`` (type is boolean), meaning that
|
||||
we convert the string ``true`` to a python boolean.
|
||||
|
||||
**Note**, this method only converts a few types and might need to be extended if a certain type is missing!
|
||||
"""
|
||||
# On OS X (and probably on other platforms too) empty value from QSettings is represented as type
|
||||
# PyQt4.QtCore.QPyNullVariant. This type has to be converted to proper 'None' Python type.
|
||||
if isinstance(setting, QtCore.QPyNullVariant) and setting.isNull():
|
||||
setting = None
|
||||
# Handle 'None' type (empty value) properly.
|
||||
if setting is None:
|
||||
# An empty string saved to the settings results in a None type being returned.
|
||||
# Convert it to empty unicode string.
|
||||
if isinstance(default_value, unicode):
|
||||
return u''
|
||||
# An empty list saved to the settings results in a None type being returned.
|
||||
else:
|
||||
return []
|
||||
# Convert the setting to the correct type.
|
||||
if isinstance(default_value, bool):
|
||||
if isinstance(setting, bool):
|
||||
return setting
|
||||
# Sometimes setting is string instead of a boolean.
|
||||
return setting == u'true'
|
||||
if isinstance(default_value, int):
|
||||
return int(setting)
|
||||
return setting
|
@ -27,121 +27,27 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
Provide handling for persisting OpenLP settings. OpenLP uses QSettings to
|
||||
manage settings persistence. QSettings provides a single API for saving and
|
||||
retrieving settings from the application but writes to disk in an OS dependant
|
||||
Provide handling for persisting OpenLP settings. OpenLP uses QSettings to manage settings persistence. QSettings
|
||||
provides a single API for saving and retrieving settings from the application but writes to disk in an OS dependant
|
||||
format.
|
||||
"""
|
||||
import os
|
||||
|
||||
from PyQt4 import QtCore
|
||||
|
||||
from openlp.core.lib import Settings
|
||||
from openlp.core.utils import AppLocation
|
||||
|
||||
|
||||
class SettingsManager(object):
|
||||
"""
|
||||
Class to provide helper functions for the loading and saving of application
|
||||
settings.
|
||||
Class to provide helper functions for the loading and saving of application settings.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def get_last_dir(section, num=None):
|
||||
"""
|
||||
Read the last directory used for plugin.
|
||||
|
||||
``section``
|
||||
The section of code calling the method. This is used in the
|
||||
settings key.
|
||||
|
||||
``num``
|
||||
Defaults to *None*. A further qualifier.
|
||||
"""
|
||||
if num:
|
||||
name = u'last directory %d' % num
|
||||
else:
|
||||
name = u'last directory'
|
||||
return Settings().value(section + u'/' + name, u'')
|
||||
|
||||
@staticmethod
|
||||
def set_last_dir(section, directory, num=None):
|
||||
"""
|
||||
Save the last directory used for plugin.
|
||||
|
||||
``section``
|
||||
The section of code calling the method. This is used in the
|
||||
settings key.
|
||||
|
||||
``directory``
|
||||
The directory being stored in the settings.
|
||||
|
||||
``num``
|
||||
Defaults to *None*. A further qualifier.
|
||||
"""
|
||||
if num:
|
||||
name = u'last directory %d' % num
|
||||
else:
|
||||
name = u'last directory'
|
||||
Settings().setValue(section + u'/' + name, directory)
|
||||
|
||||
@staticmethod
|
||||
def set_list(section, name, list):
|
||||
"""
|
||||
Save a list to application settings.
|
||||
|
||||
``section``
|
||||
The section of the settings to store this list.
|
||||
|
||||
``name``
|
||||
The name of the list to save.
|
||||
|
||||
``list``
|
||||
The list of values to save.
|
||||
"""
|
||||
settings = Settings()
|
||||
settings.beginGroup(section)
|
||||
old_count = settings.value(u'%s count' % name, 0)
|
||||
new_count = len(list)
|
||||
settings.setValue(u'%s count' % name, new_count)
|
||||
for counter in range(new_count):
|
||||
settings.setValue(u'%s %d' % (name, counter), list[counter - 1])
|
||||
if old_count > new_count:
|
||||
# Tidy up any old list items
|
||||
for counter in range(new_count, old_count):
|
||||
settings.remove(u'%s %d' % (name, counter))
|
||||
settings.endGroup()
|
||||
|
||||
@staticmethod
|
||||
def load_list(section, name):
|
||||
"""
|
||||
Load a list from the config file.
|
||||
|
||||
``section``
|
||||
The section of the settings to load the list from.
|
||||
|
||||
``name``
|
||||
The name of the list.
|
||||
"""
|
||||
settings = Settings()
|
||||
settings.beginGroup(section)
|
||||
list_count = settings.value(u'%s count' % name, 0)
|
||||
list = []
|
||||
if list_count:
|
||||
for counter in range(list_count):
|
||||
item = settings.value(u'%s %d' % (name, counter), u'')
|
||||
if item:
|
||||
list.append(item)
|
||||
settings.endGroup()
|
||||
return list
|
||||
|
||||
@staticmethod
|
||||
def get_files(section=None, extension=None):
|
||||
"""
|
||||
Get a list of files from the data files path.
|
||||
|
||||
``section``
|
||||
Defaults to *None*. The section of code getting the files - used
|
||||
to load from a section's data subdirectory.
|
||||
Defaults to *None*. The section of code getting the files - used to load from a section's data subdirectory.
|
||||
|
||||
``extension``
|
||||
Defaults to *None*. The extension to search for.
|
||||
@ -154,8 +60,7 @@ class SettingsManager(object):
|
||||
except OSError:
|
||||
return []
|
||||
if extension:
|
||||
return [filename for filename in files
|
||||
if extension == os.path.splitext(filename)[1]]
|
||||
return [filename for filename in files if extension == os.path.splitext(filename)[1]]
|
||||
else:
|
||||
# no filtering required
|
||||
return files
|
||||
|
@ -26,9 +26,16 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.lib.settingstab` module contains the base SettingsTab class which plugins use for adding their
|
||||
own tab to the settings dialog.
|
||||
"""
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
|
||||
from openlp.core.lib import Registry
|
||||
|
||||
class SettingsTab(QtGui.QWidget):
|
||||
"""
|
||||
SettingsTab is a helper widget for plugins to define Tabs for the settings
|
||||
@ -131,3 +138,54 @@ class SettingsTab(QtGui.QWidget):
|
||||
Tab has just been made visible to the user
|
||||
"""
|
||||
pass
|
||||
|
||||
def _get_service_manager(self):
|
||||
"""
|
||||
Adds the service manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_service_manager'):
|
||||
self._service_manager = Registry().get(u'service_manager')
|
||||
return self._service_manager
|
||||
|
||||
service_manager = property(_get_service_manager)
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
||||
def _get_renderer(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_renderer'):
|
||||
self._renderer = Registry().get(u'renderer')
|
||||
return self._renderer
|
||||
|
||||
renderer = property(_get_renderer)
|
||||
|
||||
def _get_theme_manager(self):
|
||||
"""
|
||||
Adds the theme manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_theme_manager'):
|
||||
self._theme_manager = Registry().get(u'theme_manager')
|
||||
return self._theme_manager
|
||||
|
||||
theme_manager = property(_get_theme_manager)
|
||||
|
||||
def _get_media_controller(self):
|
||||
"""
|
||||
Adds the media controller to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_media_controller'):
|
||||
self._media_controller = Registry().get(u'media_controller')
|
||||
return self._media_controller
|
||||
|
||||
media_controller = property(_get_media_controller)
|
||||
|
||||
|
@ -26,6 +26,10 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.lib.spelltextedit` module contains a classes to add spell checking to an edit widget.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
@ -47,11 +51,15 @@ from openlp.core.lib.ui import create_action
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SpellTextEdit(QtGui.QPlainTextEdit):
|
||||
"""
|
||||
Spell checking widget based on QPlanTextEdit.
|
||||
"""
|
||||
def __init__(self, parent=None, formattingTagsAllowed=True):
|
||||
"""
|
||||
Constructor.
|
||||
"""
|
||||
global ENCHANT_AVAILABLE
|
||||
QtGui.QPlainTextEdit.__init__(self, parent)
|
||||
self.formattingTagsAllowed = formattingTagsAllowed
|
||||
@ -171,6 +179,9 @@ class Highlighter(QtGui.QSyntaxHighlighter):
|
||||
WORDS = u'(?iu)[\w\']+'
|
||||
|
||||
def __init__(self, *args):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QSyntaxHighlighter.__init__(self, *args)
|
||||
self.spellingDictionary = None
|
||||
|
||||
@ -197,5 +208,8 @@ class SpellAction(QtGui.QAction):
|
||||
correct = QtCore.pyqtSignal(unicode)
|
||||
|
||||
def __init__(self, *args):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QAction.__init__(self, *args)
|
||||
self.triggered.connect(lambda x: self.correct.emit(self.text()))
|
||||
|
@ -36,7 +36,7 @@ import logging
|
||||
from xml.dom.minidom import Document
|
||||
from lxml import etree, objectify
|
||||
|
||||
from openlp.core.lib import str_to_bool
|
||||
from openlp.core.lib import str_to_bool, ScreenList
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -86,6 +86,7 @@ BLANK_THEME_XML = \
|
||||
</theme>
|
||||
'''
|
||||
|
||||
|
||||
class ThemeLevel(object):
|
||||
"""
|
||||
Provides an enumeration for the level a theme applies to
|
||||
@ -213,6 +214,7 @@ class ThemeXML(object):
|
||||
"""
|
||||
FIRST_CAMEL_REGEX = re.compile(u'(.)([A-Z][a-z]+)')
|
||||
SECOND_CAMEL_REGEX = re.compile(u'([a-z0-9])([A-Z])')
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialise the theme object.
|
||||
@ -380,8 +382,7 @@ class ThemeXML(object):
|
||||
# Create italics name element
|
||||
self.child_element(background, u'italics', unicode(italics))
|
||||
# Create indentation name element
|
||||
self.child_element(
|
||||
background, u'line_adjustment', unicode(line_adjustment))
|
||||
self.child_element(background, u'line_adjustment', unicode(line_adjustment))
|
||||
# Create Location element
|
||||
element = self.theme_xml.createElement(u'location')
|
||||
element.setAttribute(u'override', unicode(override))
|
||||
@ -451,7 +452,6 @@ class ThemeXML(object):
|
||||
Set the header and footer size into the current primary screen.
|
||||
10 px on each side is removed to allow for a border.
|
||||
"""
|
||||
from openlp.core.ui import ScreenList
|
||||
current_screen = ScreenList().current
|
||||
self.font_main_y = 0
|
||||
self.font_main_width = current_screen[u'size'].width() - 20
|
||||
@ -610,13 +610,15 @@ class ThemeXML(object):
|
||||
self.add_background_gradient(
|
||||
self.background_start_color,
|
||||
self.background_end_color,
|
||||
self.background_direction)
|
||||
self.background_direction
|
||||
)
|
||||
elif self.background_type == BackgroundType.to_string(BackgroundType.Image):
|
||||
filename = os.path.split(self.background_filename)[1]
|
||||
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_size,
|
||||
self.font_main_override, u'main',
|
||||
@ -632,8 +634,10 @@ class ThemeXML(object):
|
||||
self.font_main_outline_size,
|
||||
self.font_main_shadow,
|
||||
self.font_main_shadow_color,
|
||||
self.font_main_shadow_size)
|
||||
self.add_font(self.font_footer_name,
|
||||
self.font_main_shadow_size
|
||||
)
|
||||
self.add_font(
|
||||
self.font_footer_name,
|
||||
self.font_footer_color,
|
||||
self.font_footer_size,
|
||||
self.font_footer_override, u'footer',
|
||||
@ -649,7 +653,10 @@ class ThemeXML(object):
|
||||
self.font_footer_outline_size,
|
||||
self.font_footer_shadow,
|
||||
self.font_footer_shadow_color,
|
||||
self.font_footer_shadow_size)
|
||||
self.add_display(self.display_horizontal_align,
|
||||
self.font_footer_shadow_size
|
||||
)
|
||||
self.add_display(
|
||||
self.display_horizontal_align,
|
||||
self.display_vertical_align,
|
||||
self.display_slide_transition)
|
||||
self.display_slide_transition
|
||||
)
|
||||
|
@ -37,6 +37,7 @@ from openlp.core.lib.ui import create_widget_action
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpenLPToolbar(QtGui.QToolBar):
|
||||
"""
|
||||
Lots of toolbars around the place, so it makes sense to have a common way
|
||||
@ -85,4 +86,3 @@ class OpenLPToolbar(QtGui.QToolBar):
|
||||
self.actions[handle].setVisible(visible)
|
||||
else:
|
||||
log.warn(u'No handle "%s" in actions list.', unicode(handle))
|
||||
|
||||
|
@ -33,116 +33,12 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import build_icon, Receiver, translate
|
||||
from openlp.core.lib import Receiver, UiStrings, build_icon, translate
|
||||
from openlp.core.utils.actions import ActionList
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class UiStrings(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.
|
||||
Should some/more/less of these have an & attached?
|
||||
"""
|
||||
self.About = translate('OpenLP.Ui', 'About')
|
||||
self.Add = translate('OpenLP.Ui', '&Add')
|
||||
self.Advanced = translate('OpenLP.Ui', 'Advanced')
|
||||
self.AllFiles = translate('OpenLP.Ui', 'All Files')
|
||||
self.Automatic = translate('OpenLP.Ui', 'Automatic')
|
||||
self.BackgroundColor = translate('OpenLP.Ui', 'Background Color')
|
||||
self.Bottom = translate('OpenLP.Ui', 'Bottom')
|
||||
self.Browse = translate('OpenLP.Ui', 'Browse...')
|
||||
self.Cancel = translate('OpenLP.Ui', 'Cancel')
|
||||
self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
|
||||
self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
|
||||
self.ConfirmDelete = translate('OpenLP.Ui', 'Confirm Delete')
|
||||
self.Continuous = translate('OpenLP.Ui', 'Continuous')
|
||||
self.Default = translate('OpenLP.Ui', 'Default')
|
||||
self.DefaultColor = translate('OpenLP.Ui', 'Default Color:')
|
||||
self.Delete = translate('OpenLP.Ui', '&Delete')
|
||||
self.DisplayStyle = translate('OpenLP.Ui', 'Display style:')
|
||||
self.Duplicate = translate('OpenLP.Ui', 'Duplicate Error')
|
||||
self.Edit = translate('OpenLP.Ui', '&Edit')
|
||||
self.EmptyField = translate('OpenLP.Ui', 'Empty Field')
|
||||
self.Error = translate('OpenLP.Ui', 'Error')
|
||||
self.Export = translate('OpenLP.Ui', 'Export')
|
||||
self.File = translate('OpenLP.Ui', 'File')
|
||||
self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit')
|
||||
self.Help = translate('OpenLP.Ui', 'Help')
|
||||
self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
|
||||
self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected', 'Singular')
|
||||
self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
|
||||
self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
|
||||
self.Image = translate('OpenLP.Ui', 'Image')
|
||||
self.Import = translate('OpenLP.Ui', 'Import')
|
||||
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
||||
self.Live = translate('OpenLP.Ui', 'Live')
|
||||
self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
|
||||
self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
|
||||
self.Load = translate('OpenLP.Ui', 'Load')
|
||||
self.Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes')
|
||||
self.Middle = translate('OpenLP.Ui', 'Middle')
|
||||
self.New = translate('OpenLP.Ui', 'New')
|
||||
self.NewService = translate('OpenLP.Ui', 'New Service')
|
||||
self.NewTheme = translate('OpenLP.Ui', 'New Theme')
|
||||
self.NextTrack = translate('OpenLP.Ui', 'Next Track')
|
||||
self.NFdSs = translate('OpenLP.Ui', 'No Folder Selected', 'Singular')
|
||||
self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
|
||||
self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
|
||||
self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
|
||||
self.NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural')
|
||||
self.OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x')
|
||||
self.OLPV2 = translate('OpenLP.Ui', 'OpenLP 2')
|
||||
self.OLPV2x = translate('OpenLP.Ui', 'OpenLP 2.1')
|
||||
self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. Do you wish to continue?')
|
||||
self.OpenService = translate('OpenLP.Ui', 'Open service.')
|
||||
self.PlaySlidesInLoop = translate('OpenLP.Ui','Play Slides in Loop')
|
||||
self.PlaySlidesToEnd = translate('OpenLP.Ui','Play Slides to End')
|
||||
self.Preview = translate('OpenLP.Ui', 'Preview')
|
||||
self.PrintService = translate('OpenLP.Ui', 'Print Service')
|
||||
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
|
||||
self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
|
||||
self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
|
||||
self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
|
||||
self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
|
||||
self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
|
||||
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 to delete.')
|
||||
self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.')
|
||||
self.Settings = translate('OpenLP.Ui', 'Settings')
|
||||
self.SaveService = translate('OpenLP.Ui', 'Save Service')
|
||||
self.Service = translate('OpenLP.Ui', 'Service')
|
||||
self.Split = translate('OpenLP.Ui', 'Optional &Split')
|
||||
self.SplitToolTip = translate('OpenLP.Ui',
|
||||
'Split a slide into two only if it does not fit on the screen as one slide.')
|
||||
self.StartTimeCode = translate('OpenLP.Ui', 'Start %s')
|
||||
self.StopPlaySlidesInLoop = translate('OpenLP.Ui', 'Stop Play Slides in Loop')
|
||||
self.StopPlaySlidesToEnd = translate('OpenLP.Ui', 'Stop Play Slides to End')
|
||||
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
|
||||
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
|
||||
self.Tools = translate('OpenLP.Ui', 'Tools')
|
||||
self.Top = translate('OpenLP.Ui', 'Top')
|
||||
self.UnsupportedFile = translate('OpenLP.Ui', 'Unsupported File')
|
||||
self.VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide')
|
||||
self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line')
|
||||
self.Version = translate('OpenLP.Ui', 'Version')
|
||||
self.View = translate('OpenLP.Ui', 'View')
|
||||
self.ViewMode = translate('OpenLP.Ui', 'View Mode')
|
||||
|
||||
|
||||
def add_welcome_page(parent, image):
|
||||
"""
|
||||
@ -171,7 +67,7 @@ def add_welcome_page(parent, image):
|
||||
parent.addPage(parent.welcomePage)
|
||||
|
||||
|
||||
def create_button_box(dialog, name, standard_buttons, custom_buttons=[]):
|
||||
def create_button_box(dialog, name, standard_buttons, custom_buttons=None):
|
||||
"""
|
||||
Creates a QDialogButtonBox with the given buttons. The ``accepted()`` and
|
||||
``rejected()`` signals of the button box are connected with the dialogs
|
||||
@ -192,6 +88,8 @@ def create_button_box(dialog, name, standard_buttons, custom_buttons=[]):
|
||||
QtGui.QAbstractButton it is added with QDialogButtonBox.ActionRole.
|
||||
Otherwhise the item has to be a tuple of a button and a ButtonRole.
|
||||
"""
|
||||
if custom_buttons is None:
|
||||
custom_buttons = []
|
||||
buttons = QtGui.QDialogButtonBox.NoButton
|
||||
if u'ok' in standard_buttons:
|
||||
buttons |= QtGui.QDialogButtonBox.Ok
|
||||
|
146
openlp/core/lib/uistrings.py
Normal file
146
openlp/core/lib/uistrings.py
Normal file
@ -0,0 +1,146 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2013 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
|
||||
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
|
||||
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
|
||||
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
|
||||
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
|
||||
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
|
||||
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`uistrings` module provides standard strings for OpenLP.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import translate
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class UiStrings(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.
|
||||
Should some/more/less of these have an & attached?
|
||||
"""
|
||||
self.About = translate('OpenLP.Ui', 'About')
|
||||
self.Add = translate('OpenLP.Ui', '&Add')
|
||||
self.Advanced = translate('OpenLP.Ui', 'Advanced')
|
||||
self.AllFiles = translate('OpenLP.Ui', 'All Files')
|
||||
self.Automatic = translate('OpenLP.Ui', 'Automatic')
|
||||
self.BackgroundColor = translate('OpenLP.Ui', 'Background Color')
|
||||
self.Bottom = translate('OpenLP.Ui', 'Bottom')
|
||||
self.Browse = translate('OpenLP.Ui', 'Browse...')
|
||||
self.Cancel = translate('OpenLP.Ui', 'Cancel')
|
||||
self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
|
||||
self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
|
||||
self.ConfirmDelete = translate('OpenLP.Ui', 'Confirm Delete')
|
||||
self.Continuous = translate('OpenLP.Ui', 'Continuous')
|
||||
self.Default = translate('OpenLP.Ui', 'Default')
|
||||
self.DefaultColor = translate('OpenLP.Ui', 'Default Color:')
|
||||
self.DefaultServiceName = translate('OpenLP.Ui', '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.Delete = translate('OpenLP.Ui', '&Delete')
|
||||
self.DisplayStyle = translate('OpenLP.Ui', 'Display style:')
|
||||
self.Duplicate = translate('OpenLP.Ui', 'Duplicate Error')
|
||||
self.Edit = translate('OpenLP.Ui', '&Edit')
|
||||
self.EmptyField = translate('OpenLP.Ui', 'Empty Field')
|
||||
self.Error = translate('OpenLP.Ui', 'Error')
|
||||
self.Export = translate('OpenLP.Ui', 'Export')
|
||||
self.File = translate('OpenLP.Ui', 'File')
|
||||
self.FontSizePtUnit = translate('OpenLP.Ui', 'pt', 'Abbreviated font pointsize unit')
|
||||
self.Help = translate('OpenLP.Ui', 'Help')
|
||||
self.Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
|
||||
self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected', 'Singular')
|
||||
self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
|
||||
self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
|
||||
self.Image = translate('OpenLP.Ui', 'Image')
|
||||
self.Import = translate('OpenLP.Ui', 'Import')
|
||||
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
|
||||
self.Live = translate('OpenLP.Ui', 'Live')
|
||||
self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
|
||||
self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
|
||||
self.Load = translate('OpenLP.Ui', 'Load')
|
||||
self.Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes')
|
||||
self.Middle = translate('OpenLP.Ui', 'Middle')
|
||||
self.New = translate('OpenLP.Ui', 'New')
|
||||
self.NewService = translate('OpenLP.Ui', 'New Service')
|
||||
self.NewTheme = translate('OpenLP.Ui', 'New Theme')
|
||||
self.NextTrack = translate('OpenLP.Ui', 'Next Track')
|
||||
self.NFdSs = translate('OpenLP.Ui', 'No Folder Selected', 'Singular')
|
||||
self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
|
||||
self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
|
||||
self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
|
||||
self.NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural')
|
||||
self.OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x')
|
||||
self.OLPV2 = translate('OpenLP.Ui', 'OpenLP 2')
|
||||
self.OLPV2x = translate('OpenLP.Ui', 'OpenLP 2.1')
|
||||
self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. Do you wish to continue?')
|
||||
self.OpenService = translate('OpenLP.Ui', 'Open service.')
|
||||
self.PlaySlidesInLoop = translate('OpenLP.Ui', 'Play Slides in Loop')
|
||||
self.PlaySlidesToEnd = translate('OpenLP.Ui', 'Play Slides to End')
|
||||
self.Preview = translate('OpenLP.Ui', 'Preview')
|
||||
self.PrintService = translate('OpenLP.Ui', 'Print Service')
|
||||
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
|
||||
self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
|
||||
self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
|
||||
self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
|
||||
self.Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
|
||||
self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
|
||||
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 to delete.')
|
||||
self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.')
|
||||
self.Settings = translate('OpenLP.Ui', 'Settings')
|
||||
self.SaveService = translate('OpenLP.Ui', 'Save Service')
|
||||
self.Service = translate('OpenLP.Ui', 'Service')
|
||||
self.Split = translate('OpenLP.Ui', 'Optional &Split')
|
||||
self.SplitToolTip = translate('OpenLP.Ui',
|
||||
'Split a slide into two only if it does not fit on the screen as one slide.')
|
||||
self.StartTimeCode = translate('OpenLP.Ui', 'Start %s')
|
||||
self.StopPlaySlidesInLoop = translate('OpenLP.Ui', 'Stop Play Slides in Loop')
|
||||
self.StopPlaySlidesToEnd = translate('OpenLP.Ui', 'Stop Play Slides to End')
|
||||
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
|
||||
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
|
||||
self.Tools = translate('OpenLP.Ui', 'Tools')
|
||||
self.Top = translate('OpenLP.Ui', 'Top')
|
||||
self.UnsupportedFile = translate('OpenLP.Ui', 'Unsupported File')
|
||||
self.VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide')
|
||||
self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line')
|
||||
self.Version = translate('OpenLP.Ui', 'Version')
|
||||
self.View = translate('OpenLP.Ui', 'View')
|
||||
self.ViewMode = translate('OpenLP.Ui', 'View Mode')
|
@ -26,5 +26,11 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.theme` module contains all the themeing functions used by
|
||||
OpenLP when displaying a song or a scripture.
|
||||
"""
|
||||
|
||||
from openlp.core.theme.theme import Theme
|
||||
|
||||
__all__ = ['Theme']
|
||||
|
@ -37,11 +37,21 @@ from xml.etree.ElementTree import ElementTree, XML
|
||||
from PyQt4 import QtGui
|
||||
|
||||
DELPHI_COLORS = {
|
||||
u'clAqua': 0x00FFFF, u'clBlack': 0x000000, u'clBlue': 0x0000FF,
|
||||
u'clFuchsia': 0xFF00FF, u'clGray': 0x808080, u'clGreen': 0x008000,
|
||||
u'clLime': 0x00FF00, u'clMaroon': 0x800000, u'clNavy': 0x000080,
|
||||
u'clOlive': 0x808000, u'clPurple': 0x800080, u'clRed': 0xFF0000,
|
||||
u'clSilver': 0xC0C0C0, u'clTeal': 0x008080, u'clWhite': 0xFFFFFF,
|
||||
u'clAqua': 0x00FFFF,
|
||||
u'clBlack': 0x000000,
|
||||
u'clBlue': 0x0000FF,
|
||||
u'clFuchsia': 0xFF00FF,
|
||||
u'clGray': 0x808080,
|
||||
u'clGreen': 0x008000,
|
||||
u'clLime': 0x00FF00,
|
||||
u'clMaroon': 0x800000,
|
||||
u'clNavy': 0x000080,
|
||||
u'clOlive': 0x808000,
|
||||
u'clPurple': 0x800080,
|
||||
u'clRed': 0xFF0000,
|
||||
u'clSilver': 0xC0C0C0,
|
||||
u'clTeal': 0x008080,
|
||||
u'clWhite': 0xFFFFFF,
|
||||
u'clYellow': 0xFFFF00
|
||||
}
|
||||
|
||||
@ -66,6 +76,7 @@ BLANK_STYLE_XML = \
|
||||
</Theme>
|
||||
'''
|
||||
|
||||
|
||||
class Theme(object):
|
||||
"""
|
||||
Provide a class wrapper storing data from an XML theme
|
||||
@ -164,6 +175,7 @@ class Theme(object):
|
||||
* ``0`` - normal
|
||||
* ``1`` - lyrics
|
||||
"""
|
||||
|
||||
def __init__(self, xml):
|
||||
"""
|
||||
Initialise a theme with data from xml
|
||||
@ -205,10 +217,12 @@ class Theme(object):
|
||||
val = element_text
|
||||
# strings need special handling to sort the colours out
|
||||
if isinstance(element_text, basestring):
|
||||
if element_text[0] == u'$': # might be a hex number
|
||||
if element_text[0] == u'$':
|
||||
# might be a hex number
|
||||
try:
|
||||
val = int(element_text[1:], 16)
|
||||
except ValueError: # nope
|
||||
except ValueError:
|
||||
# nope
|
||||
pass
|
||||
elif element_text in DELPHI_COLORS:
|
||||
val = DELPHI_COLORS[element_text]
|
||||
|
@ -29,35 +29,30 @@
|
||||
"""
|
||||
The :mod:`ui` module provides the core user interface for OpenLP
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
|
||||
class HideMode(object):
|
||||
"""
|
||||
This is an enumeration class which specifies the different modes of hiding
|
||||
the display.
|
||||
This is an enumeration class which specifies the different modes of hiding the display.
|
||||
|
||||
``Blank``
|
||||
This mode is used to hide all output, specifically by covering the
|
||||
display with a black screen.
|
||||
This mode is used to hide all output, specifically by covering the display with a black screen.
|
||||
|
||||
``Theme``
|
||||
This mode is used to hide all output, but covers the display with the
|
||||
current theme background, as opposed to black.
|
||||
This mode is used to hide all output, but covers the display with the current theme background, as opposed to
|
||||
black.
|
||||
|
||||
``Desktop``
|
||||
This mode hides all output by minimising the display, leaving the user's
|
||||
desktop showing.
|
||||
This mode hides all output by minimising the display, leaving the user's desktop showing.
|
||||
"""
|
||||
Blank = 1
|
||||
Theme = 2
|
||||
Screen = 3
|
||||
|
||||
|
||||
class AlertLocation(object):
|
||||
"""
|
||||
This is an enumeration class which controls where Alerts are placed on the
|
||||
screen.
|
||||
This is an enumeration class which controls where Alerts are placed on the screen.
|
||||
|
||||
``Top``
|
||||
Place the text at the top of the screen.
|
||||
@ -72,10 +67,10 @@ class AlertLocation(object):
|
||||
Middle = 1
|
||||
Bottom = 2
|
||||
|
||||
|
||||
class DisplayControllerType(object):
|
||||
"""
|
||||
This is an enumeration class which says where a display controller
|
||||
originated from.
|
||||
This is an enumeration class which says where a display controller originated from.
|
||||
"""
|
||||
Live = 0
|
||||
Preview = 1
|
||||
@ -88,7 +83,6 @@ from themelayoutform import ThemeLayoutForm
|
||||
from themeform import ThemeForm
|
||||
from filerenameform import FileRenameForm
|
||||
from starttimeform import StartTimeForm
|
||||
from screen import ScreenList
|
||||
from maindisplay import MainDisplay, Display
|
||||
from servicenoteform import ServiceNoteForm
|
||||
from serviceitemeditform import ServiceItemEditForm
|
||||
@ -106,6 +100,8 @@ from mediadockmanager import MediaDockManager
|
||||
from servicemanager import ServiceManager
|
||||
from thememanager import ThemeManager
|
||||
|
||||
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay',
|
||||
'SlideController', 'ServiceManager', 'ThemeManager', 'MediaDockManager',
|
||||
'ServiceItemEditForm', 'FirstTimeForm']
|
||||
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager',
|
||||
'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm', 'FirstTimeForm', 'FirstTimeLanguageForm', 'ThemeForm',
|
||||
'ThemeLayoutForm', 'FileRenameForm', 'StartTimeForm', 'MainDisplay', 'Display', 'ServiceNoteForm',
|
||||
'SlideController', 'DisplayController', 'GeneralTab', 'ThemesTab', 'AdvancedTab', 'PluginForm',
|
||||
'FormattingTagForm', 'ShortcutListForm']
|
||||
|
@ -29,11 +29,19 @@
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import build_icon, translate
|
||||
from openlp.core.lib.ui import UiStrings, create_button, create_button_box
|
||||
from openlp.core.lib import UiStrings, build_icon, translate
|
||||
from openlp.core.lib.ui import create_button, create_button_box
|
||||
|
||||
|
||||
class Ui_AboutDialog(object):
|
||||
"""
|
||||
The actual GUI widgets for the About form.
|
||||
"""
|
||||
|
||||
def setupUi(self, aboutDialog):
|
||||
"""
|
||||
Set up the UI for the dialog.
|
||||
"""
|
||||
aboutDialog.setObjectName(u'aboutDialog')
|
||||
aboutDialog.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png'))
|
||||
self.aboutDialogLayout = QtGui.QVBoxLayout(aboutDialog)
|
||||
@ -73,12 +81,15 @@ class Ui_AboutDialog(object):
|
||||
self.aboutNotebook.addTab(self.licenseTab, u'')
|
||||
self.aboutDialogLayout.addWidget(self.aboutNotebook)
|
||||
self.volunteerButton = create_button(None, u'volunteerButton', icon=u':/system/system_volunteer.png')
|
||||
self.buttonBox = create_button_box(aboutDialog, u'buttonBox', [u'close'], [self.volunteerButton])
|
||||
self.aboutDialogLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(aboutDialog, u'button_box', [u'close'], [self.volunteerButton])
|
||||
self.aboutDialogLayout.addWidget(self.button_box)
|
||||
self.retranslateUi(aboutDialog)
|
||||
self.aboutNotebook.setCurrentIndex(0)
|
||||
|
||||
def retranslateUi(self, aboutDialog):
|
||||
"""
|
||||
Dynamically translate the UI.
|
||||
"""
|
||||
aboutDialog.setWindowTitle(u'%s OpenLP' % UiStrings().About)
|
||||
self.aboutTextEdit.setPlainText(translate('OpenLP.AboutForm',
|
||||
'OpenLP <version><revision> - Open Source Lyrics '
|
||||
@ -259,7 +270,7 @@ class Ui_AboutDialog(object):
|
||||
u'\n '.join(documentors)))
|
||||
self.aboutNotebook.setTabText(self.aboutNotebook.indexOf(self.creditsTab),
|
||||
translate('OpenLP.AboutForm', 'Credits'))
|
||||
copyright = translate('OpenLP.AboutForm',
|
||||
copyright_note = translate('OpenLP.AboutForm',
|
||||
'Copyright \xa9 2004-2013 %s\n'
|
||||
'Portions copyright \xa9 2004-2013 %s') % (u'Raoul Snyman',
|
||||
u'Tim Bentley, Gerald Britton, Jonathan Corwin, Samuel Findlay, '
|
||||
@ -651,7 +662,7 @@ class Ui_AboutDialog(object):
|
||||
'linking proprietary applications with the library. If this is '
|
||||
'what you want to do, use the GNU Lesser General Public License '
|
||||
'instead of this License.')
|
||||
self.licenseTextEdit.setPlainText(u'%s\n\n%s\n\n%s\n\n\n%s' % (copyright, licence, disclaimer, gpltext))
|
||||
self.licenseTextEdit.setPlainText(u'%s\n\n%s\n\n%s\n\n\n%s' % (copyright_note, licence, disclaimer, gpltext))
|
||||
self.aboutNotebook.setTabText(self.aboutNotebook.indexOf(self.licenseTab),
|
||||
translate('OpenLP.AboutForm', 'License'))
|
||||
self.volunteerButton.setText(translate('OpenLP.AboutForm', 'Volunteer'))
|
||||
|
@ -26,6 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The About dialog.
|
||||
"""
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -33,6 +36,7 @@ from aboutdialog import Ui_AboutDialog
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.utils import get_application_version
|
||||
|
||||
|
||||
class AboutForm(QtGui.QDialog, Ui_AboutDialog):
|
||||
"""
|
||||
The About dialog
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,14 +26,24 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The GUI widgets of the exception dialog.
|
||||
"""
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, build_icon
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import create_button, create_button_box
|
||||
|
||||
|
||||
class Ui_ExceptionDialog(object):
|
||||
"""
|
||||
The GUI widgets of the exception dialog.
|
||||
"""
|
||||
def setupUi(self, exceptionDialog):
|
||||
"""
|
||||
Set up the UI.
|
||||
"""
|
||||
exceptionDialog.setObjectName(u'exceptionDialog')
|
||||
self.exceptionLayout = QtGui.QVBoxLayout(exceptionDialog)
|
||||
self.exceptionLayout.setObjectName(u'exceptionLayout')
|
||||
@ -70,15 +80,18 @@ class Ui_ExceptionDialog(object):
|
||||
icon=u':/general/general_save.png', click=self.onSaveReportButtonClicked)
|
||||
self.attachFileButton = create_button(exceptionDialog, u'attachFileButton',
|
||||
icon=u':/general/general_open.png', click=self.onAttachFileButtonClicked)
|
||||
self.buttonBox = create_button_box(exceptionDialog, u'buttonBox',
|
||||
self.button_box = create_button_box(exceptionDialog, u'button_box',
|
||||
[u'close'], [self.sendReportButton, self.saveReportButton, self.attachFileButton])
|
||||
self.exceptionLayout.addWidget(self.buttonBox)
|
||||
self.exceptionLayout.addWidget(self.button_box)
|
||||
|
||||
self.retranslateUi(exceptionDialog)
|
||||
QtCore.QObject.connect(self.descriptionTextEdit,
|
||||
QtCore.SIGNAL(u'textChanged()'), self.onDescriptionUpdated)
|
||||
|
||||
def retranslateUi(self, exceptionDialog):
|
||||
"""
|
||||
Translate the widgets on the fly.
|
||||
"""
|
||||
exceptionDialog.setWindowTitle(translate('OpenLP.ExceptionDialog', 'Error Occurred'))
|
||||
self.descriptionExplanation.setText(translate('OpenLP.ExceptionDialog',
|
||||
'Please enter a description of what you were doing to cause this '
|
||||
|
@ -26,6 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The actual exception dialog form.
|
||||
"""
|
||||
import logging
|
||||
import re
|
||||
import os
|
||||
@ -85,30 +88,39 @@ except AttributeError:
|
||||
WEBKIT_VERSION = u'-'
|
||||
|
||||
|
||||
from openlp.core.lib import translate, SettingsManager
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib import UiStrings, Settings, translate
|
||||
from openlp.core.utils import get_application_version
|
||||
|
||||
from exceptiondialog import Ui_ExceptionDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
"""
|
||||
The exception dialog
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor.
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.settingsSection = u'crashreport'
|
||||
|
||||
def exec_(self):
|
||||
"""
|
||||
Show the dialog.
|
||||
"""
|
||||
self.descriptionTextEdit.setPlainText(u'')
|
||||
self.onDescriptionUpdated()
|
||||
self.fileAttachment = None
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def _createReport(self):
|
||||
"""
|
||||
Create an exception report.
|
||||
"""
|
||||
openlp_version = get_application_version()
|
||||
description = self.descriptionTextEdit.toPlainText()
|
||||
traceback = self.exceptionTextEdit.toPlainText()
|
||||
@ -129,9 +141,9 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
u'pyUNO bridge: %s\n' % UNO_VERSION
|
||||
if platform.system() == u'Linux':
|
||||
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
|
||||
system = system + u'Desktop: KDE SC\n'
|
||||
system += u'Desktop: KDE SC\n'
|
||||
elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'):
|
||||
system = system + u'Desktop: GNOME\n'
|
||||
system += u'Desktop: GNOME\n'
|
||||
return (openlp_version, description, traceback, system, libraries)
|
||||
|
||||
def onSaveReportButtonClicked(self):
|
||||
@ -147,12 +159,12 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
'--- Library Versions ---\n%s\n')
|
||||
filename = QtGui.QFileDialog.getSaveFileName(self,
|
||||
translate('OpenLP.ExceptionForm', 'Save Crash Report'),
|
||||
SettingsManager.get_last_dir(self.settingsSection),
|
||||
Settings().value(self.settingsSection + u'/last directory'),
|
||||
translate('OpenLP.ExceptionForm',
|
||||
'Text files (*.txt *.log *.text)'))
|
||||
if filename:
|
||||
filename = unicode(filename).replace(u'/', os.path.sep)
|
||||
SettingsManager.set_last_dir(self.settingsSection, os.path.dirname(filename))
|
||||
Settings().setValue(self.settingsSection + u'/last directory', os.path.dirname(filename))
|
||||
report_text = report_text % self._createReport()
|
||||
try:
|
||||
report_file = open(filename, u'w')
|
||||
@ -200,6 +212,9 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
QtGui.QDesktopServices.openUrl(mailto_url)
|
||||
|
||||
def onDescriptionUpdated(self):
|
||||
"""
|
||||
Update the minimum number of characters needed in the description.
|
||||
"""
|
||||
count = int(20 - len(self.descriptionTextEdit.toPlainText()))
|
||||
if count < 0:
|
||||
count = 0
|
||||
@ -210,14 +225,19 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
|
||||
translate('OpenLP.ExceptionDialog', 'Description characters to enter : %s') % count)
|
||||
|
||||
def onAttachFileButtonClicked(self):
|
||||
"""
|
||||
Attache files to the bug report e-mail.
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileName(
|
||||
self, translate('ImagePlugin.ExceptionDialog', 'Select Attachment'),
|
||||
SettingsManager.get_last_dir(u'exceptions'), u'%s (*.*) (*)' % UiStrings().AllFiles)
|
||||
Settings().value(self.settingsSection + u'/last directory'), u'%s (*.*) (*)' % UiStrings().AllFiles)
|
||||
log.info(u'New files(s) %s', unicode(files))
|
||||
if files:
|
||||
self.fileAttachment = unicode(files)
|
||||
|
||||
def __buttonState(self, state):
|
||||
"""
|
||||
Toggle the button state.
|
||||
"""
|
||||
self.saveReportButton.setEnabled(state)
|
||||
self.sendReportButton.setEnabled(state)
|
||||
|
||||
|
@ -26,18 +26,27 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets for the rename dialog
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_FileRenameDialog(object):
|
||||
"""
|
||||
The UI widgets for the rename dialog
|
||||
"""
|
||||
def setupUi(self, fileRenameDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
fileRenameDialog.setObjectName(u'fileRenameDialog')
|
||||
fileRenameDialog.resize(300, 10)
|
||||
self.dialogLayout = QtGui.QGridLayout(fileRenameDialog)
|
||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||
self.dialogLayout.setObjectName(u'dialog_layout')
|
||||
self.fileNameLabel = QtGui.QLabel(fileRenameDialog)
|
||||
self.fileNameLabel.setObjectName(u'fileNameLabel')
|
||||
self.dialogLayout.addWidget(self.fileNameLabel, 0, 0)
|
||||
@ -45,10 +54,13 @@ class Ui_FileRenameDialog(object):
|
||||
self.fileNameEdit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+%]+'), self))
|
||||
self.fileNameEdit.setObjectName(u'fileNameEdit')
|
||||
self.dialogLayout.addWidget(self.fileNameEdit, 0, 1)
|
||||
self.buttonBox = create_button_box(fileRenameDialog, u'buttonBox', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.buttonBox, 1, 0, 1, 2)
|
||||
self.button_box = create_button_box(fileRenameDialog, u'button_box', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.button_box, 1, 0, 1, 2)
|
||||
self.retranslateUi(fileRenameDialog)
|
||||
self.setMaximumHeight(self.sizeHint().height())
|
||||
|
||||
def retranslateUi(self, fileRenameDialog):
|
||||
"""
|
||||
Translate the UI on the fly.
|
||||
"""
|
||||
self.fileNameLabel.setText(translate('OpenLP.FileRenameForm', 'New File Name:'))
|
||||
|
@ -26,6 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The file rename dialog.
|
||||
"""
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
@ -33,11 +36,15 @@ from filerenamedialog import Ui_FileRenameDialog
|
||||
|
||||
from openlp.core.lib import translate
|
||||
|
||||
|
||||
class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog):
|
||||
"""
|
||||
The exception dialog
|
||||
The file rename dialog
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
|
||||
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
This module contains the first time wizard.
|
||||
"""
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
@ -39,20 +41,21 @@ from ConfigParser import SafeConfigParser
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, PluginStatus, Receiver, build_icon, check_directory_exists, Settings
|
||||
from openlp.core.utils import get_web_page, AppLocation, get_filesystem_encoding
|
||||
from openlp.core.lib import PluginStatus, Receiver, Settings, Registry, build_icon, check_directory_exists, translate
|
||||
from openlp.core.utils import AppLocation, get_web_page, get_filesystem_encoding
|
||||
from firsttimewizard import Ui_FirstTimeWizard, FirstTimePage
|
||||
|
||||
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):
|
||||
"""
|
||||
Overridden method to run the thread.
|
||||
"""
|
||||
themes = self.parent().config.get(u'themes', u'files')
|
||||
themes = themes.split(u',')
|
||||
config = self.parent().config
|
||||
@ -79,7 +82,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
log.info(u'ThemeWizardForm loaded')
|
||||
|
||||
def __init__(self, screens, parent=None):
|
||||
QtGui.QWizard.__init__(self, parent)
|
||||
"""
|
||||
Create and set up the first time wizard.
|
||||
"""
|
||||
super(FirstTimeForm, self).__init__(parent)
|
||||
self.setupUi(self)
|
||||
self.screens = screens
|
||||
# check to see if we have web access
|
||||
@ -90,7 +96,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
files = self.webAccess.read()
|
||||
self.config.readfp(io.BytesIO(files))
|
||||
self.updateScreenListCombo()
|
||||
self.downloadCancelled = False
|
||||
self.was_download_cancelled = False
|
||||
self.downloading = translate('OpenLP.FirstTimeWizard', 'Downloading %s...')
|
||||
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL('clicked()'),
|
||||
self.onCancelButtonClicked)
|
||||
@ -116,7 +122,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
unicode(gettempdir(), get_filesystem_encoding()), u'openlp'))
|
||||
self.noInternetFinishButton.setVisible(False)
|
||||
# Check if this is a re-run of the wizard.
|
||||
self.hasRunWizard = Settings().value(u'general/has run wizard', False)
|
||||
self.hasRunWizard = Settings().value(u'general/has run wizard')
|
||||
# Sort out internet access for downloads
|
||||
if self.webAccess:
|
||||
songs = self.config.get(u'songs', u'languages')
|
||||
@ -146,13 +152,13 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
# Download the theme screenshots.
|
||||
self.themeScreenshotThread = ThemeScreenshotThread(self)
|
||||
self.themeScreenshotThread.start()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def nextId(self):
|
||||
"""
|
||||
Determine the next page in the Wizard to go to.
|
||||
"""
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
if self.currentId() == FirstTimePage.Plugins:
|
||||
if not self.webAccess:
|
||||
return FirstTimePage.NoInternet
|
||||
@ -163,14 +169,13 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
elif self.currentId() == FirstTimePage.NoInternet:
|
||||
return FirstTimePage.Progress
|
||||
elif self.currentId() == FirstTimePage.Themes:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.set_busy_cursor()
|
||||
while not self.themeScreenshotThread.isFinished():
|
||||
time.sleep(0.1)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# Build the screenshot icons, as this can not be done in the thread.
|
||||
self._buildThemeScreenshots()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
return FirstTimePage.Defaults
|
||||
else:
|
||||
return self.currentId() + 1
|
||||
@ -181,7 +186,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
"""
|
||||
# Keep track of the page we are at. Triggering "Cancel" causes pageId
|
||||
# to be a -1.
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
if pageId != -1:
|
||||
self.lastId = pageId
|
||||
if pageId == FirstTimePage.Plugins:
|
||||
@ -198,11 +203,11 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.themeComboBox.addItem(item.text())
|
||||
if self.hasRunWizard:
|
||||
# Add any existing themes to list.
|
||||
for theme in self.parent().themeManagerContents.getThemes():
|
||||
for theme in self.theme_manager.get_themes():
|
||||
index = self.themeComboBox.findText(theme)
|
||||
if index == -1:
|
||||
self.themeComboBox.addItem(theme)
|
||||
default_theme = Settings().value(u'themes/global theme', u'')
|
||||
default_theme = Settings().value(u'themes/global theme')
|
||||
# Pre-select the current default theme.
|
||||
index = self.themeComboBox.findText(default_theme)
|
||||
self.themeComboBox.setCurrentIndex(index)
|
||||
@ -213,16 +218,15 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
if self.hasRunWizard:
|
||||
self.cancelButton.setVisible(False)
|
||||
elif pageId == FirstTimePage.Progress:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
self.repaint()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# Try to give the wizard a chance to redraw itself
|
||||
time.sleep(0.2)
|
||||
self._preWizard()
|
||||
self._performWizard()
|
||||
self._postWizard()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def updateScreenListCombo(self):
|
||||
"""
|
||||
@ -241,19 +245,18 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
(self.lastId <= FirstTimePage.Plugins and not self.hasRunWizard):
|
||||
QtCore.QCoreApplication.exit()
|
||||
sys.exit()
|
||||
self.downloadCancelled = True
|
||||
self.was_download_cancelled = True
|
||||
while self.themeScreenshotThread.isRunning():
|
||||
time.sleep(0.1)
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def onNoInternetFinishButtonClicked(self):
|
||||
"""
|
||||
Process the triggering of the "Finish" button on the No Internet page.
|
||||
"""
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
self._performWizard()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.set_normal_cursor()
|
||||
Settings().setValue(u'general/has run wizard', True)
|
||||
self.close()
|
||||
|
||||
@ -267,7 +270,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
urlfile = urllib2.urlopen(url)
|
||||
filename = open(fpath, "wb")
|
||||
# Download until finished or canceled.
|
||||
while not self.downloadCancelled:
|
||||
while not self.was_download_cancelled:
|
||||
data = urlfile.read(block_size)
|
||||
if not data:
|
||||
break
|
||||
@ -276,7 +279,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self._downloadProgress(block_count, block_size)
|
||||
filename.close()
|
||||
# Delete file if cancelled, it may be a partial file.
|
||||
if self.downloadCancelled:
|
||||
if self.was_download_cancelled:
|
||||
os.remove(fpath)
|
||||
|
||||
def _buildThemeScreenshots(self):
|
||||
@ -297,11 +300,20 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
screenshot)))
|
||||
|
||||
def _getFileSize(self, url):
|
||||
"""
|
||||
Get the size of a file.
|
||||
|
||||
``url``
|
||||
The URL of the file we want to download.
|
||||
"""
|
||||
site = urllib.urlopen(url)
|
||||
meta = site.info()
|
||||
return int(meta.getheaders("Content-Length")[0])
|
||||
|
||||
def _downloadProgress(self, count, block_size):
|
||||
"""
|
||||
Calculate and display the download progress.
|
||||
"""
|
||||
increment = (count * block_size) - self.previous_size
|
||||
self._incrementProgressBar(None, increment)
|
||||
self.previous_size = count * block_size
|
||||
@ -320,7 +332,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.progressLabel.setText(status_text)
|
||||
if increment > 0:
|
||||
self.progressBar.setValue(self.progressBar.value() + increment)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def _preWizard(self):
|
||||
"""
|
||||
@ -328,10 +340,10 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
"""
|
||||
self.max_progress = 0
|
||||
self.finishButton.setVisible(False)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# Loop through the songs list and increase for each selected item
|
||||
for i in xrange(self.songsListWidget.count()):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
item = self.songsListWidget.item(i)
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
filename = item.data(QtCore.Qt.UserRole)
|
||||
@ -340,7 +352,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
# Loop through the Bibles list and increase for each selected item
|
||||
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
|
||||
while iterator.value():
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
item = iterator.value()
|
||||
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
|
||||
filename = item.data(0, QtCore.Qt.UserRole)
|
||||
@ -349,7 +361,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
iterator += 1
|
||||
# Loop through the themes list and increase for each selected item
|
||||
for i in xrange(self.themesListWidget.count()):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
item = self.themesListWidget.item(i)
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
filename = item.data(QtCore.Qt.UserRole)
|
||||
@ -357,7 +369,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.max_progress += size
|
||||
if self.max_progress:
|
||||
# Add on 2 for plugins status setting plus a "finished" point.
|
||||
self.max_progress = self.max_progress + 2
|
||||
self.max_progress += 2
|
||||
self.progressBar.setValue(0)
|
||||
self.progressBar.setMinimum(0)
|
||||
self.progressBar.setMaximum(self.max_progress)
|
||||
@ -369,7 +381,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard', 'Setting Up'))
|
||||
self.progressPage.setSubTitle(u'Setup complete.')
|
||||
self.repaint()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# Try to give the wizard a chance to repaint itself
|
||||
time.sleep(0.1)
|
||||
|
||||
@ -396,7 +408,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
self.finishButton.setEnabled(True)
|
||||
self.cancelButton.setVisible(False)
|
||||
self.nextButton.setVisible(False)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def _performWizard(self):
|
||||
"""
|
||||
@ -459,5 +471,28 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
|
||||
Settings().setValue(u'themes/global theme', self.themeComboBox.currentText())
|
||||
|
||||
def _setPluginStatus(self, field, tag):
|
||||
"""
|
||||
Set the status of a plugin.
|
||||
"""
|
||||
status = PluginStatus.Active if field.checkState() == QtCore.Qt.Checked else PluginStatus.Inactive
|
||||
Settings().setValue(tag, status)
|
||||
|
||||
def _get_theme_manager(self):
|
||||
"""
|
||||
Adds the theme manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_theme_manager'):
|
||||
self._theme_manager = Registry().get(u'theme_manager')
|
||||
return self._theme_manager
|
||||
|
||||
theme_manager = property(_get_theme_manager)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -26,20 +26,29 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets of the language selection dialog.
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_FirstTimeLanguageDialog(object):
|
||||
"""
|
||||
The UI widgets of the language selection dialog.
|
||||
"""
|
||||
def setupUi(self, languageDialog):
|
||||
"""
|
||||
Set up the UI.
|
||||
"""
|
||||
languageDialog.setObjectName(u'languageDialog')
|
||||
languageDialog.resize(300, 50)
|
||||
self.dialogLayout = QtGui.QVBoxLayout(languageDialog)
|
||||
self.dialogLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dialogLayout.setSpacing(8)
|
||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||
self.dialogLayout.setObjectName(u'dialog_layout')
|
||||
self.infoLabel = QtGui.QLabel(languageDialog)
|
||||
self.infoLabel.setObjectName(u'infoLabel')
|
||||
self.dialogLayout.addWidget(self.infoLabel)
|
||||
@ -53,12 +62,15 @@ class Ui_FirstTimeLanguageDialog(object):
|
||||
self.languageComboBox.setObjectName("languageComboBox")
|
||||
self.languageLayout.addWidget(self.languageComboBox)
|
||||
self.dialogLayout.addLayout(self.languageLayout)
|
||||
self.buttonBox = create_button_box(languageDialog, u'buttonBox', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(languageDialog, u'button_box', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.button_box)
|
||||
self.retranslateUi(languageDialog)
|
||||
self.setMaximumHeight(self.sizeHint().height())
|
||||
|
||||
def retranslateUi(self, languageDialog):
|
||||
"""
|
||||
Translate the UI on the fly.
|
||||
"""
|
||||
self.setWindowTitle(translate('OpenLP.FirstTimeLanguageForm', 'Select Translation'))
|
||||
self.infoLabel.setText(
|
||||
translate('OpenLP.FirstTimeLanguageForm', 'Choose the translation you\'d like to use in OpenLP.'))
|
||||
|
@ -26,18 +26,24 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The language selection dialog.
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib.ui import create_action
|
||||
from openlp.core.utils import LanguageManager
|
||||
from firsttimelanguagedialog import Ui_FirstTimeLanguageDialog
|
||||
|
||||
|
||||
class FirstTimeLanguageForm(QtGui.QDialog, Ui_FirstTimeLanguageDialog):
|
||||
"""
|
||||
The exception dialog
|
||||
The language selection dialog.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.qmList = LanguageManager.get_qm_list()
|
||||
@ -52,6 +58,9 @@ class FirstTimeLanguageForm(QtGui.QDialog, Ui_FirstTimeLanguageDialog):
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
Run when the dialog is OKed.
|
||||
"""
|
||||
# It's the first row so must be Automatic
|
||||
if self.languageComboBox.currentIndex() == 0:
|
||||
LanguageManager.auto_language = True
|
||||
@ -63,6 +72,9 @@ class FirstTimeLanguageForm(QtGui.QDialog, Ui_FirstTimeLanguageDialog):
|
||||
return QtGui.QDialog.accept(self)
|
||||
|
||||
def reject(self):
|
||||
"""
|
||||
Run when the dialog is canceled.
|
||||
"""
|
||||
LanguageManager.auto_language = True
|
||||
LanguageManager.set_language(False, False)
|
||||
return QtGui.QDialog.reject(self)
|
||||
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets for the first time wizard.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
import sys
|
||||
@ -34,7 +36,11 @@ import sys
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import add_welcome_page
|
||||
|
||||
|
||||
class FirstTimePage(object):
|
||||
"""
|
||||
An enumeration class with each of the pages of the wizard.
|
||||
"""
|
||||
Welcome = 0
|
||||
Plugins = 1
|
||||
NoInternet = 2
|
||||
@ -46,7 +52,13 @@ class FirstTimePage(object):
|
||||
|
||||
|
||||
class Ui_FirstTimeWizard(object):
|
||||
"""
|
||||
The UI widgets for the first time wizard.
|
||||
"""
|
||||
def setupUi(self, FirstTimeWizard):
|
||||
"""
|
||||
Set up the UI.
|
||||
"""
|
||||
FirstTimeWizard.setObjectName(u'FirstTimeWizard')
|
||||
FirstTimeWizard.resize(550, 386)
|
||||
FirstTimeWizard.setModal(True)
|
||||
@ -193,9 +205,12 @@ class Ui_FirstTimeWizard(object):
|
||||
self.retranslateUi(FirstTimeWizard)
|
||||
|
||||
def retranslateUi(self, FirstTimeWizard):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
FirstTimeWizard.setWindowTitle(translate(
|
||||
'OpenLP.FirstTimeWizard', 'First Time Wizard'))
|
||||
self.titleLabel.setText(u'<span style="font-size:14pt; font-weight:600;">%s</span>' % \
|
||||
self.titleLabel.setText(u'<span style="font-size:14pt; font-weight:600;">%s</span>' %
|
||||
translate('OpenLP.FirstTimeWizard', 'Welcome to the First Time Wizard'))
|
||||
self.informationLabel.setText(translate('OpenLP.FirstTimeWizard',
|
||||
'This wizard will help you to configure OpenLP for initial use.'
|
||||
|
@ -26,15 +26,23 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets for the formatting tags window.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import UiStrings, create_button_box
|
||||
from openlp.core.lib import UiStrings, translate
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_FormattingTagDialog(object):
|
||||
|
||||
"""
|
||||
The UI widgets for the formatting tags window.
|
||||
"""
|
||||
def setupUi(self, formattingTagDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
formattingTagDialog.setObjectName(u'formattingTagDialog')
|
||||
formattingTagDialog.resize(725, 548)
|
||||
self.listdataGridLayout = QtGui.QGridLayout(formattingTagDialog)
|
||||
@ -109,12 +117,15 @@ class Ui_FormattingTagDialog(object):
|
||||
self.savePushButton.setObjectName(u'savePushButton')
|
||||
self.dataGridLayout.addWidget(self.savePushButton, 4, 2, 1, 1)
|
||||
self.listdataGridLayout.addWidget(self.editGroupBox, 2, 0, 1, 1)
|
||||
self.buttonBox = create_button_box(formattingTagDialog, u'buttonBox', [u'close'])
|
||||
self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1)
|
||||
self.button_box = create_button_box(formattingTagDialog, u'button_box', [u'close'])
|
||||
self.listdataGridLayout.addWidget(self.button_box, 3, 0, 1, 1)
|
||||
|
||||
self.retranslateUi(formattingTagDialog)
|
||||
|
||||
def retranslateUi(self, formattingTagDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
formattingTagDialog.setWindowTitle(translate('OpenLP.FormattingTagDialog', 'Configure Formatting Tags'))
|
||||
self.editGroupBox.setTitle(translate('OpenLP.FormattingTagDialog', 'Edit Selection'))
|
||||
self.savePushButton.setText(translate('OpenLP.FormattingTagDialog', 'Save'))
|
||||
|
@ -27,14 +27,13 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are
|
||||
protected and included each time loaded. Custom tags can be defined and saved.
|
||||
The Custom Tag arrays are saved in a pickle so QSettings works on them. Base
|
||||
Tags cannot be changed.
|
||||
The :mod:`formattingtagform` provides an Tag Edit facility. The Base set are protected and included each time loaded.
|
||||
Custom tags can be defined and saved. The Custom Tag arrays are saved in a pickle so QSettings works on them. Base Tags
|
||||
cannot be changed.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, FormattingTags
|
||||
from openlp.core.lib import FormattingTags, translate
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui.formattingtagdialog import Ui_FormattingTagDialog
|
||||
|
||||
@ -53,7 +52,7 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
|
||||
QtCore.QObject.connect(self.newPushButton, QtCore.SIGNAL(u'clicked()'), self.onNewClicked)
|
||||
QtCore.QObject.connect(self.savePushButton, QtCore.SIGNAL(u'clicked()'), self.onSavedClicked)
|
||||
QtCore.QObject.connect(self.deletePushButton, QtCore.SIGNAL(u'clicked()'), self.onDeleteClicked)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'), self.close)
|
||||
QtCore.QObject.connect(self.button_box, QtCore.SIGNAL(u'rejected()'), self.close)
|
||||
QtCore.QObject.connect(self.descriptionLineEdit, QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited)
|
||||
QtCore.QObject.connect(self.tagLineEdit, QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited)
|
||||
QtCore.QObject.connect(self.startTagLineEdit, QtCore.SIGNAL(u'textEdited(QString)'), self.onTextEdited)
|
||||
|
@ -26,16 +26,18 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The general tab of the configuration dialog.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, Settings, SettingsTab, translate
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.ui import ScreenList
|
||||
from openlp.core.lib import Receiver, Settings, SettingsTab, ScreenList, UiStrings, translate
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GeneralTab(SettingsTab):
|
||||
"""
|
||||
GeneralTab is the general settings tab in the settings dialog.
|
||||
@ -247,28 +249,28 @@ class GeneralTab(SettingsTab):
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.monitorComboBox.clear()
|
||||
self.monitorComboBox.addItems(self.screens.get_screen_list())
|
||||
monitorNumber = settings.value(u'monitor', self.screens.display_count - 1)
|
||||
monitorNumber = settings.value(u'monitor')
|
||||
self.monitorComboBox.setCurrentIndex(monitorNumber)
|
||||
self.numberEdit.setText(settings.value(u'ccli number', u''))
|
||||
self.usernameEdit.setText(settings.value(u'songselect username', u''))
|
||||
self.passwordEdit.setText(settings.value(u'songselect password', u''))
|
||||
self.saveCheckServiceCheckBox.setChecked(settings.value(u'save prompt', False))
|
||||
self.autoUnblankCheckBox.setChecked(settings.value(u'auto unblank', False))
|
||||
self.numberEdit.setText(settings.value(u'ccli number'))
|
||||
self.usernameEdit.setText(settings.value(u'songselect username'))
|
||||
self.passwordEdit.setText(settings.value(u'songselect password'))
|
||||
self.saveCheckServiceCheckBox.setChecked(settings.value(u'save prompt'))
|
||||
self.autoUnblankCheckBox.setChecked(settings.value(u'auto unblank'))
|
||||
self.displayOnMonitorCheck.setChecked(self.screens.display)
|
||||
self.warningCheckBox.setChecked(settings.value(u'blank warning', False))
|
||||
self.autoOpenCheckBox.setChecked(settings.value(u'auto open', False))
|
||||
self.showSplashCheckBox.setChecked(settings.value(u'show splash', True))
|
||||
self.checkForUpdatesCheckBox.setChecked(settings.value(u'update check', True))
|
||||
self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview', False))
|
||||
self.timeoutSpinBox.setValue(settings.value(u'loop delay', 5))
|
||||
self.monitorRadioButton.setChecked(not settings.value(u'override position', False))
|
||||
self.overrideRadioButton.setChecked(settings.value(u'override position', False))
|
||||
self.customXValueEdit.setValue(settings.value(u'x position', self.screens.current[u'size'].x()))
|
||||
self.customYValueEdit.setValue(settings.value(u'y position', self.screens.current[u'size'].y()))
|
||||
self.customHeightValueEdit.setValue(settings.value(u'height', self.screens.current[u'size'].height()))
|
||||
self.customWidthValueEdit.setValue(settings.value(u'width', self.screens.current[u'size'].width()))
|
||||
self.startPausedCheckBox.setChecked(settings.value(u'audio start paused', True))
|
||||
self.repeatListCheckBox.setChecked(settings.value(u'audio repeat list', False))
|
||||
self.warningCheckBox.setChecked(settings.value(u'blank warning'))
|
||||
self.autoOpenCheckBox.setChecked(settings.value(u'auto open'))
|
||||
self.showSplashCheckBox.setChecked(settings.value(u'show splash'))
|
||||
self.checkForUpdatesCheckBox.setChecked(settings.value(u'update check'))
|
||||
self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview'))
|
||||
self.timeoutSpinBox.setValue(settings.value(u'loop delay'))
|
||||
self.monitorRadioButton.setChecked(not settings.value(u'override position',))
|
||||
self.overrideRadioButton.setChecked(settings.value(u'override position'))
|
||||
self.customXValueEdit.setValue(settings.value(u'x position'))
|
||||
self.customYValueEdit.setValue(settings.value(u'y position'))
|
||||
self.customHeightValueEdit.setValue(settings.value(u'height'))
|
||||
self.customWidthValueEdit.setValue(settings.value(u'width'))
|
||||
self.startPausedCheckBox.setChecked(settings.value(u'audio start paused'))
|
||||
self.repeatListCheckBox.setChecked(settings.value(u'audio repeat list'))
|
||||
settings.endGroup()
|
||||
self.monitorComboBox.setDisabled(self.overrideRadioButton.isChecked())
|
||||
self.customXValueEdit.setEnabled(self.overrideRadioButton.isChecked())
|
||||
|
@ -27,27 +27,30 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`maindisplay` module provides the functionality to display screens
|
||||
and play multimedia within OpenLP.
|
||||
The :mod:`maindisplay` module provides the functionality to display screens and play multimedia within OpenLP.
|
||||
|
||||
Some of the code for this form is based on the examples at:
|
||||
|
||||
* `http://www.steveheffernan.com/html5-video-player/demo-video-player.html`_
|
||||
* `http://html5demos.com/two-videos`_
|
||||
|
||||
"""
|
||||
import cgi
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt4 import QtCore, QtGui, QtWebKit, QtOpenGL
|
||||
from PyQt4.phonon import Phonon
|
||||
|
||||
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, translate, PluginManager, expand_tags,\
|
||||
Settings, ImageSource
|
||||
from openlp.core.lib import Receiver, ServiceItem, Settings, ImageSource, Registry, build_html, expand_tags, \
|
||||
image_to_byte, translate
|
||||
from openlp.core.lib.theme import BackgroundType
|
||||
|
||||
from openlp.core.ui import HideMode, ScreenList, AlertLocation
|
||||
from openlp.core.lib import ScreenList
|
||||
from openlp.core.ui import HideMode, AlertLocation
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
#http://www.steveheffernan.com/html5-video-player/demo-video-player.html
|
||||
#http://html5demos.com/two-videos
|
||||
|
||||
class Display(QtGui.QGraphicsView):
|
||||
"""
|
||||
@ -56,6 +59,9 @@ class Display(QtGui.QGraphicsView):
|
||||
Preview display.
|
||||
"""
|
||||
def __init__(self, parent, live, controller):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
if live:
|
||||
QtGui.QGraphicsView.__init__(self)
|
||||
# Overwrite the parent() method.
|
||||
@ -65,7 +71,6 @@ class Display(QtGui.QGraphicsView):
|
||||
self.isLive = live
|
||||
self.controller = controller
|
||||
self.screen = {}
|
||||
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
|
||||
@ -101,6 +106,9 @@ class Display(QtGui.QGraphicsView):
|
||||
QtCore.Qt.ScrollBarAlwaysOff)
|
||||
|
||||
def resizeEvent(self, event):
|
||||
"""
|
||||
React to resizing of this display
|
||||
"""
|
||||
self.webView.setGeometry(0, 0, self.width(), self.height())
|
||||
|
||||
def isWebLoaded(self):
|
||||
@ -115,9 +123,11 @@ class MainDisplay(Display):
|
||||
"""
|
||||
This is the display screen as a specialized class from the Display class
|
||||
"""
|
||||
def __init__(self, parent, imageManager, live, controller):
|
||||
def __init__(self, parent, live, controller):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
Display.__init__(self, parent, live, controller)
|
||||
self.imageManager = imageManager
|
||||
self.screens = ScreenList()
|
||||
self.rebuildCSS = False
|
||||
self.hideMode = None
|
||||
@ -131,18 +141,8 @@ class MainDisplay(Display):
|
||||
self.firstTime = True
|
||||
self.webLoaded = True
|
||||
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
|
||||
windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | \
|
||||
QtCore.Qt.WindowStaysOnTopHint
|
||||
# Fix for bug #1014422.
|
||||
x11_bypass_default = True
|
||||
if sys.platform.startswith(u'linux'):
|
||||
# Default to False on Gnome.
|
||||
x11_bypass_default = bool(not
|
||||
os.environ.get(u'GNOME_DESKTOP_SESSION_ID'))
|
||||
# Default to False on XFce
|
||||
if os.environ.get(u'DESKTOP_SESSION') == u'xfce':
|
||||
x11_bypass_default = False
|
||||
if Settings().value(u'advanced/x11 bypass wm', x11_bypass_default):
|
||||
windowFlags = QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint
|
||||
if Settings().value(u'advanced/x11 bypass wm'):
|
||||
windowFlags |= QtCore.Qt.X11BypassWindowManagerHint
|
||||
# TODO: The following combination of windowFlags works correctly
|
||||
# on Mac OS X. For next OpenLP version we should test it on other
|
||||
@ -164,6 +164,9 @@ class MainDisplay(Display):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configChanged)
|
||||
|
||||
def setTransparency(self, enabled):
|
||||
"""
|
||||
Set the transparency of the window
|
||||
"""
|
||||
if enabled:
|
||||
self.setAutoFillBackground(False)
|
||||
else:
|
||||
@ -182,8 +185,8 @@ class MainDisplay(Display):
|
||||
Call the plugins to rebuild the Live display CSS as the screen has
|
||||
not been rebuild on exit of config.
|
||||
"""
|
||||
if self.rebuildCSS and self.plugins:
|
||||
for plugin in self.plugins:
|
||||
if self.rebuildCSS and self.plugin_manager.plugins:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
plugin.refreshCss(self.frame)
|
||||
self.rebuildCSS = False
|
||||
|
||||
@ -204,10 +207,10 @@ class MainDisplay(Display):
|
||||
if self.isLive:
|
||||
# Build the initial frame.
|
||||
background_color = QtGui.QColor()
|
||||
background_color.setNamedColor(Settings().value(u'advanced/default color', u'#ffffff'))
|
||||
background_color.setNamedColor(Settings().value(u'advanced/default color'))
|
||||
if not background_color.isValid():
|
||||
background_color = QtCore.Qt.white
|
||||
image_file = Settings().value(u'advanced/default image', u':/graphics/openlp-splash-screen.png')
|
||||
image_file = Settings().value(u'advanced/default image')
|
||||
splash_image = QtGui.QImage(image_file)
|
||||
self.initialFrame = QtGui.QImage(
|
||||
self.screen[u'size'].width(),
|
||||
@ -222,8 +225,8 @@ class MainDisplay(Display):
|
||||
splash_image)
|
||||
serviceItem = ServiceItem()
|
||||
serviceItem.bg_image_bytes = image_to_byte(self.initialFrame)
|
||||
self.webView.setHtml(build_html(serviceItem, self.screen,
|
||||
self.isLive, None, plugins=self.plugins))
|
||||
self.webView.setHtml(build_html(serviceItem, self.screen, self.isLive, None,
|
||||
plugins=self.plugin_manager.plugins))
|
||||
self.__hideMouse()
|
||||
log.debug(u'Finished MainDisplay setup')
|
||||
|
||||
@ -240,7 +243,7 @@ class MainDisplay(Display):
|
||||
log.debug(u'text to display')
|
||||
# Wait for the webview to update before displaying text.
|
||||
while not self.webLoaded:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
self.setGeometry(self.screen[u'size'])
|
||||
if animate:
|
||||
self.frame.evaluateJavaScript(u'show_text("%s")' % slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
|
||||
@ -289,7 +292,7 @@ class MainDisplay(Display):
|
||||
"""
|
||||
API for replacement backgrounds so Images are added directly to cache.
|
||||
"""
|
||||
self.imageManager.addImage(path, ImageSource.ImagePlugin, background)
|
||||
self.image_manager.add_image(path, ImageSource.ImagePlugin, background)
|
||||
if not hasattr(self, u'serviceItem'):
|
||||
return False
|
||||
self.override[u'image'] = path
|
||||
@ -311,8 +314,8 @@ class MainDisplay(Display):
|
||||
re-added to the image manager.
|
||||
"""
|
||||
log.debug(u'image to display')
|
||||
image = self.imageManager.getImageBytes(path, ImageSource.ImagePlugin)
|
||||
self.controller.mediaController.media_reset(self.controller)
|
||||
image = self.image_manager.get_image_bytes(path, ImageSource.ImagePlugin)
|
||||
self.controller.media_controller.media_reset(self.controller)
|
||||
self.displayImage(image)
|
||||
|
||||
def displayImage(self, image):
|
||||
@ -344,18 +347,18 @@ class MainDisplay(Display):
|
||||
Generates a preview of the image displayed.
|
||||
"""
|
||||
log.debug(u'preview for %s', self.isLive)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# We must have a service item to preview.
|
||||
if self.isLive and hasattr(self, u'serviceItem'):
|
||||
# Wait for the fade to finish before geting the preview.
|
||||
# Important otherwise preview will have incorrect text if at all!
|
||||
if self.serviceItem.themedata and self.serviceItem.themedata.display_slide_transition:
|
||||
while self.frame.evaluateJavaScript(u'show_text_complete()') == u'false':
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# Wait for the webview to update before getting the preview.
|
||||
# Important otherwise first preview will miss the background !
|
||||
while not self.webLoaded:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
# if was hidden keep it hidden
|
||||
if self.isLive:
|
||||
if self.hideMode:
|
||||
@ -364,7 +367,7 @@ class MainDisplay(Display):
|
||||
# Single screen active
|
||||
if self.screens.display_count == 1:
|
||||
# Only make visible if setting enabled.
|
||||
if Settings().value(u'general/display on monitor', True):
|
||||
if Settings().value(u'general/display on monitor'):
|
||||
self.setVisible(True)
|
||||
else:
|
||||
self.setVisible(True)
|
||||
@ -392,17 +395,20 @@ class MainDisplay(Display):
|
||||
self.override = {}
|
||||
else:
|
||||
# replace the background
|
||||
background = self.imageManager.getImageBytes(self.override[u'image'], ImageSource.ImagePlugin)
|
||||
background = self.image_manager.get_image_bytes(self.override[u'image'], ImageSource.ImagePlugin)
|
||||
self.setTransparency(self.serviceItem.themedata.background_type ==
|
||||
BackgroundType.to_string(BackgroundType.Transparent))
|
||||
if self.serviceItem.themedata.background_filename:
|
||||
self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes(
|
||||
self.serviceItem.themedata.background_filename,ImageSource.Theme)
|
||||
self.serviceItem.bg_image_bytes = self.image_manager.get_image_bytes(
|
||||
self.serviceItem.themedata.background_filename,
|
||||
ImageSource.Theme
|
||||
)
|
||||
if image_path:
|
||||
image_bytes = self.imageManager.getImageBytes(image_path, ImageSource.ImagePlugin)
|
||||
image_bytes = self.image_manager.get_image_bytes(image_path, ImageSource.ImagePlugin)
|
||||
else:
|
||||
image_bytes = None
|
||||
html = build_html(self.serviceItem, self.screen, self.isLive, background, image_bytes, self.plugins)
|
||||
html = build_html(self.serviceItem, self.screen, self.isLive, background, image_bytes,
|
||||
plugins=self.plugin_manager.plugins)
|
||||
log.debug(u'buildHtml - pre setHtml')
|
||||
self.webView.setHtml(html)
|
||||
log.debug(u'buildHtml - post setHtml')
|
||||
@ -410,7 +416,7 @@ class MainDisplay(Display):
|
||||
self.footer(serviceItem.foot_text)
|
||||
# if was hidden keep it hidden
|
||||
if self.hideMode and self.isLive and not serviceItem.is_media():
|
||||
if Settings().value(u'general/auto unblank', False):
|
||||
if Settings().value(u'general/auto unblank'):
|
||||
Receiver.send_message(u'slidecontroller_live_unblank')
|
||||
else:
|
||||
self.hideDisplay(self.hideMode)
|
||||
@ -432,7 +438,7 @@ class MainDisplay(Display):
|
||||
log.debug(u'hideDisplay mode = %d', mode)
|
||||
if self.screens.display_count == 1:
|
||||
# Only make visible if setting enabled.
|
||||
if not Settings().value(u'general/display on monitor', True):
|
||||
if not Settings().value(u'general/display on monitor'):
|
||||
return
|
||||
if mode == HideMode.Screen:
|
||||
self.frame.evaluateJavaScript(u'show_blank("desktop");')
|
||||
@ -456,7 +462,7 @@ class MainDisplay(Display):
|
||||
log.debug(u'showDisplay')
|
||||
if self.screens.display_count == 1:
|
||||
# Only make visible if setting enabled.
|
||||
if not Settings().value(u'general/display on monitor', True):
|
||||
if not Settings().value(u'general/display on monitor'):
|
||||
return
|
||||
self.frame.evaluateJavaScript('show_blank("show");')
|
||||
if self.isHidden():
|
||||
@ -470,13 +476,43 @@ class MainDisplay(Display):
|
||||
"""
|
||||
Hide mouse cursor when moved over display.
|
||||
"""
|
||||
if Settings().value(u'advanced/hide mouse', True):
|
||||
if Settings().value(u'advanced/hide mouse'):
|
||||
self.setCursor(QtCore.Qt.BlankCursor)
|
||||
self.frame.evaluateJavaScript('document.body.style.cursor = "none"')
|
||||
else:
|
||||
self.setCursor(QtCore.Qt.ArrowCursor)
|
||||
self.frame.evaluateJavaScript('document.body.style.cursor = "auto"')
|
||||
|
||||
def _get_plugin_manager(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_plugin_manager'):
|
||||
self._plugin_manager = Registry().get(u'plugin_manager')
|
||||
return self._plugin_manager
|
||||
|
||||
plugin_manager = property(_get_plugin_manager)
|
||||
|
||||
def _get_image_manager(self):
|
||||
"""
|
||||
Adds the image manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_image_manager'):
|
||||
self._image_manager = Registry().get(u'image_manager')
|
||||
return self._image_manager
|
||||
|
||||
image_manager = property(_get_image_manager)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
||||
|
||||
class AudioPlayer(QtCore.QObject):
|
||||
"""
|
||||
@ -522,6 +558,9 @@ class AudioPlayer(QtCore.QObject):
|
||||
self.mediaObject.enqueue(self.playlist[self.currentIndex])
|
||||
|
||||
def onFinished(self):
|
||||
"""
|
||||
When the audio track finishes.
|
||||
"""
|
||||
if self.repeat:
|
||||
log.debug(u'Repeat is enabled... here we go again!')
|
||||
self.mediaObject.clearQueue()
|
||||
@ -530,6 +569,9 @@ class AudioPlayer(QtCore.QObject):
|
||||
self.play()
|
||||
|
||||
def connectVolumeSlider(self, slider):
|
||||
"""
|
||||
Connect the volume slider to the output channel.
|
||||
"""
|
||||
slider.setAudioOutput(self.audioObject)
|
||||
|
||||
def reset(self):
|
||||
@ -576,6 +618,9 @@ class AudioPlayer(QtCore.QObject):
|
||||
self.playlist.extend(map(Phonon.MediaSource, filenames))
|
||||
|
||||
def next(self):
|
||||
"""
|
||||
Skip forward to the next track in the list
|
||||
"""
|
||||
if not self.repeat and self.currentIndex + 1 >= len(self.playlist):
|
||||
return
|
||||
isPlaying = self.mediaObject.state() == Phonon.PlayingState
|
||||
@ -589,6 +634,9 @@ class AudioPlayer(QtCore.QObject):
|
||||
self.mediaObject.play()
|
||||
|
||||
def goTo(self, index):
|
||||
"""
|
||||
Go to a particular track in the list
|
||||
"""
|
||||
isPlaying = self.mediaObject.state() == Phonon.PlayingState
|
||||
self.mediaObject.clearQueue()
|
||||
self.mediaObject.clear()
|
||||
@ -599,4 +647,7 @@ class AudioPlayer(QtCore.QObject):
|
||||
|
||||
#@todo is this used?
|
||||
def connectSlot(self, signal, slot):
|
||||
"""
|
||||
Connect a slot to a signal on the media object
|
||||
"""
|
||||
QtCore.QObject.connect(self.mediaObject, signal, slot)
|
||||
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
This is the main window, where all the action happens.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
@ -39,18 +41,16 @@ from datetime import datetime
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, PluginManager, Receiver, translate, ImageManager, \
|
||||
PluginStatus
|
||||
from openlp.core.lib import Renderer, OpenLPDockWidget, PluginManager, Receiver, ImageManager, PluginStatus, Registry, \
|
||||
Settings, ScreenList, build_icon, check_directory_exists, translate
|
||||
from openlp.core.lib.ui import UiStrings, create_action
|
||||
from openlp.core.lib import SlideLimits, Settings
|
||||
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, ThemeManager, SlideController, PluginForm, \
|
||||
MediaDockManager, ShortcutListForm, FormattingTagForm
|
||||
from openlp.core.ui.media import MediaController
|
||||
from openlp.core.utils import AppLocation, add_actions, LanguageManager, get_application_version, \
|
||||
from openlp.core.utils import AppLocation, LanguageManager, add_actions, get_application_version, \
|
||||
get_filesystem_encoding
|
||||
from openlp.core.utils.actions import ActionList, CategoryOrder
|
||||
from openlp.core.ui.firsttimeform import FirstTimeForm
|
||||
from openlp.core.ui import ScreenList
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -80,22 +80,26 @@ PROGRESSBAR_STYLE = """
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, mainWindow):
|
||||
"""
|
||||
This is the UI part of the main window.
|
||||
"""
|
||||
def setupUi(self, main_window):
|
||||
"""
|
||||
Set up the user interface
|
||||
"""
|
||||
mainWindow.setObjectName(u'MainWindow')
|
||||
mainWindow.setWindowIcon(build_icon(u':/icon/openlp-logo-64x64.png'))
|
||||
mainWindow.setDockNestingEnabled(True)
|
||||
main_window.setObjectName(u'MainWindow')
|
||||
main_window.setWindowIcon(build_icon(u':/icon/openlp-logo-64x64.png'))
|
||||
main_window.setDockNestingEnabled(True)
|
||||
# Set up the main container, which contains all the other form widgets.
|
||||
self.mainContent = QtGui.QWidget(mainWindow)
|
||||
self.mainContent = QtGui.QWidget(main_window)
|
||||
self.mainContent.setObjectName(u'mainContent')
|
||||
self.mainContentLayout = QtGui.QHBoxLayout(self.mainContent)
|
||||
self.mainContentLayout.setSpacing(0)
|
||||
self.mainContentLayout.setMargin(0)
|
||||
self.mainContentLayout.setObjectName(u'mainContentLayout')
|
||||
mainWindow.setCentralWidget(self.mainContent)
|
||||
main_window.setCentralWidget(self.mainContent)
|
||||
self.controlSplitter = QtGui.QSplitter(self.mainContent)
|
||||
self.controlSplitter.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.controlSplitter.setObjectName(u'controlSplitter')
|
||||
@ -103,13 +107,13 @@ class Ui_MainWindow(object):
|
||||
# Create slide controllers
|
||||
self.previewController = SlideController(self)
|
||||
self.liveController = SlideController(self, True)
|
||||
previewVisible = Settings().value(u'user interface/preview panel', True)
|
||||
previewVisible = Settings().value(u'user interface/preview panel')
|
||||
self.previewController.panel.setVisible(previewVisible)
|
||||
liveVisible = Settings().value(u'user interface/live panel', True)
|
||||
panelLocked = Settings().value(u'user interface/lock panel', False)
|
||||
liveVisible = Settings().value(u'user interface/live panel')
|
||||
panelLocked = Settings().value(u'user interface/lock panel')
|
||||
self.liveController.panel.setVisible(liveVisible)
|
||||
# Create menu
|
||||
self.menuBar = QtGui.QMenuBar(mainWindow)
|
||||
self.menuBar = QtGui.QMenuBar(main_window)
|
||||
self.menuBar.setObjectName(u'menuBar')
|
||||
self.fileMenu = QtGui.QMenu(self.menuBar)
|
||||
self.fileMenu.setObjectName(u'fileMenu')
|
||||
@ -135,10 +139,10 @@ class Ui_MainWindow(object):
|
||||
# Help Menu
|
||||
self.helpMenu = QtGui.QMenu(self.menuBar)
|
||||
self.helpMenu.setObjectName(u'helpMenu')
|
||||
mainWindow.setMenuBar(self.menuBar)
|
||||
self.statusBar = QtGui.QStatusBar(mainWindow)
|
||||
main_window.setMenuBar(self.menuBar)
|
||||
self.statusBar = QtGui.QStatusBar(main_window)
|
||||
self.statusBar.setObjectName(u'statusBar')
|
||||
mainWindow.setStatusBar(self.statusBar)
|
||||
main_window.setStatusBar(self.statusBar)
|
||||
self.loadProgressBar = QtGui.QProgressBar(self.statusBar)
|
||||
self.loadProgressBar.setObjectName(u'loadProgressBar')
|
||||
self.statusBar.addPermanentWidget(self.loadProgressBar)
|
||||
@ -149,142 +153,142 @@ class Ui_MainWindow(object):
|
||||
self.defaultThemeLabel.setObjectName(u'defaultThemeLabel')
|
||||
self.statusBar.addPermanentWidget(self.defaultThemeLabel)
|
||||
# Create the MediaManager
|
||||
self.mediaManagerDock = OpenLPDockWidget(mainWindow,u'mediaManagerDock', u':/system/system_mediamanager.png')
|
||||
self.mediaManagerDock = OpenLPDockWidget(main_window, u'mediaManagerDock', u':/system/system_mediamanager.png')
|
||||
self.mediaManagerDock.setStyleSheet(MEDIA_MANAGER_STYLE)
|
||||
# Create the media toolbox
|
||||
self.mediaToolBox = QtGui.QToolBox(self.mediaManagerDock)
|
||||
self.mediaToolBox.setObjectName(u'mediaToolBox')
|
||||
self.mediaManagerDock.setWidget(self.mediaToolBox)
|
||||
mainWindow.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.mediaManagerDock)
|
||||
main_window.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.mediaManagerDock)
|
||||
# Create the service manager
|
||||
self.serviceManagerDock = OpenLPDockWidget(mainWindow, u'serviceManagerDock',
|
||||
self.serviceManagerDock = OpenLPDockWidget(main_window, u'serviceManagerDock',
|
||||
u':/system/system_servicemanager.png')
|
||||
self.serviceManagerContents = ServiceManager(mainWindow, self.serviceManagerDock)
|
||||
self.serviceManagerContents = ServiceManager(self.serviceManagerDock)
|
||||
self.serviceManagerDock.setWidget(self.serviceManagerContents)
|
||||
mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.serviceManagerDock)
|
||||
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.serviceManagerDock)
|
||||
# Create the theme manager
|
||||
self.themeManagerDock = OpenLPDockWidget(mainWindow, u'themeManagerDock', u':/system/system_thememanager.png')
|
||||
self.themeManagerContents = ThemeManager(mainWindow, self.themeManagerDock)
|
||||
self.themeManagerDock = OpenLPDockWidget(main_window, u'themeManagerDock', u':/system/system_thememanager.png')
|
||||
self.themeManagerContents = ThemeManager(self.themeManagerDock)
|
||||
self.themeManagerContents.setObjectName(u'themeManagerContents')
|
||||
self.themeManagerDock.setWidget(self.themeManagerContents)
|
||||
mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.themeManagerDock)
|
||||
main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.themeManagerDock)
|
||||
# Create the menu items
|
||||
action_list = ActionList.get_instance()
|
||||
action_list.add_category(UiStrings().File, CategoryOrder.standardMenu)
|
||||
self.fileNewItem = create_action(mainWindow, u'fileNewItem',
|
||||
self.fileNewItem = create_action(main_window, u'fileNewItem',
|
||||
icon=u':/general/general_new.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Ctrl+N')],
|
||||
category=UiStrings().File,
|
||||
triggers=self.serviceManagerContents.onNewServiceClicked)
|
||||
self.fileOpenItem = create_action(mainWindow, u'fileOpenItem',
|
||||
triggers=self.serviceManagerContents.on_new_service_clicked)
|
||||
self.fileOpenItem = create_action(main_window, u'fileOpenItem',
|
||||
icon=u':/general/general_open.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Ctrl+O')],
|
||||
category=UiStrings().File,
|
||||
triggers=self.serviceManagerContents.onLoadServiceClicked)
|
||||
self.fileSaveItem = create_action(mainWindow, u'fileSaveItem',
|
||||
triggers=self.serviceManagerContents.on_load_service_clicked)
|
||||
self.fileSaveItem = create_action(main_window, u'fileSaveItem',
|
||||
icon=u':/general/general_save.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Ctrl+S')],
|
||||
category=UiStrings().File,
|
||||
triggers=self.serviceManagerContents.saveFile)
|
||||
self.fileSaveAsItem = create_action(mainWindow, u'fileSaveAsItem',
|
||||
triggers=self.serviceManagerContents.save_file)
|
||||
self.fileSaveAsItem = create_action(main_window, u'fileSaveAsItem',
|
||||
shortcuts=[QtGui.QKeySequence(u'Ctrl+Shift+S')],
|
||||
category=UiStrings().File,
|
||||
triggers=self.serviceManagerContents.saveFileAs)
|
||||
self.printServiceOrderItem = create_action(mainWindow,
|
||||
triggers=self.serviceManagerContents.save_file_as)
|
||||
self.printServiceOrderItem = create_action(main_window,
|
||||
u'printServiceItem', shortcuts=[QtGui.QKeySequence(u'Ctrl+P')],
|
||||
category=UiStrings().File,
|
||||
triggers=self.serviceManagerContents.printServiceOrder)
|
||||
self.fileExitItem = create_action(mainWindow, u'fileExitItem',
|
||||
triggers=self.serviceManagerContents.print_service_order)
|
||||
self.fileExitItem = create_action(main_window, u'fileExitItem',
|
||||
icon=u':/system/system_exit.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Alt+F4')],
|
||||
category=UiStrings().File, triggers=mainWindow.close)
|
||||
category=UiStrings().File, triggers=main_window.close)
|
||||
# Give QT Extra Hint that this is the Exit Menu Item
|
||||
self.fileExitItem.setMenuRole(QtGui.QAction.QuitRole)
|
||||
action_list.add_category(UiStrings().Import, CategoryOrder.standardMenu)
|
||||
self.importThemeItem = create_action(mainWindow, u'importThemeItem', category=UiStrings().Import)
|
||||
self.importLanguageItem = create_action(mainWindow, u'importLanguageItem')
|
||||
self.importThemeItem = create_action(main_window, u'importThemeItem', category=UiStrings().Import)
|
||||
self.importLanguageItem = create_action(main_window, u'importLanguageItem')
|
||||
action_list.add_category(UiStrings().Export, CategoryOrder.standardMenu)
|
||||
self.exportThemeItem = create_action(mainWindow, u'exportThemeItem', category=UiStrings().Export)
|
||||
self.exportLanguageItem = create_action(mainWindow, u'exportLanguageItem')
|
||||
self.exportThemeItem = create_action(main_window, u'exportThemeItem', category=UiStrings().Export)
|
||||
self.exportLanguageItem = create_action(main_window, u'exportLanguageItem')
|
||||
action_list.add_category(UiStrings().View, CategoryOrder.standardMenu)
|
||||
self.viewMediaManagerItem = create_action(mainWindow,
|
||||
self.viewMediaManagerItem = create_action(main_window,
|
||||
u'viewMediaManagerItem', shortcuts=[QtGui.QKeySequence(u'F8')],
|
||||
icon=u':/system/system_mediamanager.png',
|
||||
checked=self.mediaManagerDock.isVisible(),
|
||||
category=UiStrings().View, triggers=self.toggleMediaManager)
|
||||
self.viewThemeManagerItem = create_action(mainWindow,
|
||||
self.viewThemeManagerItem = create_action(main_window,
|
||||
u'viewThemeManagerItem', shortcuts=[QtGui.QKeySequence(u'F10')],
|
||||
icon=u':/system/system_thememanager.png',
|
||||
checked=self.themeManagerDock.isVisible(),
|
||||
category=UiStrings().View, triggers=self.toggleThemeManager)
|
||||
self.viewServiceManagerItem = create_action(mainWindow,
|
||||
self.viewServiceManagerItem = create_action(main_window,
|
||||
u'viewServiceManagerItem', shortcuts=[QtGui.QKeySequence(u'F9')],
|
||||
icon=u':/system/system_servicemanager.png',
|
||||
checked=self.serviceManagerDock.isVisible(),
|
||||
category=UiStrings().View, triggers=self.toggleServiceManager)
|
||||
self.viewPreviewPanel = create_action(mainWindow, u'viewPreviewPanel',
|
||||
self.viewPreviewPanel = create_action(main_window, u'viewPreviewPanel',
|
||||
shortcuts=[QtGui.QKeySequence(u'F11')], checked=previewVisible,
|
||||
category=UiStrings().View, triggers=self.setPreviewPanelVisibility)
|
||||
self.viewLivePanel = create_action(mainWindow, u'viewLivePanel',
|
||||
self.viewLivePanel = create_action(main_window, u'viewLivePanel',
|
||||
shortcuts=[QtGui.QKeySequence(u'F12')], checked=liveVisible,
|
||||
category=UiStrings().View, triggers=self.setLivePanelVisibility)
|
||||
self.lockPanel = create_action(mainWindow, u'lockPanel',
|
||||
self.lockPanel = create_action(main_window, u'lockPanel',
|
||||
checked=panelLocked, triggers=self.setLockPanel)
|
||||
action_list.add_category(UiStrings().ViewMode,
|
||||
CategoryOrder.standardMenu)
|
||||
self.modeDefaultItem = create_action(mainWindow, u'modeDefaultItem', checked=False,
|
||||
self.modeDefaultItem = create_action(main_window, u'modeDefaultItem', checked=False,
|
||||
category=UiStrings().ViewMode)
|
||||
self.modeSetupItem = create_action(mainWindow, u'modeSetupItem', checked=False, category=UiStrings().ViewMode)
|
||||
self.modeLiveItem = create_action(mainWindow, u'modeLiveItem', checked=True, category=UiStrings().ViewMode)
|
||||
self.modeGroup = QtGui.QActionGroup(mainWindow)
|
||||
self.modeSetupItem = create_action(main_window, u'modeSetupItem', checked=False, category=UiStrings().ViewMode)
|
||||
self.modeLiveItem = create_action(main_window, u'modeLiveItem', checked=True, category=UiStrings().ViewMode)
|
||||
self.modeGroup = QtGui.QActionGroup(main_window)
|
||||
self.modeGroup.addAction(self.modeDefaultItem)
|
||||
self.modeGroup.addAction(self.modeSetupItem)
|
||||
self.modeGroup.addAction(self.modeLiveItem)
|
||||
self.modeDefaultItem.setChecked(True)
|
||||
action_list.add_category(UiStrings().Tools, CategoryOrder.standardMenu)
|
||||
self.toolsAddToolItem = create_action(mainWindow,
|
||||
self.toolsAddToolItem = create_action(main_window,
|
||||
u'toolsAddToolItem', icon=u':/tools/tools_add.png',
|
||||
category=UiStrings().Tools)
|
||||
self.toolsOpenDataFolder = create_action(mainWindow,
|
||||
self.toolsOpenDataFolder = create_action(main_window,
|
||||
u'toolsOpenDataFolder', icon=u':/general/general_open.png',
|
||||
category=UiStrings().Tools)
|
||||
self.toolsFirstTimeWizard = create_action(mainWindow,
|
||||
self.toolsFirstTimeWizard = create_action(main_window,
|
||||
u'toolsFirstTimeWizard', icon=u':/general/general_revert.png',
|
||||
category=UiStrings().Tools)
|
||||
self.updateThemeImages = create_action(mainWindow,
|
||||
self.updateThemeImages = create_action(main_window,
|
||||
u'updateThemeImages', category=UiStrings().Tools)
|
||||
action_list.add_category(UiStrings().Settings,
|
||||
CategoryOrder.standardMenu)
|
||||
self.settingsPluginListItem = create_action(mainWindow,
|
||||
self.settingsPluginListItem = create_action(main_window,
|
||||
u'settingsPluginListItem',
|
||||
icon=u':/system/settings_plugin_list.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Alt+F7')],
|
||||
category=UiStrings().Settings, triggers=self.onPluginItemClicked)
|
||||
# i18n Language Items
|
||||
self.autoLanguageItem = create_action(mainWindow, u'autoLanguageItem',
|
||||
self.autoLanguageItem = create_action(main_window, u'autoLanguageItem',
|
||||
checked=LanguageManager.auto_language)
|
||||
self.languageGroup = QtGui.QActionGroup(mainWindow)
|
||||
self.languageGroup = QtGui.QActionGroup(main_window)
|
||||
self.languageGroup.setExclusive(True)
|
||||
self.languageGroup.setObjectName(u'languageGroup')
|
||||
add_actions(self.languageGroup, [self.autoLanguageItem])
|
||||
qmList = LanguageManager.get_qm_list()
|
||||
savedLanguage = LanguageManager.get_language()
|
||||
for key in sorted(qmList.keys()):
|
||||
languageItem = create_action(mainWindow, key, checked=qmList[key] == savedLanguage)
|
||||
languageItem = create_action(main_window, key, checked=qmList[key] == savedLanguage)
|
||||
add_actions(self.languageGroup, [languageItem])
|
||||
self.settingsShortcutsItem = create_action(mainWindow, u'settingsShortcutsItem',
|
||||
self.settingsShortcutsItem = create_action(main_window, u'settingsShortcutsItem',
|
||||
icon=u':/system/system_configure_shortcuts.png', category=UiStrings().Settings)
|
||||
# Formatting Tags were also known as display tags.
|
||||
self.formattingTagItem = create_action(mainWindow, u'displayTagItem',
|
||||
self.formattingTagItem = create_action(main_window, u'displayTagItem',
|
||||
icon=u':/system/tag_editor.png', category=UiStrings().Settings)
|
||||
self.settingsConfigureItem = create_action(mainWindow, u'settingsConfigureItem',
|
||||
self.settingsConfigureItem = create_action(main_window, u'settingsConfigureItem',
|
||||
icon=u':/system/system_settings.png', category=UiStrings().Settings)
|
||||
# Give QT Extra Hint that this is the Preferences Menu Item
|
||||
self.settingsConfigureItem.setMenuRole(QtGui.QAction.PreferencesRole)
|
||||
self.settingsImportItem = create_action(mainWindow, u'settingsImportItem', category=UiStrings().Settings)
|
||||
self.settingsExportItem = create_action(mainWindow, u'settingsExportItem', category=UiStrings().Settings)
|
||||
self.settingsImportItem = create_action(main_window, u'settingsImportItem', category=UiStrings().Settings)
|
||||
self.settingsExportItem = create_action(main_window, u'settingsExportItem', category=UiStrings().Settings)
|
||||
action_list.add_category(UiStrings().Help, CategoryOrder.standardMenu)
|
||||
self.aboutItem = create_action(mainWindow, u'aboutItem', icon=u':/system/system_about.png',
|
||||
self.aboutItem = create_action(main_window, u'aboutItem', icon=u':/system/system_about.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Ctrl+F1')],
|
||||
category=UiStrings().Help, triggers=self.onAboutItemClicked)
|
||||
# Give QT Extra Hint that this is an About Menu Item
|
||||
@ -292,15 +296,15 @@ class Ui_MainWindow(object):
|
||||
if os.name == u'nt':
|
||||
self.localHelpFile = os.path.join(
|
||||
AppLocation.get_directory(AppLocation.AppDir), 'OpenLP.chm')
|
||||
self.offlineHelpItem = create_action(mainWindow, u'offlineHelpItem',
|
||||
self.offlineHelpItem = create_action(main_window, u'offlineHelpItem',
|
||||
icon=u':/system/system_help_contents.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'F1')],
|
||||
category=UiStrings().Help, triggers=self.onOfflineHelpClicked)
|
||||
self.onlineHelpItem = create_action(mainWindow, u'onlineHelpItem',
|
||||
self.onlineHelpItem = create_action(main_window, u'onlineHelpItem',
|
||||
icon=u':/system/system_online_help.png',
|
||||
shortcuts=[QtGui.QKeySequence(u'Alt+F1')],
|
||||
category=UiStrings().Help, triggers=self.onOnlineHelpClicked)
|
||||
self.webSiteItem = create_action(mainWindow, u'webSiteItem', category=UiStrings().Help)
|
||||
self.webSiteItem = create_action(main_window, u'webSiteItem', category=UiStrings().Help)
|
||||
add_actions(self.fileImportMenu, (self.settingsImportItem, None, self.importThemeItem, self.importLanguageItem))
|
||||
add_actions(self.fileExportMenu, (self.settingsExportItem, None, self.exportThemeItem, self.exportLanguageItem))
|
||||
add_actions(self.fileMenu, (self.fileNewItem, self.fileOpenItem,
|
||||
@ -334,7 +338,7 @@ class Ui_MainWindow(object):
|
||||
add_actions(self.menuBar, (self.fileMenu.menuAction(), self.viewMenu.menuAction(), self.toolsMenu.menuAction(),
|
||||
self.settingsMenu.menuAction(), self.helpMenu.menuAction()))
|
||||
# Initialise the translation
|
||||
self.retranslateUi(mainWindow)
|
||||
self.retranslateUi(main_window)
|
||||
self.mediaToolBox.setCurrentIndex(0)
|
||||
# Connect up some signals and slots
|
||||
QtCore.QObject.connect(self.fileMenu, QtCore.SIGNAL(u'aboutToShow()'), self.updateRecentFilesMenu)
|
||||
@ -407,7 +411,8 @@ class Ui_MainWindow(object):
|
||||
'Toggle the visibility of the service manager.'))
|
||||
self.viewPreviewPanel.setText(translate('OpenLP.MainWindow', '&Preview Panel'))
|
||||
self.viewPreviewPanel.setToolTip(translate('OpenLP.MainWindow', 'Toggle Preview Panel'))
|
||||
self.viewPreviewPanel.setStatusTip(translate('OpenLP.MainWindow', 'Toggle the visibility of the preview panel.'))
|
||||
self.viewPreviewPanel.setStatusTip(
|
||||
translate('OpenLP.MainWindow', 'Toggle the visibility of the preview panel.'))
|
||||
self.viewLivePanel.setText(translate('OpenLP.MainWindow', '&Live Panel'))
|
||||
self.viewLivePanel.setToolTip(translate('OpenLP.MainWindow', 'Toggle Live Panel'))
|
||||
self.lockPanel.setText(translate('OpenLP.MainWindow', 'L&ock Panels'))
|
||||
@ -450,17 +455,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
log.info(u'MainWindow loaded')
|
||||
|
||||
def __init__(self, application):
|
||||
def __init__(self):
|
||||
"""
|
||||
This constructor sets up the interface, the various managers, and the
|
||||
plugins.
|
||||
"""
|
||||
QtGui.QMainWindow.__init__(self)
|
||||
self.application = application
|
||||
Registry().register(u'main_window', self)
|
||||
self.clipboard = self.application.clipboard()
|
||||
self.arguments = self.application.args
|
||||
# Set up settings sections for the main application
|
||||
# (not for use by plugins)
|
||||
# Set up settings sections for the main application (not for use by plugins).
|
||||
self.uiSettingsSection = u'user interface'
|
||||
self.generalSettingsSection = u'general'
|
||||
self.advancedSettingsSection = u'advanced'
|
||||
@ -471,17 +475,18 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.playersSettingsSection = u'players'
|
||||
self.displayTagsSection = u'displayTags'
|
||||
self.headerSection = u'SettingsImport'
|
||||
Settings().set_up_default_values()
|
||||
Settings().remove_obsolete_settings()
|
||||
self.serviceNotSaved = False
|
||||
self.aboutForm = AboutForm(self)
|
||||
self.mediaController = MediaController(self)
|
||||
self.settingsForm = SettingsForm(self, self)
|
||||
self.settingsForm = SettingsForm(self)
|
||||
self.formattingTagForm = FormattingTagForm(self)
|
||||
self.shortcutForm = ShortcutListForm(self)
|
||||
self.recentFiles = []
|
||||
# Set up the path with plugins
|
||||
plugin_path = AppLocation.get_directory(AppLocation.PluginsDir)
|
||||
self.pluginManager = PluginManager(plugin_path)
|
||||
self.pluginHelpers = {}
|
||||
self.plugin_manager = PluginManager(plugin_path)
|
||||
self.imageManager = ImageManager()
|
||||
# Set up the interface
|
||||
self.setupUi(self)
|
||||
@ -496,9 +501,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.copyData = False
|
||||
# Set up signals and slots
|
||||
QtCore.QObject.connect(self.importThemeItem, QtCore.SIGNAL(u'triggered()'),
|
||||
self.themeManagerContents.onImportTheme)
|
||||
self.themeManagerContents.on_import_theme)
|
||||
QtCore.QObject.connect(self.exportThemeItem, QtCore.SIGNAL(u'triggered()'),
|
||||
self.themeManagerContents.onExportTheme)
|
||||
self.themeManagerContents.on_export_theme)
|
||||
QtCore.QObject.connect(self.mediaManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'),
|
||||
self.viewMediaManagerItem.setChecked)
|
||||
QtCore.QObject.connect(self.serviceManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'),
|
||||
@ -527,14 +532,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_version_check'), self.versionNotice)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_display_blank_check'), self.blankCheck)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mainwindow_status_text'), self.showStatusMessage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'cleanup'), self.cleanUp)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'mainwindow_status_text'),
|
||||
self.showStatusMessage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'cleanup'), self.clean_up)
|
||||
# Media Manager
|
||||
QtCore.QObject.connect(self.mediaToolBox, QtCore.SIGNAL(u'currentChanged(int)'), self.onMediaToolBoxChanged)
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
# Simple message boxes
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_error_message'), self.onErrorMessage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_warning_message'), self.onWarningMessage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_information_message'),
|
||||
self.onInformationMessage)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'set_new_data_path'), self.setNewDataPath)
|
||||
@ -542,62 +547,58 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
# warning cyclic dependency
|
||||
# renderer needs to call ThemeManager and
|
||||
# ThemeManager needs to call Renderer
|
||||
self.renderer = Renderer(self.imageManager, self.themeManagerContents)
|
||||
self.renderer = Renderer()
|
||||
# Define the media Dock Manager
|
||||
self.mediaDockManager = MediaDockManager(self.mediaToolBox)
|
||||
log.info(u'Load Plugins')
|
||||
# make the controllers available to the plugins
|
||||
self.pluginHelpers[u'preview'] = self.previewController
|
||||
self.pluginHelpers[u'live'] = self.liveController
|
||||
self.pluginHelpers[u'renderer'] = self.renderer
|
||||
self.pluginHelpers[u'service'] = self.serviceManagerContents
|
||||
self.pluginHelpers[u'settings form'] = self.settingsForm
|
||||
self.pluginHelpers[u'toolbox'] = self.mediaDockManager
|
||||
self.pluginHelpers[u'pluginmanager'] = self.pluginManager
|
||||
self.pluginHelpers[u'formparent'] = self
|
||||
self.pluginHelpers[u'mediacontroller'] = self.mediaController
|
||||
self.pluginManager.find_plugins(plugin_path, self.pluginHelpers)
|
||||
self.plugin_manager.find_plugins(plugin_path)
|
||||
# hook methods have to happen after find_plugins. Find plugins needs
|
||||
# the controllers hence the hooks have moved from setupUI() to here
|
||||
# Find and insert settings tabs
|
||||
log.info(u'hook settings')
|
||||
self.pluginManager.hook_settings_tabs(self.settingsForm)
|
||||
self.plugin_manager.hook_settings_tabs(self.settingsForm)
|
||||
# Find and insert media manager items
|
||||
log.info(u'hook media')
|
||||
self.pluginManager.hook_media_manager()
|
||||
self.plugin_manager.hook_media_manager()
|
||||
# Call the hook method to pull in import menus.
|
||||
log.info(u'hook menus')
|
||||
self.pluginManager.hook_import_menu(self.fileImportMenu)
|
||||
self.plugin_manager.hook_import_menu(self.fileImportMenu)
|
||||
# Call the hook method to pull in export menus.
|
||||
self.pluginManager.hook_export_menu(self.fileExportMenu)
|
||||
self.plugin_manager.hook_export_menu(self.fileExportMenu)
|
||||
# Call the hook method to pull in tools menus.
|
||||
self.pluginManager.hook_tools_menu(self.toolsMenu)
|
||||
self.plugin_manager.hook_tools_menu(self.toolsMenu)
|
||||
# Call the initialise method to setup plugins.
|
||||
log.info(u'initialise plugins')
|
||||
self.pluginManager.initialise_plugins()
|
||||
self.plugin_manager.initialise_plugins()
|
||||
# Create the displays as all necessary components are loaded.
|
||||
self.previewController.screenSizeChanged()
|
||||
self.liveController.screenSizeChanged()
|
||||
log.info(u'Load data from Settings')
|
||||
if Settings().value(u'advanced/save current plugin', False):
|
||||
savedPlugin = Settings().value(u'advanced/current media plugin', -1)
|
||||
if Settings().value(u'advanced/save current plugin'):
|
||||
savedPlugin = Settings().value(u'advanced/current media plugin')
|
||||
if savedPlugin != -1:
|
||||
self.mediaToolBox.setCurrentIndex(savedPlugin)
|
||||
self.settingsForm.postSetUp()
|
||||
# Once all components are initialised load the Themes
|
||||
log.info(u'Load Themes')
|
||||
self.themeManagerContents.loadThemes(True)
|
||||
self.themeManagerContents.load_themes(True)
|
||||
# Hide/show the theme combobox on the service manager
|
||||
self.serviceManagerContents.themeChange()
|
||||
self.serviceManagerContents.theme_change()
|
||||
# Reset the cursor
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def setAutoLanguage(self, value):
|
||||
"""
|
||||
Set the language to automatic.
|
||||
"""
|
||||
self.languageGroup.setDisabled(value)
|
||||
LanguageManager.auto_language = value
|
||||
LanguageManager.set_language(self.languageGroup.checkedAction())
|
||||
|
||||
def onMediaToolBoxChanged(self, index):
|
||||
"""
|
||||
Focus a widget when the media toolbox changes.
|
||||
"""
|
||||
widget = self.mediaToolBox.widget(index)
|
||||
if widget:
|
||||
widget.onFocus()
|
||||
@ -628,11 +629,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
filename = args[0]
|
||||
if not isinstance(filename, unicode):
|
||||
filename = unicode(filename, sys.getfilesystemencoding())
|
||||
self.serviceManagerContents.loadFile(filename)
|
||||
elif Settings().value(
|
||||
self.generalSettingsSection + u'/auto open', False):
|
||||
self.serviceManagerContents.loadLastFile()
|
||||
view_mode = Settings().value(u'%s/view mode' % self.generalSettingsSection, u'default')
|
||||
self.serviceManagerContents.load_file(filename)
|
||||
elif Settings().value(self.generalSettingsSection + u'/auto open'):
|
||||
self.serviceManagerContents.load_Last_file()
|
||||
view_mode = Settings().value(u'%s/view mode' % self.generalSettingsSection)
|
||||
if view_mode == u'default':
|
||||
self.modeDefaultItem.setChecked(True)
|
||||
elif view_mode == u'setup':
|
||||
@ -642,24 +642,26 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.setViewMode(False, True, False, False, True)
|
||||
self.modeLiveItem.setChecked(True)
|
||||
|
||||
def appStartup(self):
|
||||
def app_startup(self):
|
||||
"""
|
||||
Give all the plugins a chance to perform some tasks at startup
|
||||
"""
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
for plugin in self.pluginManager.plugins:
|
||||
self.application.process_events()
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
if plugin.isActive():
|
||||
plugin.appStartup()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
plugin.app_startup()
|
||||
self.application.process_events()
|
||||
|
||||
def firstTime(self):
|
||||
# Import themes if first time
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
for plugin in self.pluginManager.plugins:
|
||||
if hasattr(plugin, u'firstTime'):
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
plugin.firstTime()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
def first_time(self):
|
||||
"""
|
||||
Import themes if first time
|
||||
"""
|
||||
self.application.process_events()
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
if hasattr(plugin, u'first_time'):
|
||||
self.application.process_events()
|
||||
plugin.first_time()
|
||||
self.application.process_events()
|
||||
temp_dir = os.path.join(unicode(gettempdir()), u'openlp')
|
||||
shutil.rmtree(temp_dir, True)
|
||||
|
||||
@ -680,29 +682,30 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
QtGui.QMessageBox.No)
|
||||
if answer == QtGui.QMessageBox.No:
|
||||
return
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
screens = ScreenList()
|
||||
firstTime = FirstTimeForm(screens, self)
|
||||
firstTime.exec_()
|
||||
if firstTime.downloadCancelled:
|
||||
first_run_wizard = FirstTimeForm(screens, self)
|
||||
first_run_wizard.exec_()
|
||||
if first_run_wizard.was_download_cancelled:
|
||||
return
|
||||
self.firstTime()
|
||||
for plugin in self.pluginManager.plugins:
|
||||
self.application.set_busy_cursor()
|
||||
self.first_time()
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
self.activePlugin = plugin
|
||||
oldStatus = self.activePlugin.status
|
||||
self.activePlugin.setStatus()
|
||||
if oldStatus != self.activePlugin.status:
|
||||
if self.activePlugin.status == PluginStatus.Active:
|
||||
self.activePlugin.toggleStatus(PluginStatus.Active)
|
||||
self.activePlugin.appStartup()
|
||||
self.activePlugin.app_startup()
|
||||
else:
|
||||
self.activePlugin.toggleStatus(PluginStatus.Inactive)
|
||||
self.themeManagerContents.configUpdated()
|
||||
self.themeManagerContents.loadThemes(True)
|
||||
self.themeManagerContents.load_themes(True)
|
||||
Receiver.send_message(u'theme_update_global', self.themeManagerContents.global_theme)
|
||||
# Check if any Bibles downloaded. If there are, they will be
|
||||
# processed.
|
||||
Receiver.send_message(u'bibles_load_list', True)
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def blankCheck(self):
|
||||
"""
|
||||
@ -710,23 +713,30 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
settings = Settings()
|
||||
self.liveController.mainDisplaySetBackground()
|
||||
if settings.value(u'%s/screen blank' % self.generalSettingsSection,
|
||||
False):
|
||||
if settings.value(u'%s/blank warning' % self.generalSettingsSection,
|
||||
False):
|
||||
if settings.value(u'%s/screen blank' % self.generalSettingsSection):
|
||||
if settings.value(u'%s/blank warning' % self.generalSettingsSection):
|
||||
QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'OpenLP Main Display Blanked'),
|
||||
translate('OpenLP.MainWindow', 'The Main Display has been blanked out'))
|
||||
|
||||
def onErrorMessage(self, data):
|
||||
Receiver.send_message(u'close_splash')
|
||||
"""
|
||||
Display an error message
|
||||
"""
|
||||
self.application.close_splash_screen()
|
||||
QtGui.QMessageBox.critical(self, data[u'title'], data[u'message'])
|
||||
|
||||
def onWarningMessage(self, data):
|
||||
Receiver.send_message(u'close_splash')
|
||||
QtGui.QMessageBox.warning(self, data[u'title'], data[u'message'])
|
||||
def warning_message(self, message):
|
||||
"""
|
||||
Display a warning message
|
||||
"""
|
||||
self.application.close_splash_screen()
|
||||
QtGui.QMessageBox.warning(self, message[u'title'], message[u'message'])
|
||||
|
||||
def onInformationMessage(self, data):
|
||||
Receiver.send_message(u'close_splash')
|
||||
"""
|
||||
Display an informational message
|
||||
"""
|
||||
self.application.close_splash_screen()
|
||||
QtGui.QMessageBox.information(self, data[u'title'], data[u'message'])
|
||||
|
||||
def onHelpWebSiteClicked(self):
|
||||
@ -773,7 +783,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
Updates the new theme preview images.
|
||||
"""
|
||||
self.themeManagerContents.updatePreviewImages()
|
||||
self.themeManagerContents.update_preview_images()
|
||||
|
||||
def onFormattingTagItemClicked(self):
|
||||
"""
|
||||
@ -830,14 +840,21 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
setting_sections.extend([self.headerSection])
|
||||
setting_sections.extend([u'crashreport'])
|
||||
# Add plugin sections.
|
||||
for plugin in self.pluginManager.plugins:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
setting_sections.extend([plugin.name])
|
||||
# Copy the settings file to the tmp dir, because we do not want to change the original one.
|
||||
temp_directory = os.path.join(unicode(gettempdir()), u'openlp')
|
||||
check_directory_exists(temp_directory)
|
||||
temp_config = os.path.join(temp_directory, os.path.basename(import_file_name))
|
||||
shutil.copyfile(import_file_name, temp_config)
|
||||
settings = Settings()
|
||||
import_settings = Settings(import_file_name, Settings.IniFormat)
|
||||
import_settings = Settings(temp_config, Settings.IniFormat)
|
||||
# Remove/rename old settings to prepare the import.
|
||||
import_settings.remove_obsolete_settings()
|
||||
# Lets do a basic sanity check. If it contains this string we can
|
||||
# assume it was created by OpenLP and so we'll load what we can
|
||||
# from it, and just silently ignore anything we don't recognise
|
||||
if import_settings.value(u'SettingsImport/type', u'') != u'OpenLP_settings_export':
|
||||
if import_settings.value(u'SettingsImport/type') != u'OpenLP_settings_export':
|
||||
QtGui.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'Import settings'),
|
||||
translate('OpenLP.MainWindow', 'The file you have selected does not appear to be a valid OpenLP '
|
||||
'settings file.\n\nProcessing has terminated and no changes have been made.'),
|
||||
@ -860,7 +877,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
continue
|
||||
# We have a good file, import it.
|
||||
for section_key in import_keys:
|
||||
value = import_settings.value(section_key, None)
|
||||
if u'eneral' in section_key:
|
||||
section_key = section_key.lower()
|
||||
value = import_settings.value(section_key)
|
||||
if value is not None:
|
||||
settings.setValue(u'%s' % (section_key), value)
|
||||
now = datetime.now()
|
||||
@ -877,7 +896,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
'be applied the next time you start OpenLP.'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
|
||||
self.settingsImported = True
|
||||
self.cleanUp()
|
||||
self.clean_up()
|
||||
QtCore.QCoreApplication.exit()
|
||||
|
||||
def onSettingsExportItemClicked(self):
|
||||
@ -891,7 +910,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
return
|
||||
# Make sure it's a .conf file.
|
||||
if not export_file_name.endswith(u'conf'):
|
||||
export_file_name = export_file_name + u'.conf'
|
||||
export_file_name += u'.conf'
|
||||
temp_file = os.path.join(unicode(gettempdir(),
|
||||
get_filesystem_encoding()), u'openlp', u'exportConf.tmp')
|
||||
self.saveSettings()
|
||||
@ -905,7 +924,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
setting_sections.extend([self.themesSettingsSection])
|
||||
setting_sections.extend([self.displayTagsSection])
|
||||
# Add plugin sections.
|
||||
for plugin in self.pluginManager.plugins:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
setting_sections.extend([plugin.name])
|
||||
# Delete old files if found.
|
||||
if os.path.exists(temp_file):
|
||||
@ -926,13 +945,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
export_settings.beginGroup(self.headerSection)
|
||||
export_settings.setValue(u'Make_Changes', u'At_Own_RISK')
|
||||
export_settings.setValue(u'type', u'OpenLP_settings_export')
|
||||
export_settings.setValue(u'file_date_created',
|
||||
now.strftime("%Y-%m-%d %H:%M"))
|
||||
export_settings.setValue(u'file_date_created', now.strftime("%Y-%m-%d %H:%M"))
|
||||
export_settings.setValue(u'version', application_version[u'full'])
|
||||
export_settings.endGroup()
|
||||
# Write all the sections and keys.
|
||||
for section_key in keys:
|
||||
key_value = settings.value(section_key, None)
|
||||
# FIXME: We are conflicting with the standard "General" section.
|
||||
if u'eneral' in section_key:
|
||||
section_key = section_key.lower()
|
||||
key_value = settings.value(section_key)
|
||||
if key_value is not None:
|
||||
export_settings.setValue(section_key, key_value)
|
||||
export_settings.sync()
|
||||
@ -949,7 +970,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
temp_conf.close()
|
||||
export_conf.close()
|
||||
os.remove(temp_file)
|
||||
return
|
||||
|
||||
def onModeDefaultItemClicked(self):
|
||||
"""
|
||||
@ -989,14 +1009,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
renderer.
|
||||
"""
|
||||
log.debug(u'screenChanged')
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.imageManager.updateDisplay()
|
||||
self.application.set_busy_cursor()
|
||||
self.imageManager.update_display()
|
||||
self.renderer.update_display()
|
||||
self.previewController.screenSizeChanged()
|
||||
self.liveController.screenSizeChanged()
|
||||
self.setFocus()
|
||||
self.activateWindow()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""
|
||||
@ -1004,59 +1024,59 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
"""
|
||||
# The MainApplication did not even enter the event loop (this happens
|
||||
# when OpenLP is not fully loaded). Just ignore the event.
|
||||
if not self.application.eventLoopIsActive:
|
||||
if not self.application.is_event_loop_active:
|
||||
event.ignore()
|
||||
return
|
||||
# If we just did a settings import, close without saving changes.
|
||||
if self.settingsImported:
|
||||
self.cleanUp(False)
|
||||
self.clean_up(False)
|
||||
event.accept()
|
||||
if self.serviceManagerContents.isModified():
|
||||
ret = self.serviceManagerContents.saveModifiedService()
|
||||
if self.serviceManagerContents.is_modified():
|
||||
ret = self.serviceManagerContents.save_modified_service()
|
||||
if ret == QtGui.QMessageBox.Save:
|
||||
if self.serviceManagerContents.decideSaveMethod():
|
||||
self.cleanUp()
|
||||
if self.serviceManagerContents.decide_save_method():
|
||||
self.clean_up()
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
elif ret == QtGui.QMessageBox.Discard:
|
||||
self.cleanUp()
|
||||
self.clean_up()
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
if Settings().value(u'advanced/enable exit confirmation', True):
|
||||
if Settings().value(u'advanced/enable exit confirmation'):
|
||||
ret = QtGui.QMessageBox.question(self, translate('OpenLP.MainWindow', 'Close OpenLP'),
|
||||
translate('OpenLP.MainWindow', 'Are you sure you want to close OpenLP?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
|
||||
QtGui.QMessageBox.Yes)
|
||||
if ret == QtGui.QMessageBox.Yes:
|
||||
self.cleanUp()
|
||||
self.clean_up()
|
||||
event.accept()
|
||||
else:
|
||||
event.ignore()
|
||||
else:
|
||||
self.cleanUp()
|
||||
self.clean_up()
|
||||
event.accept()
|
||||
|
||||
def cleanUp(self, save_settings=True):
|
||||
def clean_up(self, save_settings=True):
|
||||
"""
|
||||
Runs all the cleanup code before OpenLP shuts down.
|
||||
|
||||
``save_settings``
|
||||
Switch to prevent saving settings. Defaults to **True**.
|
||||
"""
|
||||
self.imageManager.stopManager = True
|
||||
while self.imageManager.imageThread.isRunning():
|
||||
self.imageManager.stop_manager = True
|
||||
while self.imageManager.image_thread.isRunning():
|
||||
time.sleep(0.1)
|
||||
# Clean temporary files used by services
|
||||
self.serviceManagerContents.cleanUp()
|
||||
self.serviceManagerContents.clean_up()
|
||||
if save_settings:
|
||||
if Settings().value(u'advanced/save current plugin', False):
|
||||
if Settings().value(u'advanced/save current plugin'):
|
||||
Settings().setValue(u'advanced/current media plugin', self.mediaToolBox.currentIndex())
|
||||
# Call the cleanup method to shutdown plugins.
|
||||
log.info(u'cleanup plugins')
|
||||
self.pluginManager.finalise_plugins()
|
||||
self.plugin_manager.finalise_plugins()
|
||||
if save_settings:
|
||||
# Save settings
|
||||
self.saveSettings()
|
||||
@ -1110,18 +1130,33 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.setWindowTitle(title)
|
||||
|
||||
def showStatusMessage(self, message):
|
||||
"""
|
||||
Show a message in the status bar
|
||||
"""
|
||||
self.statusBar.showMessage(message)
|
||||
|
||||
def defaultThemeChanged(self, theme):
|
||||
"""
|
||||
Update the default theme indicator in the status bar
|
||||
"""
|
||||
self.defaultThemeLabel.setText(translate('OpenLP.MainWindow', 'Default Theme: %s') % theme)
|
||||
|
||||
def toggleMediaManager(self):
|
||||
"""
|
||||
Toggle the visibility of the media manager
|
||||
"""
|
||||
self.mediaManagerDock.setVisible(not self.mediaManagerDock.isVisible())
|
||||
|
||||
def toggleServiceManager(self):
|
||||
"""
|
||||
Toggle the visibility of the service manager
|
||||
"""
|
||||
self.serviceManagerDock.setVisible(not self.serviceManagerDock.isVisible())
|
||||
|
||||
def toggleThemeManager(self):
|
||||
"""
|
||||
Toggle the visibility of the theme manager
|
||||
"""
|
||||
self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible())
|
||||
|
||||
def setPreviewPanelVisibility(self, visible):
|
||||
@ -1181,28 +1216,20 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
Load the main window settings.
|
||||
"""
|
||||
log.debug(u'Loading QSettings')
|
||||
# Migrate Wrap Settings to Slide Limits Settings
|
||||
if Settings().contains(self.generalSettingsSection + u'/enable slide loop'):
|
||||
if Settings().value(self.generalSettingsSection + u'/enable slide loop', True):
|
||||
Settings().setValue(self.advancedSettingsSection + u'/slide limits', SlideLimits.Wrap)
|
||||
else:
|
||||
Settings().setValue(self.advancedSettingsSection + u'/slide limits', SlideLimits.End)
|
||||
Settings().remove(self.generalSettingsSection + u'/enable slide loop')
|
||||
Receiver.send_message(u'slidecontroller_update_slide_limits')
|
||||
settings = Settings()
|
||||
# Remove obsolete entries.
|
||||
settings.remove(u'custom slide')
|
||||
settings.remove(u'service')
|
||||
settings.beginGroup(self.generalSettingsSection)
|
||||
self.recentFiles = settings.value(u'recent files', self.recentFiles)
|
||||
self.recentFiles = settings.value(u'recent files')
|
||||
settings.endGroup()
|
||||
settings.beginGroup(self.uiSettingsSection)
|
||||
self.move(settings.value(u'main window position', QtCore.QPoint(0, 0)))
|
||||
self.restoreGeometry(settings.value(u'main window geometry', QtCore.QByteArray()))
|
||||
self.restoreState(settings.value(u'main window state', QtCore.QByteArray()))
|
||||
self.liveController.splitter.restoreState(settings.value(u'live splitter geometry', QtCore.QByteArray()))
|
||||
self.previewController.splitter.restoreState(settings.value(u'preview splitter geometry', QtCore.QByteArray()))
|
||||
self.controlSplitter.restoreState(settings.value(u'mainwindow splitter geometry', QtCore.QByteArray()))
|
||||
self.move(settings.value(u'main window position'))
|
||||
self.restoreGeometry(settings.value(u'main window geometry'))
|
||||
self.restoreState(settings.value(u'main window state'))
|
||||
self.liveController.splitter.restoreState(settings.value(u'live splitter geometry'))
|
||||
self.previewController.splitter.restoreState(settings.value(u'preview splitter geometry'))
|
||||
self.controlSplitter.restoreState(settings.value(u'main window splitter geometry'))
|
||||
settings.endGroup()
|
||||
|
||||
def saveSettings(self):
|
||||
@ -1231,7 +1258,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
Updates the recent file menu with the latest list of service files
|
||||
accessed.
|
||||
"""
|
||||
recentFileCount = Settings().value(u'advanced/recent file count', 4)
|
||||
recentFileCount = Settings().value(u'advanced/recent file count')
|
||||
existingRecentFiles = [recentFile for recentFile in self.recentFiles
|
||||
if os.path.isfile(unicode(recentFile))]
|
||||
recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
|
||||
@ -1241,7 +1268,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
action = create_action(self, u'',
|
||||
text=u'&%d %s' % (fileId + 1, os.path.splitext(os.path.basename(
|
||||
unicode(filename)))[0]), data=filename,
|
||||
triggers=self.serviceManagerContents.onRecentServiceClicked)
|
||||
triggers=self.serviceManagerContents.on_recent_service_clicked)
|
||||
self.recentFilesMenu.addAction(action)
|
||||
clearRecentFilesAction = create_action(self, u'',
|
||||
text=translate('OpenLP.MainWindow', 'Clear List', 'Clear List of recent files'),
|
||||
@ -1261,7 +1288,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
# The maxRecentFiles value does not have an interface and so never gets
|
||||
# actually stored in the settings therefore the default value of 20 will
|
||||
# always be used.
|
||||
maxRecentFiles = Settings().value(u'advanced/max recent files', 20)
|
||||
maxRecentFiles = Settings().value(u'advanced/max recent files')
|
||||
if filename:
|
||||
# Add some cleanup to reduce duplication in the recent file list
|
||||
filename = os.path.abspath(filename)
|
||||
@ -1288,14 +1315,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
self.loadProgressBar.show()
|
||||
self.loadProgressBar.setMaximum(size)
|
||||
self.loadProgressBar.setValue(0)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def incrementProgressBar(self):
|
||||
"""
|
||||
Increase the Progress Bar value by 1
|
||||
"""
|
||||
self.loadProgressBar.setValue(self.loadProgressBar.value() + 1)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def finishedProgressBar(self):
|
||||
"""
|
||||
@ -1310,30 +1337,38 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
if event.timerId() == self.timer_id:
|
||||
self.timer_id = 0
|
||||
self.loadProgressBar.hide()
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def setNewDataPath(self, new_data_path):
|
||||
"""
|
||||
Set the new data path
|
||||
"""
|
||||
self.newDataPath = new_data_path
|
||||
|
||||
def setCopyData(self, copy_data):
|
||||
"""
|
||||
Set the flag to copy the data
|
||||
"""
|
||||
self.copyData = copy_data
|
||||
|
||||
def changeDataDirectory(self):
|
||||
"""
|
||||
Change the data directory.
|
||||
"""
|
||||
log.info(u'Changing data path to %s' % self.newDataPath)
|
||||
old_data_path = unicode(AppLocation.get_data_path())
|
||||
# Copy OpenLP data to new location if requested.
|
||||
self.application.set_busy_cursor()
|
||||
if self.copyData:
|
||||
log.info(u'Copying data to new path')
|
||||
try:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.showStatusMessage(
|
||||
translate('OpenLP.MainWindow', 'Copying OpenLP data to new data directory location - %s '
|
||||
'- Please wait for copy to finish').replace('%s', self.newDataPath))
|
||||
dir_util.copy_tree(old_data_path, self.newDataPath)
|
||||
log.info(u'Copy sucessful')
|
||||
except (IOError, os.error, DistutilsFileError), why:
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
log.exception(u'Data copy failed %s' % unicode(why))
|
||||
QtGui.QMessageBox.critical(self, translate('OpenLP.MainWindow', 'New Data Directory Error'),
|
||||
translate('OpenLP.MainWindow',
|
||||
@ -1348,3 +1383,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
|
||||
# Check if the new data path is our default.
|
||||
if self.newDataPath == AppLocation.get_directory(AppLocation.DataDir):
|
||||
settings.remove(u'advanced/data path')
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -26,6 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media` module contains classes and objects for media player integration.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Settings
|
||||
@ -34,6 +37,7 @@ from PyQt4 import QtCore
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MediaState(object):
|
||||
"""
|
||||
An enumeration for possible States of the Media Player
|
||||
@ -70,16 +74,16 @@ class MediaInfo(object):
|
||||
end_time = 0
|
||||
media_type = MediaType()
|
||||
|
||||
|
||||
def get_media_players():
|
||||
"""
|
||||
This method extracts the configured media players and overridden player
|
||||
from the settings.
|
||||
"""
|
||||
log.debug(u'get_media_players')
|
||||
saved_players = Settings().value(u'media/players', u'webkit')
|
||||
saved_players = Settings().value(u'media/players')
|
||||
reg_ex = QtCore.QRegExp(".*\[(.*)\].*")
|
||||
if Settings().value(u'media/override player',
|
||||
QtCore.Qt.Unchecked)== QtCore.Qt.Checked:
|
||||
if Settings().value(u'media/override player') == QtCore.Qt.Checked:
|
||||
if reg_ex.exactMatch(saved_players):
|
||||
overridden_player = u'%s' % reg_ex.cap(1)
|
||||
else:
|
||||
@ -103,10 +107,11 @@ def set_media_players(players_list, overridden_player=u'auto'):
|
||||
"""
|
||||
log.debug(u'set_media_players')
|
||||
players = u','.join(players_list)
|
||||
if Settings().value(u'media/override player', QtCore.Qt.Unchecked) == QtCore.Qt.Checked and \
|
||||
overridden_player != u'auto':
|
||||
if Settings().value(u'media/override player') == QtCore.Qt.Checked and overridden_player != u'auto':
|
||||
players = players.replace(overridden_player, u'[%s]' % overridden_player)
|
||||
Settings().setValue(u'media/players', players)
|
||||
|
||||
from mediacontroller import MediaController
|
||||
from playertab import PlayerTab
|
||||
|
||||
__all__ = [u'MediaController', u'PlayerTab']
|
||||
|
@ -26,22 +26,59 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.mediacontroller` module contains a base class for media components and other widgets
|
||||
related to playing media, such as sliders.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import OpenLPToolbar, Receiver, translate, Settings
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, \
|
||||
get_media_players, set_media_players
|
||||
from openlp.core.lib import OpenLPToolbar, Receiver, Settings, Registry, UiStrings, translate
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui.media import MediaState, MediaInfo, MediaType, get_media_players, set_media_players
|
||||
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
||||
from openlp.core.utils import AppLocation
|
||||
from openlp.core.ui import DisplayControllerType
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MediaSlider(QtGui.QSlider):
|
||||
"""
|
||||
Allows the mouse events of a slider to be overridden and extra functionality added
|
||||
"""
|
||||
def __init__(self, direction, manager, controller, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QSlider.__init__(self, direction)
|
||||
self.manager = manager
|
||||
self.controller = controller
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
"""
|
||||
Override event to allow hover time to be displayed.
|
||||
"""
|
||||
timevalue = QtGui.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width())
|
||||
self.setToolTip(u'%s' % datetime.timedelta(seconds=int(timevalue / 1000)))
|
||||
QtGui.QSlider.mouseMoveEvent(self, event)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
"""
|
||||
Mouse Press event no new functionality
|
||||
"""
|
||||
QtGui.QSlider.mousePressEvent(self, event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
"""
|
||||
Set the slider position when the mouse is clicked and released on the slider.
|
||||
"""
|
||||
self.setValue(QtGui.QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), event.x(), self.width()))
|
||||
QtGui.QSlider.mouseReleaseEvent(self, event)
|
||||
|
||||
|
||||
class MediaController(object):
|
||||
"""
|
||||
The implementation of the Media Controller. The Media Controller adds an own
|
||||
@ -57,7 +94,11 @@ class MediaController(object):
|
||||
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.mainWindow = parent
|
||||
Registry().register(u'media_controller', self)
|
||||
self.mediaPlayers = {}
|
||||
self.displayControllers = {}
|
||||
self.currentMediaPlayer = {}
|
||||
@ -65,12 +106,12 @@ class MediaController(object):
|
||||
self.timer = QtCore.QTimer()
|
||||
self.timer.setInterval(200)
|
||||
# Signals
|
||||
QtCore.QObject.connect(self.timer, QtCore.SIGNAL("timeout()"), self.media_state)
|
||||
self.timer.timeout.connect(self.media_state)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPlay'), self.media_play_msg)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackPause'), self.media_pause_msg)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'playbackStop'), self.media_stop_msg)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'seekSlider'), self.media_seek)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'volumeSlider'), self.media_volume)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'seekSlider'), self.media_seek_msg)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'volumeSlider'), self.media_volume_msg)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_hide'), self.media_hide)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_blank'), self.media_blank)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'media_unblank'), self.media_unblank)
|
||||
@ -100,14 +141,14 @@ class MediaController(object):
|
||||
for item in player.audio_extensions_list:
|
||||
if not item in self.audio_extensions_list:
|
||||
self.audio_extensions_list.append(item)
|
||||
self.mainWindow.serviceManagerContents.supportedSuffixes(item[2:])
|
||||
self.service_manager.supported_suffixes(item[2:])
|
||||
self.video_extensions_list = []
|
||||
for player in self.mediaPlayers.values():
|
||||
if player.isActive:
|
||||
for item in player.video_extensions_list:
|
||||
if item not in self.video_extensions_list:
|
||||
self.video_extensions_list.extend(item)
|
||||
self.mainWindow.serviceManagerContents.supportedSuffixes(item[2:])
|
||||
self.service_manager.supported_suffixes(item[2:])
|
||||
|
||||
def register_players(self, player):
|
||||
"""
|
||||
@ -241,9 +282,10 @@ class MediaController(object):
|
||||
icon=u':/slides/media_playback_stop.png',
|
||||
tooltip=translate('OpenLP.SlideController', 'Stop playing media.'), triggers=controller.sendToPlugins)
|
||||
# Build the seekSlider.
|
||||
controller.seekSlider = QtGui.QSlider(QtCore.Qt.Horizontal)
|
||||
controller.seekSlider = MediaSlider(QtCore.Qt.Horizontal, self, controller)
|
||||
controller.seekSlider.setMaximum(1000)
|
||||
controller.seekSlider.setTracking(False)
|
||||
controller.seekSlider.setTracking(True)
|
||||
controller.seekSlider.setMouseTracking(True)
|
||||
controller.seekSlider.setToolTip(translate('OpenLP.SlideController', 'Video position.'))
|
||||
controller.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24))
|
||||
controller.seekSlider.setObjectName(u'seekSlider')
|
||||
@ -266,7 +308,6 @@ class MediaController(object):
|
||||
QtCore.QObject.connect(controller.seekSlider, QtCore.SIGNAL(u'valueChanged(int)'), controller.sendToPlugins)
|
||||
QtCore.QObject.connect(controller.volumeSlider, QtCore.SIGNAL(u'valueChanged(int)'), controller.sendToPlugins)
|
||||
|
||||
|
||||
def setup_display(self, display, preview):
|
||||
"""
|
||||
After a new display is configured, all media related widget will be
|
||||
@ -344,12 +385,8 @@ class MediaController(object):
|
||||
# stop running videos
|
||||
self.media_reset(controller)
|
||||
controller.media_info = MediaInfo()
|
||||
if videoBehindText:
|
||||
controller.media_info.volume = 0
|
||||
controller.media_info.is_background = True
|
||||
else:
|
||||
controller.media_info.volume = controller.volumeSlider.value()
|
||||
controller.media_info.is_background = False
|
||||
controller.media_info.is_background = videoBehindText
|
||||
controller.media_info.file_info = QtCore.QFileInfo(serviceItem.get_frame_path())
|
||||
display = self._define_display(controller)
|
||||
if controller.isLive:
|
||||
@ -361,7 +398,7 @@ class MediaController(object):
|
||||
controller.media_info.start_time = 0
|
||||
controller.media_info.end_time = 0
|
||||
else:
|
||||
controller.media_info.start_time = display.serviceItem.start_time
|
||||
controller.media_info.start_time = serviceItem.start_time
|
||||
controller.media_info.end_time = serviceItem.end_time
|
||||
elif controller.previewDisplay:
|
||||
isValid = self._check_file_type(controller, display, serviceItem)
|
||||
@ -382,7 +419,7 @@ class MediaController(object):
|
||||
elif not hidden or controller.media_info.is_background or serviceItem.will_auto_start:
|
||||
autoplay = True
|
||||
# Unblank on load set
|
||||
elif Settings().value(u'general/auto unblank', False):
|
||||
elif Settings().value(u'general/auto unblank'):
|
||||
autoplay = True
|
||||
if autoplay:
|
||||
if not self.media_play(controller):
|
||||
@ -474,7 +511,6 @@ class MediaController(object):
|
||||
log.debug(u'media_play_msg')
|
||||
self.media_play(msg[0], status)
|
||||
|
||||
|
||||
def media_play(self, controller, status=True):
|
||||
"""
|
||||
Responds to the request to play a loaded video
|
||||
@ -483,9 +519,17 @@ class MediaController(object):
|
||||
The controller to be played
|
||||
"""
|
||||
log.debug(u'media_play')
|
||||
controller.seekSlider.blockSignals(True)
|
||||
controller.volumeSlider.blockSignals(True)
|
||||
display = self._define_display(controller)
|
||||
if not self.currentMediaPlayer[controller.controllerType].play(display):
|
||||
controller.seekSlider.blockSignals(False)
|
||||
controller.volumeSlider.blockSignals(False)
|
||||
return False
|
||||
if controller.media_info.is_background:
|
||||
self.media_volume(controller, 0)
|
||||
else:
|
||||
self.media_volume(controller, controller.media_info.volume)
|
||||
if status:
|
||||
display.frame.evaluateJavaScript(u'show_blank("desktop");')
|
||||
self.currentMediaPlayer[controller.controllerType].set_visible(display, True)
|
||||
@ -503,6 +547,8 @@ class MediaController(object):
|
||||
# Start Timer for ui updates
|
||||
if not self.timer.isActive():
|
||||
self.timer.start()
|
||||
controller.seekSlider.blockSignals(False)
|
||||
controller.volumeSlider.blockSignals(False)
|
||||
return True
|
||||
|
||||
def media_pause_msg(self, msg):
|
||||
@ -557,7 +603,7 @@ class MediaController(object):
|
||||
controller.mediabar.actions[u'playbackStop'].setVisible(False)
|
||||
controller.mediabar.actions[u'playbackPause'].setVisible(False)
|
||||
|
||||
def media_volume(self, msg):
|
||||
def media_volume_msg(self, msg):
|
||||
"""
|
||||
Changes the volume of a running video
|
||||
|
||||
@ -566,11 +612,21 @@ class MediaController(object):
|
||||
"""
|
||||
controller = msg[0]
|
||||
vol = msg[1][0]
|
||||
log.debug(u'media_volume %d' % vol)
|
||||
display = self._define_display(controller)
|
||||
self.currentMediaPlayer[controller.controllerType].volume(display, vol)
|
||||
self.media_volume(controller, vol)
|
||||
|
||||
def media_seek(self, msg):
|
||||
def media_volume(self, controller, volume):
|
||||
"""
|
||||
Changes the volume of a running video
|
||||
|
||||
``msg``
|
||||
First element is the controller which should be used
|
||||
"""
|
||||
log.debug(u'media_volume %d' % volume)
|
||||
display = self._define_display(controller)
|
||||
self.currentMediaPlayer[controller.controllerType].volume(display, volume)
|
||||
controller.volumeSlider.setValue(volume)
|
||||
|
||||
def media_seek_msg(self, msg):
|
||||
"""
|
||||
Responds to the request to change the seek Slider of a loaded video
|
||||
|
||||
@ -581,6 +637,17 @@ class MediaController(object):
|
||||
log.debug(u'media_seek')
|
||||
controller = msg[0]
|
||||
seekVal = msg[1][0]
|
||||
self.media_seek(controller, seekVal)
|
||||
|
||||
def media_seek(self, controller, seekVal):
|
||||
"""
|
||||
Responds to the request to change the seek Slider of a loaded video
|
||||
|
||||
``msg``
|
||||
First element is the controller which should be used
|
||||
Second element is a list with the seek Value as first element
|
||||
"""
|
||||
log.debug(u'media_seek')
|
||||
display = self._define_display(controller)
|
||||
self.currentMediaPlayer[controller.controllerType].seek(display, seekVal)
|
||||
|
||||
@ -610,7 +677,8 @@ class MediaController(object):
|
||||
return
|
||||
controller = self.mainWindow.liveController
|
||||
display = self._define_display(controller)
|
||||
if self.currentMediaPlayer[controller.controllerType].state == MediaState.Playing:
|
||||
if controller.controllerType in self.currentMediaPlayer and \
|
||||
self.currentMediaPlayer[controller.controllerType].state == MediaState.Playing:
|
||||
self.currentMediaPlayer[controller.controllerType].pause(display)
|
||||
self.currentMediaPlayer[controller.controllerType].set_visible(display, False)
|
||||
|
||||
@ -656,6 +724,9 @@ class MediaController(object):
|
||||
self.timer.start()
|
||||
|
||||
def finalise(self):
|
||||
"""
|
||||
Reset all the media controllers when OpenLP shuts down
|
||||
"""
|
||||
self.timer.stop()
|
||||
for controller in self.displayControllers:
|
||||
self.media_reset(self.displayControllers[controller])
|
||||
@ -670,3 +741,13 @@ class MediaController(object):
|
||||
if controller.isLive:
|
||||
return controller.display
|
||||
return controller.previewDisplay
|
||||
|
||||
def _get_service_manager(self):
|
||||
"""
|
||||
Adds the plugin manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_service_manager'):
|
||||
self._service_manager = Registry().get(u'service_manager')
|
||||
return self._service_manager
|
||||
|
||||
service_manager = property(_get_service_manager)
|
||||
|
@ -26,9 +26,13 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.mediaplayer` module contains the MediaPlayer class.
|
||||
"""
|
||||
from openlp.core.lib import Registry
|
||||
from openlp.core.ui.media import MediaState
|
||||
|
||||
|
||||
class MediaPlayer(object):
|
||||
"""
|
||||
This is the base class media Player class to provide OpenLP with a
|
||||
@ -36,6 +40,9 @@ class MediaPlayer(object):
|
||||
"""
|
||||
|
||||
def __init__(self, parent, name=u'media_player'):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.parent = parent
|
||||
self.name = name
|
||||
self.available = self.check_available()
|
||||
@ -143,3 +150,13 @@ class MediaPlayer(object):
|
||||
Returns Information about the player
|
||||
"""
|
||||
return u''
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
@ -26,15 +26,17 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.phononplayer` contains the Phonon player component.
|
||||
"""
|
||||
import logging
|
||||
import mimetypes
|
||||
from datetime import datetime
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4 import QtGui
|
||||
from PyQt4.phonon import Phonon
|
||||
|
||||
from openlp.core.lib import Receiver, translate, Settings
|
||||
from openlp.core.lib import Settings, translate
|
||||
|
||||
from openlp.core.ui.media import MediaState
|
||||
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
||||
@ -62,18 +64,19 @@ ADDITIONAL_EXT = {
|
||||
VIDEO_CSS = u"""
|
||||
#videobackboard {
|
||||
z-index:3;
|
||||
background-color: %s;
|
||||
background-color: %(bgcolor)s;
|
||||
}
|
||||
#video1 {
|
||||
background-color: %s;
|
||||
background-color: %(bgcolor)s;
|
||||
z-index:4;
|
||||
}
|
||||
#video2 {
|
||||
background-color: %s;
|
||||
background-color: %(bgcolor)s;
|
||||
z-index:4;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class PhononPlayer(MediaPlayer):
|
||||
"""
|
||||
A specialised version of the MediaPlayer class, which provides a Phonon
|
||||
@ -81,6 +84,9 @@ class PhononPlayer(MediaPlayer):
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
MediaPlayer.__init__(self, parent, u'phonon')
|
||||
self.original_name = u'Phonon'
|
||||
self.display_name = u'&Phonon'
|
||||
@ -94,13 +100,16 @@ class PhononPlayer(MediaPlayer):
|
||||
elif mimetype.startswith(u'video/'):
|
||||
self._addToList(self.video_extensions_list, mimetype)
|
||||
|
||||
def _addToList(self, list, mimetype):
|
||||
def _addToList(self, mimetype_list, mimetype):
|
||||
"""
|
||||
Add mimetypes to the provided list
|
||||
"""
|
||||
# Add all extensions which mimetypes provides us for supported types.
|
||||
extensions = mimetypes.guess_all_extensions(unicode(mimetype))
|
||||
for extension in extensions:
|
||||
ext = u'*%s' % extension
|
||||
if ext not in list:
|
||||
list.append(ext)
|
||||
if ext not in mimetype_list:
|
||||
mimetype_list.append(ext)
|
||||
log.info(u'MediaPlugin: %s extensions: %s' % (mimetype, u' '.join(extensions)))
|
||||
# Add extensions for this mimetype from self.additional_extensions.
|
||||
# This hack clears mimetypes' and operating system's shortcomings
|
||||
@ -108,12 +117,15 @@ class PhononPlayer(MediaPlayer):
|
||||
if mimetype in self.additional_extensions.keys():
|
||||
for extension in self.additional_extensions[mimetype]:
|
||||
ext = u'*%s' % extension
|
||||
if ext not in list:
|
||||
list.append(ext)
|
||||
if ext not in mimetype_list:
|
||||
mimetype_list.append(ext)
|
||||
log.info(u'MediaPlugin: %s additional extensions: %s' %
|
||||
(mimetype, u' '.join(self.additional_extensions[mimetype])))
|
||||
|
||||
def setup(self, display):
|
||||
"""
|
||||
Set up the player widgets
|
||||
"""
|
||||
display.phononWidget = Phonon.VideoWidget(display)
|
||||
display.phononWidget.resize(display.size())
|
||||
display.mediaObject = Phonon.MediaObject(display)
|
||||
@ -126,9 +138,15 @@ class PhononPlayer(MediaPlayer):
|
||||
self.hasOwnWidget = True
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
Check if the player is available
|
||||
"""
|
||||
return True
|
||||
|
||||
def load(self, display):
|
||||
"""
|
||||
Load a video into the display
|
||||
"""
|
||||
log.debug(u'load vid in Phonon Controller')
|
||||
controller = display.controller
|
||||
volume = controller.media_info.volume
|
||||
@ -150,15 +168,21 @@ class PhononPlayer(MediaPlayer):
|
||||
current_state = display.mediaObject.state()
|
||||
if current_state == Phonon.ErrorState:
|
||||
return False
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
if (datetime.now() - start).seconds > 5:
|
||||
return False
|
||||
return True
|
||||
|
||||
def resize(self, display):
|
||||
"""
|
||||
Resize the display
|
||||
"""
|
||||
display.phononWidget.resize(display.size())
|
||||
|
||||
def play(self, display):
|
||||
"""
|
||||
Play the current media item
|
||||
"""
|
||||
controller = display.controller
|
||||
start_time = 0
|
||||
if display.mediaObject.state() != Phonon.PausedState and \
|
||||
@ -177,25 +201,40 @@ class PhononPlayer(MediaPlayer):
|
||||
return True
|
||||
|
||||
def pause(self, display):
|
||||
"""
|
||||
Pause the current media item
|
||||
"""
|
||||
display.mediaObject.pause()
|
||||
if self.media_state_wait(display, Phonon.PausedState):
|
||||
self.state = MediaState.Paused
|
||||
|
||||
def stop(self, display):
|
||||
"""
|
||||
Stop the current media item
|
||||
"""
|
||||
display.mediaObject.stop()
|
||||
self.set_visible(display, False)
|
||||
self.state = MediaState.Stopped
|
||||
|
||||
def volume(self, display, vol):
|
||||
"""
|
||||
Set the volume
|
||||
"""
|
||||
# 1.0 is the highest value
|
||||
if display.hasAudio:
|
||||
vol = float(vol) / float(100)
|
||||
display.audio.setVolume(vol)
|
||||
|
||||
def seek(self, display, seekVal):
|
||||
"""
|
||||
Go to a particular point in the current media item
|
||||
"""
|
||||
display.mediaObject.seek(seekVal)
|
||||
|
||||
def reset(self, display):
|
||||
"""
|
||||
Reset the media player
|
||||
"""
|
||||
display.mediaObject.stop()
|
||||
display.mediaObject.clearQueue()
|
||||
self.set_visible(display, False)
|
||||
@ -203,10 +242,16 @@ class PhononPlayer(MediaPlayer):
|
||||
self.state = MediaState.Off
|
||||
|
||||
def set_visible(self, display, status):
|
||||
"""
|
||||
Set the visibility of the widget
|
||||
"""
|
||||
if self.hasOwnWidget:
|
||||
display.phononWidget.setVisible(status)
|
||||
|
||||
def update_ui(self, display):
|
||||
"""
|
||||
Update the UI
|
||||
"""
|
||||
if display.mediaObject.state() == Phonon.PausedState and self.state != MediaState.Paused:
|
||||
self.stop(display)
|
||||
controller = display.controller
|
||||
@ -215,17 +260,21 @@ class PhononPlayer(MediaPlayer):
|
||||
self.stop(display)
|
||||
self.set_visible(display, False)
|
||||
if not controller.seekSlider.isSliderDown():
|
||||
controller.seekSlider.setSliderPosition(
|
||||
display.mediaObject.currentTime())
|
||||
controller.seekSlider.blockSignals(True)
|
||||
controller.seekSlider.setSliderPosition(display.mediaObject.currentTime())
|
||||
controller.seekSlider.blockSignals(False)
|
||||
|
||||
def get_media_display_css(self):
|
||||
"""
|
||||
Add css style sheets to htmlbuilder
|
||||
"""
|
||||
background = QtGui.QColor(Settings().value(u'players/background color', u'#000000')).name()
|
||||
return VIDEO_CSS % (background,background,background)
|
||||
background = QtGui.QColor(Settings().value(u'players/background color')).name()
|
||||
return VIDEO_CSS % {u'bgcolor': background}
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
Return some info about this player
|
||||
"""
|
||||
return(translate('Media.player', 'Phonon is a media player which '
|
||||
'interacts with the operating system to provide media capabilities.') +
|
||||
u'<br/> <strong>' + translate('Media.player', 'Audio') +
|
||||
|
@ -26,18 +26,24 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.playertab` module holds the configuration tab for the media stuff.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver, Settings
|
||||
from openlp.core.lib.ui import UiStrings, create_button
|
||||
from openlp.core.lib import SettingsTab, Receiver, Settings, UiStrings, translate
|
||||
from openlp.core.lib.ui import create_button
|
||||
from openlp.core.ui.media import get_media_players, set_media_players
|
||||
|
||||
|
||||
class MediaQCheckBox(QtGui.QCheckBox):
|
||||
"""
|
||||
MediaQCheckBox adds an extra property, playerName to the QCheckBox class.
|
||||
"""
|
||||
def setPlayerName(self, name):
|
||||
"""
|
||||
Set the player name
|
||||
"""
|
||||
self.playerName = name
|
||||
|
||||
|
||||
@ -45,16 +51,20 @@ class PlayerTab(SettingsTab):
|
||||
"""
|
||||
MediaTab is the Media settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, parent, mainWindow):
|
||||
self.parent = parent
|
||||
self.mainWindow = mainWindow
|
||||
self.mediaPlayers = mainWindow.mediaController.mediaPlayers
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.mediaPlayers = self.media_controller.mediaPlayers
|
||||
self.savedUsedPlayers = None
|
||||
self.iconPath = u':/media/multimedia-player.png'
|
||||
player_translated = translate('OpenLP.PlayerTab', 'Players')
|
||||
SettingsTab.__init__(self, parent, u'Players', player_translated)
|
||||
|
||||
def setupUi(self):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
self.setObjectName(u'MediaTab')
|
||||
SettingsTab.setupUi(self)
|
||||
self.bgColorGroupBox = QtGui.QGroupBox(self.leftColumn)
|
||||
@ -116,6 +126,9 @@ class PlayerTab(SettingsTab):
|
||||
self.onbackgroundColorButtonClicked)
|
||||
|
||||
def retranslateUi(self):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
self.mediaPlayerGroupBox.setTitle(translate('OpenLP.PlayerTab', 'Available Media Players'))
|
||||
self.playerOrderGroupBox.setTitle(translate('OpenLP.PlayerTab', 'Player Search Order'))
|
||||
self.bgColorGroupBox.setTitle(UiStrings().BackgroundColor)
|
||||
@ -125,12 +138,18 @@ class PlayerTab(SettingsTab):
|
||||
self.retranslatePlayers()
|
||||
|
||||
def onbackgroundColorButtonClicked(self):
|
||||
"""
|
||||
Set the background color
|
||||
"""
|
||||
new_color = QtGui.QColorDialog.getColor(QtGui.QColor(self.bg_color), self)
|
||||
if new_color.isValid():
|
||||
self.bg_color = new_color.name()
|
||||
self.backgroundColorButton.setStyleSheet(u'background-color: %s' % self.bg_color)
|
||||
|
||||
def onPlayerCheckBoxChanged(self, check_state):
|
||||
"""
|
||||
Add or remove players depending on their status
|
||||
"""
|
||||
player = self.sender().playerName
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
if player not in self.usedPlayers:
|
||||
@ -141,6 +160,9 @@ class PlayerTab(SettingsTab):
|
||||
self.updatePlayerList()
|
||||
|
||||
def updatePlayerList(self):
|
||||
"""
|
||||
Update the list of media players
|
||||
"""
|
||||
self.playerOrderlistWidget.clear()
|
||||
for player in self.usedPlayers:
|
||||
if player in self.playerCheckBoxes.keys():
|
||||
@ -152,6 +174,9 @@ class PlayerTab(SettingsTab):
|
||||
self.playerOrderlistWidget.addItem(self.mediaPlayers[unicode(player)].original_name)
|
||||
|
||||
def onUpButtonClicked(self):
|
||||
"""
|
||||
Move a media player up in the order
|
||||
"""
|
||||
row = self.playerOrderlistWidget.currentRow()
|
||||
if row <= 0:
|
||||
return
|
||||
@ -161,6 +186,9 @@ class PlayerTab(SettingsTab):
|
||||
self.usedPlayers.insert(row - 1, self.usedPlayers.pop(row))
|
||||
|
||||
def onDownButtonClicked(self):
|
||||
"""
|
||||
Move a media player down in the order
|
||||
"""
|
||||
row = self.playerOrderlistWidget.currentRow()
|
||||
if row == -1 or row > self.playerOrderlistWidget.count() - 1:
|
||||
return
|
||||
@ -170,6 +198,9 @@ class PlayerTab(SettingsTab):
|
||||
self.usedPlayers.insert(row + 1, self.usedPlayers.pop(row))
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load the settings
|
||||
"""
|
||||
if self.savedUsedPlayers:
|
||||
self.usedPlayers = self.savedUsedPlayers
|
||||
self.usedPlayers = get_media_players()[0]
|
||||
@ -177,12 +208,15 @@ class PlayerTab(SettingsTab):
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.updatePlayerList()
|
||||
self.bg_color = settings.value(u'background color', u'#000000')
|
||||
self.bg_color = settings.value(u'background color')
|
||||
self.initial_color = self.bg_color
|
||||
settings.endGroup()
|
||||
self.backgroundColorButton.setStyleSheet(u'background-color: %s' % self.bg_color)
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the settings
|
||||
"""
|
||||
player_string_changed = False
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
@ -194,7 +228,7 @@ class PlayerTab(SettingsTab):
|
||||
set_media_players(self.usedPlayers, override_player)
|
||||
player_string_changed = True
|
||||
if player_string_changed:
|
||||
self.parent.resetSupportedSuffixes()
|
||||
self.service_manager.reset_supported_suffixes()
|
||||
Receiver.send_message(u'mediaitem_media_rebuild')
|
||||
Receiver.send_message(u'config_screen_changed')
|
||||
|
||||
|
4
openlp/core/ui/media/vendor/__init__.py
vendored
4
openlp/core/ui/media/vendor/__init__.py
vendored
@ -26,3 +26,7 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.vendor` module contains any scripts or libraries
|
||||
from 3rd party vendors which are required to make certain media modules work.
|
||||
"""
|
||||
|
@ -26,16 +26,18 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.vlcplayer` module contains our VLC component wrapper
|
||||
"""
|
||||
from datetime import datetime
|
||||
from distutils.version import LooseVersion
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, translate, Settings
|
||||
from openlp.core.lib import Settings, translate
|
||||
from openlp.core.ui.media import MediaState
|
||||
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
||||
|
||||
@ -99,6 +101,9 @@ class VlcPlayer(MediaPlayer):
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
MediaPlayer.__init__(self, parent, u'vlc')
|
||||
self.original_name = u'VLC'
|
||||
self.display_name = u'&VLC'
|
||||
@ -108,12 +113,16 @@ class VlcPlayer(MediaPlayer):
|
||||
self.video_extensions_list = VIDEO_EXT
|
||||
|
||||
def setup(self, display):
|
||||
"""
|
||||
Set up the media player
|
||||
"""
|
||||
display.vlcWidget = QtGui.QFrame(display)
|
||||
display.vlcWidget.setFrameStyle(QtGui.QFrame.NoFrame)
|
||||
# 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 Settings().value(u'advanced/hide mouse', True) and display.controller.isLive:
|
||||
if Settings().value(u'advanced/hide mouse') 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)
|
||||
@ -140,9 +149,15 @@ class VlcPlayer(MediaPlayer):
|
||||
self.hasOwnWidget = True
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
Return the availability of VLC
|
||||
"""
|
||||
return VLC_AVAILABLE
|
||||
|
||||
def load(self, display):
|
||||
"""
|
||||
Load a video into VLC
|
||||
"""
|
||||
log.debug(u'load vid in Vlc Controller')
|
||||
controller = display.controller
|
||||
volume = controller.media_info.volume
|
||||
@ -172,15 +187,21 @@ class VlcPlayer(MediaPlayer):
|
||||
while not mediaState == display.vlcMedia.get_state():
|
||||
if display.vlcMedia.get_state() == vlc.State.Error:
|
||||
return False
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
if (datetime.now() - start).seconds > 60:
|
||||
return False
|
||||
return True
|
||||
|
||||
def resize(self, display):
|
||||
"""
|
||||
Resize the player
|
||||
"""
|
||||
display.vlcWidget.resize(display.size())
|
||||
|
||||
def play(self, display):
|
||||
"""
|
||||
Play the current item
|
||||
"""
|
||||
controller = display.controller
|
||||
start_time = 0
|
||||
if self.state != MediaState.Paused and controller.media_info.start_time > 0:
|
||||
@ -188,6 +209,7 @@ class VlcPlayer(MediaPlayer):
|
||||
display.vlcMediaPlayer.play()
|
||||
if not self.media_state_wait(display, vlc.State.Playing):
|
||||
return False
|
||||
self.volume(display, controller.media_info.volume)
|
||||
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)
|
||||
@ -197,6 +219,9 @@ class VlcPlayer(MediaPlayer):
|
||||
return True
|
||||
|
||||
def pause(self, display):
|
||||
"""
|
||||
Pause the current item
|
||||
"""
|
||||
if display.vlcMedia.get_state() != vlc.State.Playing:
|
||||
return
|
||||
display.vlcMediaPlayer.pause()
|
||||
@ -204,27 +229,45 @@ class VlcPlayer(MediaPlayer):
|
||||
self.state = MediaState.Paused
|
||||
|
||||
def stop(self, display):
|
||||
"""
|
||||
Stop the current item
|
||||
"""
|
||||
display.vlcMediaPlayer.stop()
|
||||
self.state = MediaState.Stopped
|
||||
|
||||
def volume(self, display, vol):
|
||||
"""
|
||||
Set the volume
|
||||
"""
|
||||
if display.hasAudio:
|
||||
display.vlcMediaPlayer.audio_set_volume(vol)
|
||||
|
||||
def seek(self, display, seekVal):
|
||||
"""
|
||||
Go to a particular position
|
||||
"""
|
||||
if display.vlcMediaPlayer.is_seekable():
|
||||
display.vlcMediaPlayer.set_time(seekVal)
|
||||
|
||||
def reset(self, display):
|
||||
"""
|
||||
Reset the player
|
||||
"""
|
||||
display.vlcMediaPlayer.stop()
|
||||
display.vlcWidget.setVisible(False)
|
||||
self.state = MediaState.Off
|
||||
|
||||
def set_visible(self, display, status):
|
||||
"""
|
||||
Set the visibility
|
||||
"""
|
||||
if self.hasOwnWidget:
|
||||
display.vlcWidget.setVisible(status)
|
||||
|
||||
def update_ui(self, display):
|
||||
"""
|
||||
Update the UI
|
||||
"""
|
||||
# Stop video if playback is finished.
|
||||
if display.vlcMedia.get_state() == vlc.State.Ended:
|
||||
self.stop(display)
|
||||
@ -234,9 +277,14 @@ class VlcPlayer(MediaPlayer):
|
||||
self.stop(display)
|
||||
self.set_visible(display, False)
|
||||
if not controller.seekSlider.isSliderDown():
|
||||
controller.seekSlider.blockSignals(True)
|
||||
controller.seekSlider.setSliderPosition(display.vlcMediaPlayer.get_time())
|
||||
controller.seekSlider.blockSignals(False)
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
Return some information about this player
|
||||
"""
|
||||
return(translate('Media.player', 'VLC is an external player which '
|
||||
'supports a number of different formats.') +
|
||||
u'<br/> <strong>' + translate('Media.player', 'Audio') +
|
||||
|
@ -26,12 +26,14 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.media.webkit` module contains our WebKit video player
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import translate, Settings
|
||||
from openlp.core.lib import Settings, translate
|
||||
from openlp.core.ui.media import MediaState
|
||||
from openlp.core.ui.media.mediaplayer import MediaPlayer
|
||||
|
||||
@ -40,14 +42,14 @@ log = logging.getLogger(__name__)
|
||||
VIDEO_CSS = u"""
|
||||
#videobackboard {
|
||||
z-index:3;
|
||||
background-color: %s;
|
||||
background-color: %(bgcolor)s;
|
||||
}
|
||||
#video1 {
|
||||
background-color: %s;
|
||||
background-color: %(bgcolor)s;
|
||||
z-index:4;
|
||||
}
|
||||
#video2 {
|
||||
background-color: %s;
|
||||
background-color: %(bgcolor)s;
|
||||
z-index:4;
|
||||
}
|
||||
"""
|
||||
@ -234,32 +236,32 @@ FLASH_HTML = u"""
|
||||
"""
|
||||
|
||||
VIDEO_EXT = [
|
||||
u'*.3gp'
|
||||
, u'*.3gpp'
|
||||
, u'*.3g2'
|
||||
, u'*.3gpp2'
|
||||
, u'*.aac'
|
||||
, u'*.flv'
|
||||
, u'*.f4a'
|
||||
, u'*.f4b'
|
||||
, u'*.f4p'
|
||||
, u'*.f4v'
|
||||
, u'*.mov'
|
||||
, u'*.m4a'
|
||||
, u'*.m4b'
|
||||
, u'*.m4p'
|
||||
, u'*.m4v'
|
||||
, u'*.mkv'
|
||||
, u'*.mp4'
|
||||
, u'*.ogv'
|
||||
, u'*.webm'
|
||||
, u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi'
|
||||
, u'*.swf'
|
||||
u'*.3gp',
|
||||
u'*.3gpp',
|
||||
u'*.3g2',
|
||||
u'*.3gpp2',
|
||||
u'*.aac',
|
||||
u'*.flv',
|
||||
u'*.f4a',
|
||||
u'*.f4b',
|
||||
u'*.f4p',
|
||||
u'*.f4v',
|
||||
u'*.mov',
|
||||
u'*.m4a',
|
||||
u'*.m4b',
|
||||
u'*.m4p',
|
||||
u'*.m4v',
|
||||
u'*.mkv',
|
||||
u'*.mp4',
|
||||
u'*.ogv',
|
||||
u'*.webm',
|
||||
u'*.mpg', u'*.wmv', u'*.mpeg', u'*.avi',
|
||||
u'*.swf'
|
||||
]
|
||||
|
||||
AUDIO_EXT = [
|
||||
u'*.mp3'
|
||||
, u'*.ogg'
|
||||
u'*.mp3',
|
||||
u'*.ogg'
|
||||
]
|
||||
|
||||
|
||||
@ -270,6 +272,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
"""
|
||||
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
MediaPlayer.__init__(self, parent, u'webkit')
|
||||
self.original_name = u'WebKit'
|
||||
self.display_name = u'&WebKit'
|
||||
@ -282,8 +287,8 @@ class WebkitPlayer(MediaPlayer):
|
||||
"""
|
||||
Add css style sheets to htmlbuilder
|
||||
"""
|
||||
background = QtGui.QColor(Settings().value(u'players/background color', u'#000000')).name()
|
||||
css = VIDEO_CSS % (background,background,background)
|
||||
background = QtGui.QColor(Settings().value(u'players/background color')).name()
|
||||
css = VIDEO_CSS % {u'bgcolor': background}
|
||||
return css + FLASH_CSS
|
||||
|
||||
def get_media_display_javascript(self):
|
||||
@ -299,14 +304,23 @@ class WebkitPlayer(MediaPlayer):
|
||||
return VIDEO_HTML + FLASH_HTML
|
||||
|
||||
def setup(self, display):
|
||||
"""
|
||||
Set up the player
|
||||
"""
|
||||
display.webView.resize(display.size())
|
||||
display.webView.raise_()
|
||||
self.hasOwnWidget = False
|
||||
|
||||
def check_available(self):
|
||||
"""
|
||||
Check the availability of the media player
|
||||
"""
|
||||
return True
|
||||
|
||||
def load(self, display):
|
||||
"""
|
||||
Load a video
|
||||
"""
|
||||
log.debug(u'load vid in Webkit Controller')
|
||||
controller = display.controller
|
||||
if display.hasAudio and not controller.media_info.is_background:
|
||||
@ -329,9 +343,15 @@ class WebkitPlayer(MediaPlayer):
|
||||
return True
|
||||
|
||||
def resize(self, display):
|
||||
"""
|
||||
Resize the player
|
||||
"""
|
||||
display.webView.resize(display.size())
|
||||
|
||||
def play(self, display):
|
||||
"""
|
||||
Play a video
|
||||
"""
|
||||
controller = display.controller
|
||||
display.webLoaded = True
|
||||
length = 0
|
||||
@ -352,6 +372,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
return True
|
||||
|
||||
def pause(self, display):
|
||||
"""
|
||||
Pause a video
|
||||
"""
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
display.frame.evaluateJavaScript(u'show_flash("pause");')
|
||||
@ -360,6 +383,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
self.state = MediaState.Paused
|
||||
|
||||
def stop(self, display):
|
||||
"""
|
||||
Stop a video
|
||||
"""
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
display.frame.evaluateJavaScript(u'show_flash("stop");')
|
||||
@ -368,6 +394,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
self.state = MediaState.Stopped
|
||||
|
||||
def volume(self, display, vol):
|
||||
"""
|
||||
Set the volume
|
||||
"""
|
||||
controller = display.controller
|
||||
# 1.0 is the highest value
|
||||
if display.hasAudio:
|
||||
@ -376,6 +405,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
display.frame.evaluateJavaScript(u'show_video(null, null, %s);' % str(vol))
|
||||
|
||||
def seek(self, display, seekVal):
|
||||
"""
|
||||
Go to a position in the video
|
||||
"""
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
seek = seekVal
|
||||
@ -385,6 +417,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
display.frame.evaluateJavaScript(u'show_video("seek", null, null, null, "%f");' % (seek))
|
||||
|
||||
def reset(self, display):
|
||||
"""
|
||||
Reset the player
|
||||
"""
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
display.frame.evaluateJavaScript(u'show_flash("close");')
|
||||
@ -393,6 +428,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
self.state = MediaState.Off
|
||||
|
||||
def set_visible(self, display, status):
|
||||
"""
|
||||
Set the visibility
|
||||
"""
|
||||
controller = display.controller
|
||||
if status:
|
||||
is_visible = "visible"
|
||||
@ -404,6 +442,9 @@ class WebkitPlayer(MediaPlayer):
|
||||
display.frame.evaluateJavaScript(u'show_video("setVisible", null, null, null, "%s");' % (is_visible))
|
||||
|
||||
def update_ui(self, display):
|
||||
"""
|
||||
Update the UI
|
||||
"""
|
||||
controller = display.controller
|
||||
if controller.media_info.is_flash:
|
||||
currentTime = display.frame.evaluateJavaScript(u'show_flash("currentTime");')
|
||||
@ -411,21 +452,26 @@ class WebkitPlayer(MediaPlayer):
|
||||
else:
|
||||
if display.frame.evaluateJavaScript(u'show_video("isEnded");') == 'true':
|
||||
self.stop(display)
|
||||
(currentTime, ok) = display.frame.evaluateJavaScript(u'show_video("currentTime");')
|
||||
currentTime = display.frame.evaluateJavaScript(u'show_video("currentTime");')
|
||||
# check if conversion was ok and value is not 'NaN'
|
||||
if ok and currentTime != float('inf'):
|
||||
if currentTime and currentTime != float('inf'):
|
||||
currentTime = int(currentTime * 1000)
|
||||
(length, ok) = display.frame.evaluateJavaScript(u'show_video("length");')
|
||||
length = display.frame.evaluateJavaScript(u'show_video("length");')
|
||||
# check if conversion was ok and value is not 'NaN'
|
||||
if ok and length != float('inf'):
|
||||
if length and length != float('inf'):
|
||||
length = int(length * 1000)
|
||||
if currentTime > 0:
|
||||
controller.media_info.length = length
|
||||
controller.seekSlider.setMaximum(length)
|
||||
if not controller.seekSlider.isSliderDown():
|
||||
controller.seekSlider.blockSignals(True)
|
||||
controller.seekSlider.setSliderPosition(currentTime)
|
||||
controller.seekSlider.blockSignals(False)
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
Return some information about this player
|
||||
"""
|
||||
return(translate('Media.player', 'Webkit is a media player which runs '
|
||||
'inside a web browser. This player allows text over video to be '
|
||||
'rendered.') +
|
||||
|
@ -26,13 +26,16 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The media manager dock.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import StringContent
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MediaDockManager(object):
|
||||
"""
|
||||
Provide a repository for MediaManagerItems
|
||||
|
@ -26,14 +26,23 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets of the plugin view dialog
|
||||
#"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import UiStrings, create_button_box
|
||||
from openlp.core.lib import UiStrings, translate
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_PluginViewDialog(object):
|
||||
"""
|
||||
The UI of the plugin view dialog
|
||||
"""
|
||||
def setupUi(self, pluginViewDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
pluginViewDialog.setObjectName(u'pluginViewDialog')
|
||||
pluginViewDialog.setWindowModality(QtCore.Qt.ApplicationModal)
|
||||
self.pluginLayout = QtGui.QVBoxLayout(pluginViewDialog)
|
||||
@ -66,11 +75,14 @@ class Ui_PluginViewDialog(object):
|
||||
self.pluginInfoLayout.addRow(self.aboutLabel, self.aboutTextBrowser)
|
||||
self.listLayout.addWidget(self.pluginInfoGroupBox)
|
||||
self.pluginLayout.addLayout(self.listLayout)
|
||||
self.buttonBox = create_button_box(pluginViewDialog, u'buttonBox', [u'ok'])
|
||||
self.pluginLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(pluginViewDialog, u'button_box', [u'ok'])
|
||||
self.pluginLayout.addWidget(self.button_box)
|
||||
self.retranslateUi(pluginViewDialog)
|
||||
|
||||
def retranslateUi(self, pluginViewDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
pluginViewDialog.setWindowTitle(translate('OpenLP.PluginForm', 'Plugin List'))
|
||||
self.pluginInfoGroupBox.setTitle(translate('OpenLP.PluginForm', 'Plugin Details'))
|
||||
self.versionLabel.setText(u'%s:' % UiStrings().Version)
|
||||
|
@ -26,21 +26,27 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The actual plugin view form
|
||||
"""
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import PluginStatus, Receiver, translate
|
||||
from openlp.core.lib import PluginStatus, Registry, translate
|
||||
from plugindialog import Ui_PluginViewDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
"""
|
||||
The plugin form provides user control over the plugins OpenLP uses.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.activePlugin = None
|
||||
self.programaticChange = False
|
||||
@ -62,7 +68,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
self._clearDetails()
|
||||
self.programaticChange = True
|
||||
pluginListWidth = 0
|
||||
for plugin in self.parent().pluginManager.plugins:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
item = QtGui.QListWidgetItem(self.pluginListWidget)
|
||||
# We do this just to make 100% sure the status is an integer as
|
||||
# sometimes when it's loaded from the config, it isn't cast to int.
|
||||
@ -85,12 +91,18 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
self.pluginListWidget.setFixedWidth(pluginListWidth + self.pluginListWidget.iconSize().width() + 48)
|
||||
|
||||
def _clearDetails(self):
|
||||
"""
|
||||
Clear the plugin details widgets
|
||||
"""
|
||||
self.statusComboBox.setCurrentIndex(-1)
|
||||
self.versionNumberLabel.setText(u'')
|
||||
self.aboutTextBrowser.setHtml(u'')
|
||||
self.statusComboBox.setEnabled(False)
|
||||
|
||||
def _setDetails(self):
|
||||
"""
|
||||
Set the details of the currently selected plugin
|
||||
"""
|
||||
log.debug(u'PluginStatus: %s', str(self.activePlugin.status))
|
||||
self.versionNumberLabel.setText(self.activePlugin.version)
|
||||
self.aboutTextBrowser.setHtml(self.activePlugin.about())
|
||||
@ -103,13 +115,15 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
self.programaticChange = False
|
||||
|
||||
def onPluginListWidgetSelectionChanged(self):
|
||||
"""
|
||||
If the selected plugin changes, update the form
|
||||
"""
|
||||
if self.pluginListWidget.currentItem() is None:
|
||||
self._clearDetails()
|
||||
return
|
||||
plugin_name_singular = \
|
||||
self.pluginListWidget.currentItem().text().split(u'(')[0][:-1]
|
||||
plugin_name_singular = self.pluginListWidget.currentItem().text().split(u'(')[0][:-1]
|
||||
self.activePlugin = None
|
||||
for plugin in self.parent().pluginManager.plugins:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
if plugin.status != PluginStatus.Disabled:
|
||||
if plugin.nameStrings[u'singular'] == plugin_name_singular:
|
||||
self.activePlugin = plugin
|
||||
@ -120,13 +134,16 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
self._clearDetails()
|
||||
|
||||
def onStatusComboBoxChanged(self, status):
|
||||
"""
|
||||
If the status of a plugin is altered, apply the change
|
||||
"""
|
||||
if self.programaticChange or status == PluginStatus.Disabled:
|
||||
return
|
||||
if status == PluginStatus.Inactive:
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
self.activePlugin.toggleStatus(PluginStatus.Active)
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.activePlugin.appStartup()
|
||||
self.application.set_normal_cursor()
|
||||
self.activePlugin.app_startup()
|
||||
else:
|
||||
self.activePlugin.toggleStatus(PluginStatus.Inactive)
|
||||
status_text = translate('OpenLP.PluginForm', '%s (Inactive)')
|
||||
@ -138,3 +155,23 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
status_text = translate('OpenLP.PluginForm', '%s (Disabled)')
|
||||
self.pluginListWidget.currentItem().setText(
|
||||
status_text % self.activePlugin.nameStrings[u'singular'])
|
||||
|
||||
def _get_plugin_manager(self):
|
||||
"""
|
||||
Adds the plugin manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_plugin_manager'):
|
||||
self._plugin_manager = Registry().get(u'plugin_manager')
|
||||
return self._plugin_manager
|
||||
|
||||
plugin_manager = property(_get_plugin_manager)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -26,11 +26,13 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets of the print service dialog.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import build_icon, translate, SpellTextEdit
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib import SpellTextEdit, UiStrings, build_icon, translate
|
||||
|
||||
|
||||
class ZoomSize(object):
|
||||
"""
|
||||
@ -45,7 +47,13 @@ class ZoomSize(object):
|
||||
|
||||
|
||||
class Ui_PrintServiceDialog(object):
|
||||
"""
|
||||
The UI of the print service dialog
|
||||
"""
|
||||
def setupUi(self, printServiceDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
printServiceDialog.setObjectName(u'printServiceDialog')
|
||||
printServiceDialog.resize(664, 594)
|
||||
self.mainLayout = QtGui.QVBoxLayout(printServiceDialog)
|
||||
@ -125,6 +133,9 @@ class Ui_PrintServiceDialog(object):
|
||||
QtCore.QObject.connect(self.optionsButton, QtCore.SIGNAL(u'toggled(bool)'), self.toggleOptions)
|
||||
|
||||
def retranslateUi(self, printServiceDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
printServiceDialog.setWindowTitle(UiStrings().PrintService)
|
||||
self.zoomOutButton.setToolTip(translate('OpenLP.PrintServiceForm', 'Zoom Out'))
|
||||
self.zoomOriginalButton.setToolTip(translate('OpenLP.PrintServiceForm', 'Zoom Original'))
|
||||
@ -145,6 +156,5 @@ class Ui_PrintServiceDialog(object):
|
||||
u'100%',
|
||||
u'75%',
|
||||
u'50%',
|
||||
u'25%']
|
||||
)
|
||||
|
||||
u'25%'
|
||||
])
|
||||
|
@ -26,6 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The actual print service dialog
|
||||
"""
|
||||
import cgi
|
||||
import datetime
|
||||
import os
|
||||
@ -33,8 +36,7 @@ import os
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from lxml import html
|
||||
|
||||
from openlp.core.lib import translate, get_text_file_string, Receiver, Settings
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.core.lib import Receiver, Settings, UiStrings, Registry, translate, get_text_file_string
|
||||
from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
|
||||
from openlp.core.utils import AppLocation
|
||||
|
||||
@ -107,15 +109,16 @@ http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties
|
||||
}
|
||||
"""
|
||||
|
||||
class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
|
||||
def __init__(self, mainWindow, serviceManager):
|
||||
class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
"""
|
||||
The :class:`~openlp.core.ui.printserviceform.PrintServiceForm` class displays a dialog for printing the service.
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, mainWindow)
|
||||
self.mainWindow = mainWindow
|
||||
self.serviceManager = serviceManager
|
||||
QtGui.QDialog.__init__(self, self.main_window)
|
||||
self.printer = QtGui.QPrinter()
|
||||
self.printDialog = QtGui.QPrintDialog(self.printer, self)
|
||||
self.document = QtGui.QTextDocument()
|
||||
@ -124,13 +127,13 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
# Load the settings for the dialog.
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'advanced')
|
||||
self.slideTextCheckBox.setChecked(settings.value(u'print slide text', False))
|
||||
self.pageBreakAfterText.setChecked(settings.value(u'add page break', False))
|
||||
self.slideTextCheckBox.setChecked(settings.value(u'print slide text'))
|
||||
self.pageBreakAfterText.setChecked(settings.value(u'add page break'))
|
||||
if not self.slideTextCheckBox.isChecked():
|
||||
self.pageBreakAfterText.setDisabled(True)
|
||||
self.metaDataCheckBox.setChecked(settings.value(u'print file meta data', False))
|
||||
self.notesCheckBox.setChecked(settings.value(u'print notes', False))
|
||||
self.zoomComboBox.setCurrentIndex(settings.value(u'display size', 0))
|
||||
self.metaDataCheckBox.setChecked(settings.value(u'print file meta data'))
|
||||
self.notesCheckBox.setChecked(settings.value(u'print notes'))
|
||||
self.zoomComboBox.setCurrentIndex(settings.value(u'display size'))
|
||||
settings.endGroup()
|
||||
# Signals
|
||||
QtCore.QObject.connect(self.printButton, QtCore.SIGNAL(u'triggered()'), self.printServiceOrder)
|
||||
@ -141,10 +144,14 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
QtCore.QObject.connect(self.zoomComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.displaySizeChanged)
|
||||
QtCore.QObject.connect(self.plainCopy, QtCore.SIGNAL(u'triggered()'), self.copyText)
|
||||
QtCore.QObject.connect(self.htmlCopy, QtCore.SIGNAL(u'triggered()'), self.copyHtmlText)
|
||||
QtCore.QObject.connect(self.slideTextCheckBox, QtCore.SIGNAL(u'stateChanged(int)'), self.onSlideTextCheckBoxChanged)
|
||||
QtCore.QObject.connect(self.slideTextCheckBox, QtCore.SIGNAL(u'stateChanged(int)'),
|
||||
self.onSlideTextCheckBoxChanged)
|
||||
self.updatePreviewText()
|
||||
|
||||
def toggleOptions(self, checked):
|
||||
"""
|
||||
Toggle various options
|
||||
"""
|
||||
self.optionsWidget.setVisible(checked)
|
||||
if checked:
|
||||
left = self.optionsButton.pos().x()
|
||||
@ -171,7 +178,7 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
self._addElement(u'body', parent=html_data)
|
||||
self._addElement(u'h1', cgi.escape(self.titleLineEdit.text()),
|
||||
html_data.body, classId=u'serviceTitle')
|
||||
for index, item in enumerate(self.serviceManager.serviceItems):
|
||||
for index, item in enumerate(self.service_manager.service_items):
|
||||
self._addPreviewItem(html_data.body, item[u'service_item'], index)
|
||||
# Add the custom service notes:
|
||||
if self.footerTextEdit.toPlainText():
|
||||
@ -183,6 +190,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
self.previewWidget.updatePreview()
|
||||
|
||||
def _addPreviewItem(self, body, item, index):
|
||||
"""
|
||||
Add a preview item
|
||||
"""
|
||||
div = self._addElement(u'div', classId=u'item', parent=body)
|
||||
# Add the title of the service item.
|
||||
item_title = self._addElement(u'h2', parent=div, classId=u'itemTitle')
|
||||
@ -320,14 +330,14 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
# remove the icon from the text
|
||||
clipboard_text = clipboard_text.replace(u'\ufffc\xa0', u'')
|
||||
# and put it all on the clipboard
|
||||
self.mainWindow.clipboard.setText(clipboard_text)
|
||||
self.main_window.clipboard.setText(clipboard_text)
|
||||
|
||||
def copyHtmlText(self):
|
||||
"""
|
||||
Copies the display text to the clipboard as Html
|
||||
"""
|
||||
self.update_song_usage()
|
||||
self.mainWindow.clipboard.setText(self.document.toHtml())
|
||||
self.main_window.clipboard.setText(self.document.toHtml())
|
||||
|
||||
def printServiceOrder(self):
|
||||
"""
|
||||
@ -390,9 +400,32 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
|
||||
settings.endGroup()
|
||||
|
||||
def update_song_usage(self):
|
||||
"""
|
||||
Update the song usage
|
||||
"""
|
||||
# Only continue when we include the song's text.
|
||||
if not self.slideTextCheckBox.isChecked():
|
||||
return
|
||||
for item in self.serviceManager.serviceItems:
|
||||
for item in self.service_manager.serviceItems:
|
||||
# Trigger Audit requests
|
||||
Receiver.send_message(u'print_service_started', [item[u'service_item']])
|
||||
|
||||
def _get_service_manager(self):
|
||||
"""
|
||||
Adds the service manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_service_manager'):
|
||||
self._service_manager = Registry().get(u'service_manager')
|
||||
return self._service_manager
|
||||
|
||||
service_manager = property(_get_service_manager)
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
@ -26,39 +26,51 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets for the service item edit dialog
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import create_button_box, create_button
|
||||
|
||||
|
||||
class Ui_ServiceItemEditDialog(object):
|
||||
"""
|
||||
The UI widgets for the service item edit dialog
|
||||
"""
|
||||
def setupUi(self, serviceItemEditDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
serviceItemEditDialog.setObjectName(u'serviceItemEditDialog')
|
||||
self.dialogLayout = QtGui.QGridLayout(serviceItemEditDialog)
|
||||
self.dialogLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dialogLayout.setSpacing(8)
|
||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||
self.listWidget = QtGui.QListWidget(serviceItemEditDialog)
|
||||
self.listWidget.setAlternatingRowColors(True)
|
||||
self.listWidget.setObjectName(u'listWidget')
|
||||
self.dialogLayout.addWidget(self.listWidget, 0, 0)
|
||||
self.buttonLayout = QtGui.QVBoxLayout()
|
||||
self.buttonLayout.setObjectName(u'buttonLayout')
|
||||
self.deleteButton = create_button(serviceItemEditDialog, u'deleteButton', role=u'delete',
|
||||
click=serviceItemEditDialog.onDeleteButtonClicked)
|
||||
self.buttonLayout.addWidget(self.deleteButton)
|
||||
self.buttonLayout.addStretch()
|
||||
self.upButton = create_button(serviceItemEditDialog, u'upButton', role=u'up',
|
||||
click=serviceItemEditDialog.onUpButtonClicked)
|
||||
self.downButton = create_button(serviceItemEditDialog, u'downButton', role=u'down',
|
||||
click=serviceItemEditDialog.onDownButtonClicked)
|
||||
self.buttonLayout.addWidget(self.upButton)
|
||||
self.buttonLayout.addWidget(self.downButton)
|
||||
self.dialogLayout.addLayout(self.buttonLayout, 0, 1)
|
||||
self.buttonBox = create_button_box(serviceItemEditDialog, u'buttonBox', [u'cancel', u'save'])
|
||||
self.dialogLayout.addWidget(self.buttonBox, 1, 0, 1, 2)
|
||||
self.dialog_layout = QtGui.QGridLayout(serviceItemEditDialog)
|
||||
self.dialog_layout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dialog_layout.setSpacing(8)
|
||||
self.dialog_layout.setObjectName(u'dialog_layout')
|
||||
self.list_widget = QtGui.QListWidget(serviceItemEditDialog)
|
||||
self.list_widget.setAlternatingRowColors(True)
|
||||
self.list_widget.setObjectName(u'list_widget')
|
||||
self.dialog_layout.addWidget(self.list_widget, 0, 0)
|
||||
self.button_layout = QtGui.QVBoxLayout()
|
||||
self.button_layout.setObjectName(u'button_layout')
|
||||
self.delete_button = create_button(serviceItemEditDialog, u'deleteButton', role=u'delete',
|
||||
click=serviceItemEditDialog.on_delete_button_clicked)
|
||||
self.button_layout.addWidget(self.delete_button)
|
||||
self.button_layout.addStretch()
|
||||
self.up_button = create_button(serviceItemEditDialog, u'upButton', role=u'up',
|
||||
click=serviceItemEditDialog.on_up_button_clicked)
|
||||
self.down_button = create_button(serviceItemEditDialog, u'downButton', role=u'down',
|
||||
click=serviceItemEditDialog.on_down_button_clicked)
|
||||
self.button_layout.addWidget(self.up_button)
|
||||
self.button_layout.addWidget(self.down_button)
|
||||
self.dialog_layout.addLayout(self.button_layout, 0, 1)
|
||||
self.button_box = create_button_box(serviceItemEditDialog, u'button_box', [u'cancel', u'save'])
|
||||
self.dialog_layout.addWidget(self.button_box, 1, 0, 1, 2)
|
||||
self.retranslateUi(serviceItemEditDialog)
|
||||
|
||||
def retranslateUi(self, serviceItemEditDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
serviceItemEditDialog.setWindowTitle(translate('OpenLP.ServiceItemEditForm', 'Reorder Service Item'))
|
||||
|
@ -26,100 +26,111 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The service item edit dialog
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import Registry
|
||||
|
||||
from serviceitemeditdialog import Ui_ServiceItemEditDialog
|
||||
|
||||
|
||||
class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
||||
"""
|
||||
This is the form that is used to edit the verses of the song.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
QtGui.QDialog.__init__(self, self.main_window)
|
||||
self.setupUi(self)
|
||||
self.itemList = []
|
||||
QtCore.QObject.connect(self.listWidget, QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
|
||||
self.item_list = []
|
||||
QtCore.QObject.connect(self.list_widget, QtCore.SIGNAL(u'currentRowChanged(int)'),
|
||||
self.on_current_row_changed)
|
||||
|
||||
def setServiceItem(self, item):
|
||||
def set_service_item(self, item):
|
||||
"""
|
||||
Set the service item to be edited.
|
||||
"""
|
||||
self.item = item
|
||||
self.itemList = []
|
||||
self.item_list = []
|
||||
if self.item.is_image():
|
||||
self.data = True
|
||||
for frame in self.item._raw_frames:
|
||||
self.itemList.append(frame)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentItem(self.listWidget.currentItem())
|
||||
self.item_list.append(frame)
|
||||
self.load_data()
|
||||
self.list_widget.setCurrentItem(self.list_widget.currentItem())
|
||||
|
||||
def getServiceItem(self):
|
||||
def get_service_item(self):
|
||||
"""
|
||||
Get the modified service item.
|
||||
"""
|
||||
if self.data:
|
||||
self.item._raw_frames = []
|
||||
if self.item.is_image():
|
||||
for item in self.itemList:
|
||||
for item in self.item_list:
|
||||
self.item.add_from_image(item[u'path'], item[u'title'])
|
||||
self.item.render()
|
||||
return self.item
|
||||
|
||||
def loadData(self):
|
||||
def load_data(self):
|
||||
"""
|
||||
Loads the image list.
|
||||
"""
|
||||
self.listWidget.clear()
|
||||
for frame in self.itemList:
|
||||
self.list_widget.clear()
|
||||
for frame in self.item_list:
|
||||
item_name = QtGui.QListWidgetItem(frame[u'title'])
|
||||
self.listWidget.addItem(item_name)
|
||||
self.list_widget.addItem(item_name)
|
||||
|
||||
def onDeleteButtonClicked(self):
|
||||
def on_delete_button_clicked(self):
|
||||
"""
|
||||
Delete the current row.
|
||||
"""
|
||||
item = self.listWidget.currentItem()
|
||||
item = self.list_widget.currentItem()
|
||||
if not item:
|
||||
return
|
||||
row = self.listWidget.row(item)
|
||||
self.itemList.pop(row)
|
||||
self.loadData()
|
||||
if row == self.listWidget.count():
|
||||
self.listWidget.setCurrentRow(row - 1)
|
||||
row = self.list_widget.row(item)
|
||||
self.item_list.pop(row)
|
||||
self.load_data()
|
||||
if row == self.list_widget.count():
|
||||
self.list_widget.setCurrentRow(row - 1)
|
||||
else:
|
||||
self.listWidget.setCurrentRow(row)
|
||||
self.list_widget.setCurrentRow(row)
|
||||
|
||||
def onUpButtonClicked(self):
|
||||
def on_up_button_clicked(self):
|
||||
"""
|
||||
Move the current row up in the list.
|
||||
"""
|
||||
self.__moveItem(u'up')
|
||||
self.__move_item(u'up')
|
||||
|
||||
def onDownButtonClicked(self):
|
||||
def on_down_button_clicked(self):
|
||||
"""
|
||||
Move the current row down in the list
|
||||
"""
|
||||
self.__moveItem(u'down')
|
||||
self.__move_item(u'down')
|
||||
|
||||
def __moveItem(self, direction=u''):
|
||||
def __move_item(self, direction=u''):
|
||||
"""
|
||||
Move the current item.
|
||||
"""
|
||||
if not direction:
|
||||
return
|
||||
item = self.listWidget.currentItem()
|
||||
item = self.list_widget.currentItem()
|
||||
if not item:
|
||||
return
|
||||
row = self.listWidget.row(item)
|
||||
temp = self.itemList[row]
|
||||
self.itemList.pop(row)
|
||||
row = self.list_widget.row(item)
|
||||
temp = self.item_list[row]
|
||||
self.item_list.pop(row)
|
||||
if direction == u'up':
|
||||
row -= 1
|
||||
else:
|
||||
row += 1
|
||||
self.itemList.insert(row, temp)
|
||||
self.loadData()
|
||||
self.listWidget.setCurrentRow(row)
|
||||
self.item_list.insert(row, temp)
|
||||
self.load_data()
|
||||
self.list_widget.setCurrentRow(row)
|
||||
|
||||
def onCurrentRowChanged(self, row):
|
||||
def on_current_row_changed(self, row):
|
||||
"""
|
||||
Called when the currentRow has changed.
|
||||
|
||||
@ -127,19 +138,29 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
|
||||
The row number (int).
|
||||
"""
|
||||
# Disable all buttons, as no row is selected or only one image is left.
|
||||
if row == -1 or self.listWidget.count() == 1:
|
||||
self.downButton.setEnabled(False)
|
||||
self.upButton.setEnabled(False)
|
||||
self.deleteButton.setEnabled(False)
|
||||
if row == -1 or self.list_widget.count() == 1:
|
||||
self.down_button.setEnabled(False)
|
||||
self.up_button.setEnabled(False)
|
||||
self.delete_button.setEnabled(False)
|
||||
else:
|
||||
# Check if we are at the end of the list.
|
||||
if self.listWidget.count() == row + 1:
|
||||
self.downButton.setEnabled(False)
|
||||
if self.list_widget.count() == row + 1:
|
||||
self.down_button.setEnabled(False)
|
||||
else:
|
||||
self.downButton.setEnabled(True)
|
||||
self.down_button.setEnabled(True)
|
||||
# Check if we are at the beginning of the list.
|
||||
if row == 0:
|
||||
self.upButton.setEnabled(False)
|
||||
self.up_button.setEnabled(False)
|
||||
else:
|
||||
self.upButton.setEnabled(True)
|
||||
self.deleteButton.setEnabled(True)
|
||||
self.up_button.setEnabled(True)
|
||||
self.delete_button.setEnabled(True)
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
File diff suppressed because it is too large
Load Diff
@ -26,39 +26,61 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.servicenoteform` module contains the `ServiceNoteForm` class.
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import translate, SpellTextEdit
|
||||
from openlp.core.lib import SpellTextEdit, Registry, translate
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class ServiceNoteForm(QtGui.QDialog):
|
||||
"""
|
||||
This is the form that is used to edit the verses of the song.
|
||||
"""
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
QtGui.QDialog.__init__(self, self.main_window)
|
||||
self.setupUi()
|
||||
self.retranslateUi()
|
||||
|
||||
def exec_(self):
|
||||
self.textEdit.setFocus()
|
||||
"""
|
||||
Execute the form and return the result.
|
||||
"""
|
||||
self.text_edit.setFocus()
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def setupUi(self):
|
||||
"""
|
||||
Set up the UI of the dialog
|
||||
"""
|
||||
self.setObjectName(u'serviceNoteEdit')
|
||||
self.dialogLayout = QtGui.QVBoxLayout(self)
|
||||
self.dialogLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dialogLayout.setSpacing(8)
|
||||
self.dialogLayout.setObjectName(u'verticalLayout')
|
||||
self.textEdit = SpellTextEdit(self, False)
|
||||
self.textEdit.setObjectName(u'textEdit')
|
||||
self.dialogLayout.addWidget(self.textEdit)
|
||||
self.buttonBox = create_button_box(self, u'buttonBox', [u'cancel', u'save'])
|
||||
self.dialogLayout.addWidget(self.buttonBox)
|
||||
self.dialog_layout = QtGui.QVBoxLayout(self)
|
||||
self.dialog_layout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dialog_layout.setSpacing(8)
|
||||
self.dialog_layout.setObjectName(u'verticalLayout')
|
||||
self.text_edit = SpellTextEdit(self, False)
|
||||
self.text_edit.setObjectName(u'textEdit')
|
||||
self.dialog_layout.addWidget(self.text_edit)
|
||||
self.button_box = create_button_box(self, u'button_box', [u'cancel', u'save'])
|
||||
self.dialog_layout.addWidget(self.button_box)
|
||||
|
||||
def retranslateUi(self):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
self.setWindowTitle(translate('OpenLP.ServiceNoteForm', 'Service Item Notes'))
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
@ -26,19 +26,28 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets of the settings dialog.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, build_icon
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_SettingsDialog(object):
|
||||
"""
|
||||
The UI widgets of the settings dialog.
|
||||
"""
|
||||
def setupUi(self, settingsDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
settingsDialog.setObjectName(u'settingsDialog')
|
||||
settingsDialog.resize(800, 500)
|
||||
settingsDialog.setWindowIcon(build_icon(u':/system/system_settings.png'))
|
||||
self.dialogLayout = QtGui.QGridLayout(settingsDialog)
|
||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||
self.dialogLayout.setObjectName(u'dialog_layout')
|
||||
self.dialogLayout.setMargin(8)
|
||||
self.settingListWidget = QtGui.QListWidget(settingsDialog)
|
||||
self.settingListWidget.setUniformItemSizes(True)
|
||||
@ -49,10 +58,13 @@ class Ui_SettingsDialog(object):
|
||||
self.stackedLayout = QtGui.QStackedLayout()
|
||||
self.stackedLayout.setObjectName(u'stackedLayout')
|
||||
self.dialogLayout.addLayout(self.stackedLayout, 0, 1, 1, 1)
|
||||
self.buttonBox = create_button_box(settingsDialog, u'buttonBox', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.buttonBox, 1, 1, 1, 1)
|
||||
self.button_box = create_button_box(settingsDialog, u'button_box', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.button_box, 1, 1, 1, 1)
|
||||
self.retranslateUi(settingsDialog)
|
||||
QtCore.QObject.connect(self.settingListWidget, QtCore.SIGNAL(u'currentRowChanged(int)'), self.tabChanged)
|
||||
|
||||
def retranslateUi(self, settingsDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
settingsDialog.setWindowTitle(translate('OpenLP.SettingsForm', 'Configure OpenLP'))
|
||||
|
@ -31,36 +31,40 @@ The :mod:`settingsform` provides a user interface for the OpenLP settings
|
||||
"""
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, build_icon, PluginStatus
|
||||
from openlp.core.lib import Receiver, PluginStatus, Registry, build_icon
|
||||
from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab
|
||||
from openlp.core.ui.media import PlayerTab
|
||||
from settingsdialog import Ui_SettingsDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
||||
"""
|
||||
Provide the form to manipulate the settings for OpenLP
|
||||
"""
|
||||
def __init__(self, mainWindow, parent=None):
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Initialise the settings form
|
||||
"""
|
||||
self.mainWindow = mainWindow
|
||||
Registry().register(u'settings_form', self)
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
# General tab
|
||||
self.generalTab = GeneralTab(self)
|
||||
# Themes tab
|
||||
self.themesTab = ThemesTab(self, mainWindow)
|
||||
self.themesTab = ThemesTab(self)
|
||||
# Advanced tab
|
||||
self.advancedTab = AdvancedTab(self)
|
||||
# Advanced tab
|
||||
self.playerTab = PlayerTab(self, mainWindow)
|
||||
self.playerTab = PlayerTab(self)
|
||||
|
||||
def exec_(self):
|
||||
"""
|
||||
Execute the form
|
||||
"""
|
||||
# load all the settings
|
||||
self.settingListWidget.clear()
|
||||
while self.stackedLayout.count():
|
||||
@ -140,5 +144,25 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
||||
per save.
|
||||
"""
|
||||
if self.resetSuffixes:
|
||||
self.mainWindow.serviceManagerContents.resetSupportedSuffixes()
|
||||
self.service_manager.reset_supported_suffixes()
|
||||
self.resetSuffixes = False
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
||||
def _get_service_manager(self):
|
||||
"""
|
||||
Adds the plugin manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_service_manager'):
|
||||
self._service_manager = Registry().get(u'service_manager')
|
||||
return self._service_manager
|
||||
|
||||
service_manager = property(_get_service_manager)
|
||||
|
@ -26,17 +26,23 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The list of shortcuts within a dialog.
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, build_icon
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class CaptureShortcutButton(QtGui.QPushButton):
|
||||
"""
|
||||
A class to encapsulate a ``QPushButton``.
|
||||
"""
|
||||
def __init__(self, *args):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QPushButton.__init__(self, *args)
|
||||
self.setCheckable(True)
|
||||
|
||||
@ -51,7 +57,13 @@ class CaptureShortcutButton(QtGui.QPushButton):
|
||||
|
||||
|
||||
class Ui_ShortcutListDialog(object):
|
||||
"""
|
||||
The UI widgets for the shortcut dialog.
|
||||
"""
|
||||
def setupUi(self, shortcutListDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
shortcutListDialog.setObjectName(u'shortcutListDialog')
|
||||
shortcutListDialog.resize(500, 438)
|
||||
self.shortcutListLayout = QtGui.QVBoxLayout(shortcutListDialog)
|
||||
@ -107,12 +119,15 @@ class Ui_ShortcutListDialog(object):
|
||||
self.alternateLabel.setObjectName(u'alternateLabel')
|
||||
self.detailsLayout.addWidget(self.alternateLabel, 0, 2, 1, 1)
|
||||
self.shortcutListLayout.addLayout(self.detailsLayout)
|
||||
self.buttonBox = create_button_box(shortcutListDialog, u'buttonBox', [u'cancel', u'ok', u'defaults'])
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.shortcutListLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(shortcutListDialog, u'button_box', [u'cancel', u'ok', u'defaults'])
|
||||
self.button_box.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.shortcutListLayout.addWidget(self.button_box)
|
||||
self.retranslateUi(shortcutListDialog)
|
||||
|
||||
def retranslateUi(self, shortcutListDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
shortcutListDialog.setWindowTitle(translate('OpenLP.ShortcutListDialog', 'Configure Shortcuts'))
|
||||
self.descriptionLabel.setText(
|
||||
translate('OpenLP.ShortcutListDialog', 'Select an action and click one of the buttons below to start '
|
||||
|
@ -26,13 +26,14 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`~openlp.core.ui.shortcutlistform` module contains the form class"""
|
||||
import logging
|
||||
import re
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, Settings
|
||||
from openlp.core.lib import Registry, Settings
|
||||
from openlp.core.utils import translate
|
||||
from openlp.core.utils.actions import ActionList
|
||||
from shortcutlistdialog import Ui_ShortcutListDialog
|
||||
@ -41,12 +42,16 @@ REMOVE_AMPERSAND = re.compile(r'&{1}')
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
"""
|
||||
The shortcut list dialog
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
self.changedActions = {}
|
||||
@ -63,7 +68,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
self.onClearPrimaryButtonClicked)
|
||||
QtCore.QObject.connect(self.clearAlternateButton, QtCore.SIGNAL(u'clicked(bool)'),
|
||||
self.onClearAlternateButtonClicked)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'clicked(QAbstractButton*)'),
|
||||
QtCore.QObject.connect(self.button_box, QtCore.SIGNAL(u'clicked(QAbstractButton*)'),
|
||||
self.onRestoreDefaultsClicked)
|
||||
QtCore.QObject.connect(self.defaultRadioButton, QtCore.SIGNAL(u'clicked(bool)'),
|
||||
self.onDefaultRadioButtonClicked)
|
||||
@ -71,6 +76,9 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
self.onCustomRadioButtonClicked)
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
"""
|
||||
Respond to certain key presses
|
||||
"""
|
||||
if event.key() == QtCore.Qt.Key_Space:
|
||||
self.keyReleaseEvent(event)
|
||||
elif self.primaryPushButton.isChecked() or self.alternatePushButton.isChecked():
|
||||
@ -80,6 +88,9 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
self.close()
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
"""
|
||||
Respond to certain key presses
|
||||
"""
|
||||
if not self.primaryPushButton.isChecked() and not self.alternatePushButton.isChecked():
|
||||
return
|
||||
key = event.key()
|
||||
@ -105,6 +116,9 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
False, text=key_sequence.toString())
|
||||
|
||||
def exec_(self):
|
||||
"""
|
||||
Execute the dialog
|
||||
"""
|
||||
self.changedActions = {}
|
||||
self.reloadShortcutList()
|
||||
self._adjustButton(self.primaryPushButton, False, False, u'')
|
||||
@ -273,7 +287,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
"""
|
||||
Restores all default shortcuts.
|
||||
"""
|
||||
if self.buttonBox.buttonRole(button) != QtGui.QDialogButtonBox.ResetRole:
|
||||
if self.button_box.buttonRole(button) != QtGui.QDialogButtonBox.ResetRole:
|
||||
return
|
||||
if QtGui.QMessageBox.question(self, translate('OpenLP.ShortcutListDialog', 'Restore Default Shortcuts'),
|
||||
translate('OpenLP.ShortcutListDialog', 'Do you want to restore all '
|
||||
@ -424,7 +438,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
if changing_action.shortcutContext() in [QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
|
||||
is_valid = False
|
||||
if not is_valid:
|
||||
Receiver.send_message(u'openlp_warning_message', {
|
||||
self.main_window.warning_message( {
|
||||
u'title': translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
|
||||
u'message': translate('OpenLP.ShortcutListDialog',
|
||||
'The shortcut "%s" is already assigned to another action, '
|
||||
@ -464,3 +478,13 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
|
||||
button.setChecked(checked)
|
||||
if enabled is not None:
|
||||
button.setEnabled(enabled)
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The :mod:`slidecontroller` module contains argubly the most important part of OpenLP - the slide controller
|
||||
"""
|
||||
import os
|
||||
import logging
|
||||
import copy
|
||||
@ -34,14 +36,10 @@ from collections import deque
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, \
|
||||
translate, build_icon, build_html, PluginManager, ServiceItem, \
|
||||
ImageSource, SlideLimits, ServiceItemAction, Settings
|
||||
from openlp.core.ui import HideMode, MainDisplay, Display, ScreenList
|
||||
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, \
|
||||
DisplayControllerType
|
||||
from openlp.core.lib import OpenLPToolbar, Receiver, ItemCapabilities, ServiceItem, ImageSource, SlideLimits, \
|
||||
ServiceItemAction, Settings, Registry, UiStrings, ScreenList, build_icon, build_html, translate
|
||||
from openlp.core.ui import HideMode, MainDisplay, Display, DisplayControllerType
|
||||
from openlp.core.lib.ui import create_action
|
||||
from openlp.core.utils.actions import ActionList, CategoryOrder
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -86,8 +84,6 @@ class SlideController(DisplayController):
|
||||
self.ratio = float(self.screens.current[u'size'].width()) / float(self.screens.current[u'size'].height())
|
||||
except ZeroDivisionError:
|
||||
self.ratio = 1
|
||||
self.imageManager = self.parent().imageManager
|
||||
self.mediaController = self.parent().mediaController
|
||||
self.loopList = [
|
||||
u'playSlidesMenu',
|
||||
u'loopSeparator',
|
||||
@ -98,6 +94,14 @@ class SlideController(DisplayController):
|
||||
u'audioPauseItem',
|
||||
u'audioTimeLabel'
|
||||
]
|
||||
self.wideMenu = [
|
||||
u'blankScreenButton',
|
||||
u'themeScreenButton',
|
||||
u'desktopScreenButton'
|
||||
]
|
||||
self.hideMenuList = [
|
||||
u'hideMenu'
|
||||
]
|
||||
self.timer_id = 0
|
||||
self.songEdit = False
|
||||
self.selectedRow = 0
|
||||
@ -113,6 +117,7 @@ class SlideController(DisplayController):
|
||||
# Type label for the top of the slide controller
|
||||
self.typeLabel = QtGui.QLabel(self.panel)
|
||||
if self.isLive:
|
||||
Registry().register(u'live_controller', self)
|
||||
self.typeLabel.setText(UiStrings().Live)
|
||||
self.split = 1
|
||||
self.typePrefix = u'live'
|
||||
@ -121,6 +126,7 @@ class SlideController(DisplayController):
|
||||
self.category = UiStrings().LiveToolbar
|
||||
ActionList.get_instance().add_category(unicode(self.category), CategoryOrder.standardToolbar)
|
||||
else:
|
||||
Registry().register(u'preview_controller', self)
|
||||
self.typeLabel.setText(UiStrings().Preview)
|
||||
self.split = 0
|
||||
self.typePrefix = u'preview'
|
||||
@ -197,6 +203,19 @@ class SlideController(DisplayController):
|
||||
self.hideMenu.menu().addAction(self.blankScreen)
|
||||
self.hideMenu.menu().addAction(self.themeScreen)
|
||||
self.hideMenu.menu().addAction(self.desktopScreen)
|
||||
# Wide menu of display control buttons.
|
||||
self.blankScreenButton = QtGui.QToolButton(self.toolbar)
|
||||
self.blankScreenButton.setObjectName(u'blankScreenButton')
|
||||
self.toolbar.addToolbarWidget(self.blankScreenButton)
|
||||
self.blankScreenButton.setDefaultAction(self.blankScreen)
|
||||
self.themeScreenButton = QtGui.QToolButton(self.toolbar)
|
||||
self.themeScreenButton.setObjectName(u'themeScreenButton')
|
||||
self.toolbar.addToolbarWidget(self.themeScreenButton)
|
||||
self.themeScreenButton.setDefaultAction(self.themeScreen)
|
||||
self.desktopScreenButton = QtGui.QToolButton(self.toolbar)
|
||||
self.desktopScreenButton.setObjectName(u'desktopScreenButton')
|
||||
self.toolbar.addToolbarWidget(self.desktopScreenButton)
|
||||
self.desktopScreenButton.setDefaultAction(self.desktopScreen)
|
||||
self.toolbar.addToolbarAction(u'loopSeparator', separator=True)
|
||||
# Play Slides Menu
|
||||
self.playSlidesMenu = QtGui.QToolButton(self.toolbar)
|
||||
@ -211,7 +230,7 @@ class SlideController(DisplayController):
|
||||
self.playSlidesOnce = create_action(self, u'playSlidesOnce', text=UiStrings().PlaySlidesToEnd,
|
||||
icon=u':/media/media_time.png', checked=False, shortcuts=[],
|
||||
category=self.category, triggers=self.onPlaySlidesOnce)
|
||||
if Settings().value(self.parent().generalSettingsSection + u'/enable slide loop', True):
|
||||
if Settings().value(self.parent().advancedSettingsSection + u'/slide limits') == SlideLimits.Wrap:
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
||||
else:
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
|
||||
@ -234,7 +253,7 @@ class SlideController(DisplayController):
|
||||
tooltip=translate('OpenLP.SlideController', 'Edit and reload song preview.'), triggers=self.onEditSong)
|
||||
self.controllerLayout.addWidget(self.toolbar)
|
||||
# Build the Media Toolbar
|
||||
self.mediaController.register_controller(self)
|
||||
self.media_controller.register_controller(self)
|
||||
if self.isLive:
|
||||
# Build the Song Toolbar
|
||||
self.songMenu = QtGui.QToolButton(self.toolbar)
|
||||
@ -301,8 +320,7 @@ class SlideController(DisplayController):
|
||||
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(
|
||||
self.slidePreview.sizePolicy().hasHeightForWidth())
|
||||
sizePolicy.setHeightForWidth(self.slidePreview.sizePolicy().hasHeightForWidth())
|
||||
self.slidePreview.setSizePolicy(sizePolicy)
|
||||
self.slidePreview.setFrameShape(QtGui.QFrame.Box)
|
||||
self.slidePreview.setFrameShadow(QtGui.QFrame.Plain)
|
||||
@ -349,6 +367,7 @@ class SlideController(DisplayController):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'slidecontroller_toggle_display'), self.toggleDisplay)
|
||||
self.toolbar.setWidgetVisible(self.loopList, False)
|
||||
self.toolbar.setWidgetVisible(self.wideMenu, False)
|
||||
else:
|
||||
QtCore.QObject.connect(self.previewListWidget,
|
||||
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick)
|
||||
@ -357,8 +376,7 @@ class SlideController(DisplayController):
|
||||
self.setLiveHotkeys(self)
|
||||
self.__addActionsToWidget(self.previewListWidget)
|
||||
else:
|
||||
self.previewListWidget.addActions(
|
||||
[self.nextItem, self.previousItem])
|
||||
self.previewListWidget.addActions([self.nextItem, self.previousItem])
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix), self.onStopLoop)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
@ -438,6 +456,9 @@ class SlideController(DisplayController):
|
||||
self.current_shortcut = u''
|
||||
|
||||
def setLiveHotkeys(self, parent=None):
|
||||
"""
|
||||
Set the live hotkeys
|
||||
"""
|
||||
self.previousService = create_action(parent, u'previousService',
|
||||
text=translate('OpenLP.SlideController', 'Previous Service'),
|
||||
shortcuts=[QtCore.Qt.Key_Left], context=QtCore.Qt.WidgetWithChildrenShortcut, category=self.category,
|
||||
@ -452,8 +473,11 @@ class SlideController(DisplayController):
|
||||
triggers=self.liveEscape)
|
||||
|
||||
def liveEscape(self):
|
||||
"""
|
||||
If you press ESC on the live screen it should close the display temporarily.
|
||||
"""
|
||||
self.display.setVisible(False)
|
||||
self.mediaController.media_stop(self)
|
||||
self.media_controller.media_stop(self)
|
||||
|
||||
def toggleDisplay(self, action):
|
||||
"""
|
||||
@ -494,12 +518,12 @@ class SlideController(DisplayController):
|
||||
self.keypress_loop = True
|
||||
keypressCommand = self.keypress_queue.popleft()
|
||||
if keypressCommand == ServiceItemAction.Previous:
|
||||
Receiver.send_message('servicemanager_previous_item')
|
||||
self.service_manager.previous_item()
|
||||
elif keypressCommand == ServiceItemAction.PreviousLastSlide:
|
||||
# Go to the last slide of the previous item
|
||||
Receiver.send_message('servicemanager_previous_item', u'last slide')
|
||||
self.service_manager.previous_item(last_slide=True)
|
||||
else:
|
||||
Receiver.send_message('servicemanager_next_item')
|
||||
self.service_manager.next_item()
|
||||
self.keypress_loop = False
|
||||
|
||||
def screenSizeChanged(self):
|
||||
@ -510,7 +534,7 @@ class SlideController(DisplayController):
|
||||
# rebuild display as screen size changed
|
||||
if self.display:
|
||||
self.display.close()
|
||||
self.display = MainDisplay(self, self.imageManager, self.isLive, self)
|
||||
self.display = MainDisplay(self, self.isLive, self)
|
||||
self.display.setup()
|
||||
if self.isLive:
|
||||
self.__addActionsToWidget(self.display)
|
||||
@ -520,17 +544,20 @@ class SlideController(DisplayController):
|
||||
self.ratio = float(self.screens.current[u'size'].width()) / float(self.screens.current[u'size'].height())
|
||||
except ZeroDivisionError:
|
||||
self.ratio = 1
|
||||
self.mediaController.setup_display(self.display, False)
|
||||
self.media_controller.setup_display(self.display, False)
|
||||
self.previewSizeChanged()
|
||||
self.previewDisplay.setup()
|
||||
serviceItem = ServiceItem()
|
||||
self.previewDisplay.webView.setHtml(build_html(serviceItem, self.previewDisplay.screen, None, self.isLive,
|
||||
plugins=PluginManager.get_instance().plugins))
|
||||
self.mediaController.setup_display(self.previewDisplay,True)
|
||||
plugins=self.plugin_manager.plugins))
|
||||
self.media_controller.setup_display(self.previewDisplay, True)
|
||||
if self.serviceItem:
|
||||
self.refreshServiceItem()
|
||||
|
||||
def __addActionsToWidget(self, widget):
|
||||
"""
|
||||
Add actions to the widget specified by `widget`
|
||||
"""
|
||||
widget.addActions([
|
||||
self.previousItem, self.nextItem,
|
||||
self.previousService, self.nextService,
|
||||
@ -568,8 +595,24 @@ class SlideController(DisplayController):
|
||||
width = self.parent().controlSplitter.sizes()[self.split]
|
||||
for framenumber in range(len(self.serviceItem.get_frames())):
|
||||
self.previewListWidget.setRowHeight(framenumber, width / self.ratio)
|
||||
self.onControllerSizeChanged(self.controller.width(), self.controller.height())
|
||||
|
||||
def onControllerSizeChanged(self, width, height):
|
||||
"""
|
||||
Change layout of display control buttons on controller size change
|
||||
"""
|
||||
if self.isLive:
|
||||
if width > 300 and self.hideMenu.isVisible():
|
||||
self.toolbar.setWidgetVisible(self.hideMenuList, False)
|
||||
self.toolbar.setWidgetVisible(self.wideMenu)
|
||||
elif width < 300 and not self.hideMenu.isVisible():
|
||||
self.toolbar.setWidgetVisible(self.wideMenu, False)
|
||||
self.toolbar.setWidgetVisible(self.hideMenuList)
|
||||
|
||||
def onSongBarHandler(self):
|
||||
"""
|
||||
Some song handler
|
||||
"""
|
||||
request = self.sender().text()
|
||||
slide_no = self.slideList[request]
|
||||
self.__updatePreviewSelection(slide_no)
|
||||
@ -585,7 +628,7 @@ class SlideController(DisplayController):
|
||||
"""
|
||||
Updates the Slide Limits variable from the settings.
|
||||
"""
|
||||
self.slide_limits = Settings().value(self.parent().advancedSettingsSection + u'/slide limits', SlideLimits.End)
|
||||
self.slide_limits = Settings().value(self.parent().advancedSettingsSection + u'/slide limits')
|
||||
|
||||
def enableToolBar(self, item):
|
||||
"""
|
||||
@ -613,7 +656,7 @@ class SlideController(DisplayController):
|
||||
self.playSlidesLoop.setChecked(False)
|
||||
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||
if item.is_text():
|
||||
if Settings().value(self.parent().songsSettingsSection + u'/display songbar', True) and self.slideList:
|
||||
if Settings().value(self.parent().songsSettingsSection + u'/display songbar') and self.slideList:
|
||||
self.songMenu.show()
|
||||
if item.is_capable(ItemCapabilities.CanLoop) and len(item.get_frames()) > 1:
|
||||
self.toolbar.setWidgetVisible(self.loopList)
|
||||
@ -654,12 +697,12 @@ class SlideController(DisplayController):
|
||||
item.render()
|
||||
self._processItem(item, self.selectedRow)
|
||||
|
||||
def addServiceItem(self, item):
|
||||
def add_service_item(self, item):
|
||||
"""
|
||||
Method to install the service item into the controller
|
||||
Called by plugins
|
||||
"""
|
||||
log.debug(u'addServiceItem live = %s' % self.isLive)
|
||||
log.debug(u'add_service_item live = %s' % self.isLive)
|
||||
item.render()
|
||||
slideno = 0
|
||||
if self.songEdit:
|
||||
@ -692,6 +735,14 @@ class SlideController(DisplayController):
|
||||
self.slideSelected()
|
||||
else:
|
||||
self._processItem(item, slidenum)
|
||||
if self.isLive and item.auto_play_slides_loop and item.timed_slide_interval > 0:
|
||||
self.playSlidesLoop.setChecked(item.auto_play_slides_loop)
|
||||
self.delaySpinBox.setValue(int(item.timed_slide_interval))
|
||||
self.onPlaySlidesLoop()
|
||||
elif self.isLive and item.auto_play_slides_once and item.timed_slide_interval > 0:
|
||||
self.playSlidesOnce.setChecked(item.auto_play_slides_once)
|
||||
self.delaySpinBox.setValue(int(item.timed_slide_interval))
|
||||
self.onPlaySlidesOnce()
|
||||
|
||||
def _processItem(self, serviceItem, slideno):
|
||||
"""
|
||||
@ -727,8 +778,8 @@ class SlideController(DisplayController):
|
||||
action.setData(counter)
|
||||
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), self.onTrackTriggered)
|
||||
self.display.audioPlayer.repeat = Settings().value(
|
||||
self.parent().generalSettingsSection + u'/audio repeat list', False)
|
||||
if Settings().value(self.parent().generalSettingsSection + u'/audio start paused', True):
|
||||
self.parent().generalSettingsSection + u'/audio repeat list')
|
||||
if Settings().value(self.parent().generalSettingsSection + u'/audio start paused'):
|
||||
self.audioPauseItem.setChecked(True)
|
||||
self.display.audioPlayer.pause()
|
||||
else:
|
||||
@ -768,9 +819,9 @@ class SlideController(DisplayController):
|
||||
else:
|
||||
# If current slide set background to image
|
||||
if framenumber == slideno:
|
||||
self.serviceItem.bg_image_bytes = self.imageManager.getImageBytes(frame[u'path'],
|
||||
self.serviceItem.bg_image_bytes = self.image_manager.get_image_bytes(frame[u'path'],
|
||||
ImageSource.ImagePlugin)
|
||||
image = self.imageManager.getImage(frame[u'path'], ImageSource.ImagePlugin)
|
||||
image = self.image_manager.get_image(frame[u'path'], ImageSource.ImagePlugin)
|
||||
label.setPixmap(QtGui.QPixmap.fromImage(image))
|
||||
self.previewListWidget.setCellWidget(framenumber, 0, label)
|
||||
slideHeight = width * (1 / self.ratio)
|
||||
@ -837,8 +888,7 @@ class SlideController(DisplayController):
|
||||
Allow the main display to blank the main display at startup time
|
||||
"""
|
||||
log.debug(u'mainDisplaySetBackground live = %s' % self.isLive)
|
||||
display_type = Settings().value(self.parent().generalSettingsSection + u'/screen blank',
|
||||
u'')
|
||||
display_type = Settings().value(self.parent().generalSettingsSection + u'/screen blank')
|
||||
if self.screens.which_screen(self.window()) != self.screens.which_screen(self.display):
|
||||
# Order done to handle initial conversion
|
||||
if display_type == u'themed':
|
||||
@ -881,6 +931,7 @@ class SlideController(DisplayController):
|
||||
Settings().remove(self.parent().generalSettingsSection + u'/screen blank')
|
||||
self.blankPlugin()
|
||||
self.updatePreview()
|
||||
self.onToggleLoop()
|
||||
|
||||
def onThemeDisplay(self, checked=None):
|
||||
"""
|
||||
@ -899,6 +950,7 @@ class SlideController(DisplayController):
|
||||
Settings().remove(self.parent().generalSettingsSection + u'/screen blank')
|
||||
self.blankPlugin()
|
||||
self.updatePreview()
|
||||
self.onToggleLoop()
|
||||
|
||||
def onHideDisplay(self, checked=None):
|
||||
"""
|
||||
@ -917,6 +969,7 @@ class SlideController(DisplayController):
|
||||
Settings().remove(self.parent().generalSettingsSection + u'/screen blank')
|
||||
self.hidePlugin(checked)
|
||||
self.updatePreview()
|
||||
self.onToggleLoop()
|
||||
|
||||
def blankPlugin(self):
|
||||
"""
|
||||
@ -933,8 +986,7 @@ class SlideController(DisplayController):
|
||||
else:
|
||||
if not self.serviceItem.is_command():
|
||||
Receiver.send_message(u'live_display_show')
|
||||
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
|
||||
else:
|
||||
if hide_mode:
|
||||
Receiver.send_message(u'live_display_hide', hide_mode)
|
||||
@ -949,13 +1001,11 @@ class SlideController(DisplayController):
|
||||
if self.serviceItem is not None:
|
||||
if hide:
|
||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||
Receiver.send_message(u'%s_hide' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
Receiver.send_message(u'%s_hide' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
|
||||
else:
|
||||
if not self.serviceItem.is_command():
|
||||
Receiver.send_message(u'live_display_show')
|
||||
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
Receiver.send_message(u'%s_unblank' % self.serviceItem.name.lower(), [self.serviceItem, self.isLive])
|
||||
else:
|
||||
if hide:
|
||||
Receiver.send_message(u'live_display_hide', HideMode.Screen)
|
||||
@ -995,6 +1045,7 @@ class SlideController(DisplayController):
|
||||
self.selectedRow = row
|
||||
self.__checkUpdateSelectedSlide(row)
|
||||
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row)
|
||||
self.display.setFocus()
|
||||
|
||||
def onSlideChange(self, row):
|
||||
"""
|
||||
@ -1086,6 +1137,9 @@ class SlideController(DisplayController):
|
||||
self.slideSelected()
|
||||
|
||||
def __checkUpdateSelectedSlide(self, row):
|
||||
"""
|
||||
Check if this slide has been updated
|
||||
"""
|
||||
if row + 1 < self.previewListWidget.rowCount():
|
||||
self.previewListWidget.scrollToItem(self.previewListWidget.item(row + 1, 0))
|
||||
self.previewListWidget.selectRow(row)
|
||||
@ -1094,7 +1148,8 @@ class SlideController(DisplayController):
|
||||
"""
|
||||
Toggles the loop state.
|
||||
"""
|
||||
if self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked():
|
||||
hide_mode = self.hideMode()
|
||||
if hide_mode is None and (self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked()):
|
||||
self.onStartLoop()
|
||||
else:
|
||||
self.onStopLoop()
|
||||
@ -1128,11 +1183,11 @@ class SlideController(DisplayController):
|
||||
self.playSlidesLoop.setText(UiStrings().StopPlaySlidesInLoop)
|
||||
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time.png'))
|
||||
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
||||
self.playSlidesOnce.setChecked(False)
|
||||
else:
|
||||
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
|
||||
self.playSlidesOnce.setChecked(False)
|
||||
self.onToggleLoop()
|
||||
|
||||
def onPlaySlidesOnce(self, checked=None):
|
||||
@ -1149,17 +1204,23 @@ class SlideController(DisplayController):
|
||||
self.playSlidesOnce.setText(UiStrings().StopPlaySlidesToEnd)
|
||||
self.playSlidesLoop.setIcon(build_icon(u':/media/media_time.png'))
|
||||
self.playSlidesLoop.setText(UiStrings().PlaySlidesInLoop)
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
|
||||
self.playSlidesLoop.setChecked(False)
|
||||
else:
|
||||
self.playSlidesOnce.setIcon(build_icon(u':/media/media_time'))
|
||||
self.playSlidesOnce.setText(UiStrings().PlaySlidesToEnd)
|
||||
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
|
||||
self.playSlidesLoop.setChecked(False)
|
||||
self.onToggleLoop()
|
||||
|
||||
def setAudioItemsVisibility(self, visible):
|
||||
"""
|
||||
Set the visibility of the audio stuff
|
||||
"""
|
||||
self.toolbar.setWidgetVisible(self.audioList, visible)
|
||||
|
||||
def onAudioPauseClicked(self, checked):
|
||||
"""
|
||||
Pause the audio player
|
||||
"""
|
||||
if not self.audioPauseItem.isVisible():
|
||||
return
|
||||
if checked:
|
||||
@ -1179,20 +1240,22 @@ class SlideController(DisplayController):
|
||||
From the preview display requires the service Item to be editied
|
||||
"""
|
||||
self.songEdit = True
|
||||
Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(), u'P:%s' % self.serviceItem.edit_id)
|
||||
new_item = Registry().get(self.serviceItem.name).onRemoteEdit(self.serviceItem.edit_id, True)
|
||||
if new_item:
|
||||
self.add_service_item(new_item)
|
||||
|
||||
def onPreviewAddToService(self):
|
||||
"""
|
||||
From the preview display request the Item to be added to service
|
||||
"""
|
||||
if self.serviceItem:
|
||||
self.parent().serviceManagerContents.addServiceItem(self.serviceItem)
|
||||
self.service_manager.add_service_item(self.serviceItem)
|
||||
|
||||
def onGoLiveClick(self):
|
||||
"""
|
||||
triggered by clicking the Preview slide items
|
||||
"""
|
||||
if Settings().value(u'advanced/double click live', False):
|
||||
if Settings().value(u'advanced/double click live'):
|
||||
# Live and Preview have issues if we have video or presentations
|
||||
# playing in both at the same time.
|
||||
if self.serviceItem.is_command():
|
||||
@ -1208,16 +1271,16 @@ class SlideController(DisplayController):
|
||||
row = self.previewListWidget.currentRow()
|
||||
if -1 < row < self.previewListWidget.rowCount():
|
||||
if self.serviceItem.from_service:
|
||||
Receiver.send_message('servicemanager_preview_live', u'%s:%s' % (self.serviceItem._uuid, row))
|
||||
self.service_manager.preview_live(self.serviceItem.unique_identifier, row)
|
||||
else:
|
||||
self.parent().liveController.addServiceManagerItem(self.serviceItem, row)
|
||||
self.live_controller.addServiceManagerItem(self.serviceItem, row)
|
||||
|
||||
def onMediaStart(self, item):
|
||||
"""
|
||||
Respond to the arrival of a media service item
|
||||
"""
|
||||
log.debug(u'SlideController onMediaStart')
|
||||
self.mediaController.video(self.controllerType, item, self.hideMode())
|
||||
self.media_controller.video(self.controllerType, item, self.hideMode())
|
||||
if not self.isLive:
|
||||
self.previewDisplay.show()
|
||||
self.slidePreview.hide()
|
||||
@ -1227,7 +1290,7 @@ class SlideController(DisplayController):
|
||||
Respond to a request to close the Video
|
||||
"""
|
||||
log.debug(u'SlideController onMediaClose')
|
||||
self.mediaController.media_reset(self)
|
||||
self.media_controller.media_reset(self)
|
||||
self.previewDisplay.hide()
|
||||
self.slidePreview.show()
|
||||
|
||||
@ -1262,14 +1325,73 @@ class SlideController(DisplayController):
|
||||
return None
|
||||
|
||||
def onNextTrackClicked(self):
|
||||
"""
|
||||
Go to the next track when next is clicked
|
||||
"""
|
||||
self.display.audioPlayer.next()
|
||||
|
||||
def onAudioTimeRemaining(self, time):
|
||||
"""
|
||||
Update how much time is remaining
|
||||
"""
|
||||
seconds = self.display.audioPlayer.mediaObject.remainingTime() // 1000
|
||||
minutes = seconds // 60
|
||||
seconds %= 60
|
||||
self.audioTimeLabel.setText(u' %02d:%02d ' % (minutes, seconds))
|
||||
|
||||
def onTrackTriggered(self):
|
||||
"""
|
||||
Start playing a track
|
||||
"""
|
||||
action = self.sender()
|
||||
self.display.audioPlayer.goTo(action.data())
|
||||
|
||||
def _get_plugin_manager(self):
|
||||
"""
|
||||
Adds the plugin manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_plugin_manager'):
|
||||
self._plugin_manager = Registry().get(u'plugin_manager')
|
||||
return self._plugin_manager
|
||||
|
||||
plugin_manager = property(_get_plugin_manager)
|
||||
|
||||
def _get_image_manager(self):
|
||||
"""
|
||||
Adds the image manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_image_manager'):
|
||||
self._image_manager = Registry().get(u'image_manager')
|
||||
return self._image_manager
|
||||
|
||||
image_manager = property(_get_image_manager)
|
||||
|
||||
def _get_media_controller(self):
|
||||
"""
|
||||
Adds the media controller to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_media_controller'):
|
||||
self._media_controller = Registry().get(u'media_controller')
|
||||
return self._media_controller
|
||||
|
||||
media_controller = property(_get_media_controller)
|
||||
|
||||
def _get_service_manager(self):
|
||||
"""
|
||||
Adds the service manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_service_manager'):
|
||||
self._service_manager = Registry().get(u'service_manager')
|
||||
return self._service_manager
|
||||
|
||||
service_manager = property(_get_service_manager)
|
||||
|
||||
def _get_live_controller(self):
|
||||
"""
|
||||
Adds the live controller to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_live_controller'):
|
||||
self._live_controller = Registry().get(u'live_controller')
|
||||
return self._live_controller
|
||||
|
||||
live_controller = property(_get_live_controller)
|
||||
|
@ -26,17 +26,28 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
from openlp.core.lib import Receiver
|
||||
"""
|
||||
The splash screen
|
||||
"""
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
|
||||
class SplashScreen(QtGui.QSplashScreen):
|
||||
"""
|
||||
The splash screen
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QSplashScreen.__init__(self)
|
||||
self.setupUi()
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'close_splash'), self.close)
|
||||
|
||||
def setupUi(self):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
self.setObjectName(u'splashScreen')
|
||||
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
||||
splash_image = QtGui.QPixmap(u':/graphics/openlp-splash-screen.png')
|
||||
|
@ -26,18 +26,27 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The UI widgets for the time dialog
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import UiStrings, create_button_box
|
||||
from openlp.core.lib import UiStrings, translate
|
||||
from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_StartTimeDialog(object):
|
||||
"""
|
||||
The UI widgets for the time dialog
|
||||
"""
|
||||
def setupUi(self, StartTimeDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
StartTimeDialog.setObjectName(u'StartTimeDialog')
|
||||
StartTimeDialog.resize(350, 10)
|
||||
self.dialogLayout = QtGui.QGridLayout(StartTimeDialog)
|
||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||
self.dialogLayout.setObjectName(u'dialog_layout')
|
||||
self.startLabel = QtGui.QLabel(StartTimeDialog)
|
||||
self.startLabel.setObjectName(u'startLabel')
|
||||
self.startLabel.setAlignment(QtCore.Qt.AlignHCenter)
|
||||
@ -101,12 +110,15 @@ class Ui_StartTimeDialog(object):
|
||||
self.secondFinishLabel.setAlignment(QtCore.Qt.AlignRight)
|
||||
self.dialogLayout.addWidget(self.secondFinishLabel, 3, 3, 1, 1)
|
||||
self.dialogLayout.addWidget(self.secondSpinBox, 3, 1, 1, 1)
|
||||
self.buttonBox = create_button_box(StartTimeDialog, u'buttonBox', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.buttonBox, 5, 2, 1, 2)
|
||||
self.button_box = create_button_box(StartTimeDialog, u'button_box', [u'cancel', u'ok'])
|
||||
self.dialogLayout.addWidget(self.button_box, 5, 2, 1, 2)
|
||||
self.retranslateUi(StartTimeDialog)
|
||||
self.setMaximumHeight(self.sizeHint().height())
|
||||
|
||||
def retranslateUi(self, StartTimeDialog):
|
||||
"""
|
||||
Update the translations on the fly
|
||||
"""
|
||||
self.setWindowTitle(translate('OpenLP.StartTimeForm', 'Item Start and Finish Time'))
|
||||
self.hourSpinBox.setSuffix(UiStrings().Hours)
|
||||
self.minuteSpinBox.setSuffix(UiStrings().Minutes)
|
||||
|
@ -26,20 +26,26 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The actual start time form.
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from starttimedialog import Ui_StartTimeDialog
|
||||
|
||||
from openlp.core.lib import translate
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.lib import UiStrings, Registry, translate
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
|
||||
|
||||
class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
|
||||
"""
|
||||
The exception dialog
|
||||
The start time dialog
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, self.main_window)
|
||||
self.setupUi(self)
|
||||
|
||||
def exec_(self):
|
||||
@ -60,6 +66,9 @@ class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
When the dialog succeeds, this is run
|
||||
"""
|
||||
start = self.hourSpinBox.value() * 3600 + \
|
||||
self.minuteSpinBox.value() * 60 + \
|
||||
self.secondSpinBox.value()
|
||||
@ -79,8 +88,21 @@ class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
|
||||
return QtGui.QDialog.accept(self)
|
||||
|
||||
def _time_split(self, seconds):
|
||||
"""
|
||||
Split time up into hours minutes and seconds from secongs
|
||||
"""
|
||||
hours = seconds / 3600
|
||||
seconds -= 3600 * hours
|
||||
minutes = seconds / 60
|
||||
seconds -= 60 * minutes
|
||||
return hours, minutes, seconds
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
@ -26,21 +26,24 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The Theme wizard
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.lib import Receiver, UiStrings, Registry, translate
|
||||
from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui import ThemeLayoutForm
|
||||
from openlp.core.utils import get_images_filter
|
||||
from themewizard import Ui_ThemeWizard
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
"""
|
||||
This is the Theme Import Wizard, which allows easy creation and editing of
|
||||
@ -56,7 +59,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
The QWidget-derived parent of the wizard.
|
||||
"""
|
||||
QtGui.QWizard.__init__(self, parent)
|
||||
self.thememanager = parent
|
||||
self.setupUi(self)
|
||||
self.registerFields()
|
||||
self.updateThemeAllowed = True
|
||||
@ -149,7 +151,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
# Do not trigger on start up
|
||||
if self.currentPage != self.welcomePage:
|
||||
self.updateTheme()
|
||||
self.thememanager.generateImage(self.theme, True)
|
||||
self.theme_manager.generate_image(self.theme, True)
|
||||
|
||||
def updateLinesText(self, lines):
|
||||
"""
|
||||
@ -178,6 +180,9 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
pixmapHeight + 2 * frameWidth)
|
||||
|
||||
def validateCurrentPage(self):
|
||||
"""
|
||||
Validate the current page
|
||||
"""
|
||||
background_image = BackgroundType.to_string(BackgroundType.Image)
|
||||
if self.page(self.currentId()) == self.backgroundPage and \
|
||||
self.theme.background_type == background_image and not self.imageFileEdit.text():
|
||||
@ -196,7 +201,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
self.setOption(QtGui.QWizard.HaveCustomButton1, enabled)
|
||||
if self.page(pageId) == self.previewPage:
|
||||
self.updateTheme()
|
||||
frame = self.thememanager.generateImage(self.theme)
|
||||
frame = self.theme_manager.generate_image(self.theme)
|
||||
self.previewBoxLabel.setPixmap(frame)
|
||||
self.displayAspectRatio = float(frame.width()) / frame.height()
|
||||
self.resizeEvent()
|
||||
@ -206,15 +211,15 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
Generate layout preview and display the form.
|
||||
"""
|
||||
self.updateTheme()
|
||||
width = self.thememanager.mainwindow.renderer.width
|
||||
height = self.thememanager.mainwindow.renderer.height
|
||||
width = self.renderer.width
|
||||
height = self.renderer.height
|
||||
pixmap = QtGui.QPixmap(width, height)
|
||||
pixmap.fill(QtCore.Qt.white)
|
||||
paint = QtGui.QPainter(pixmap)
|
||||
paint.setPen(QtGui.QPen(QtCore.Qt.blue, 2))
|
||||
paint.drawRect(self.thememanager.mainwindow.renderer.get_main_rectangle(self.theme))
|
||||
paint.drawRect(self.renderer.get_main_rectangle(self.theme))
|
||||
paint.setPen(QtGui.QPen(QtCore.Qt.red, 2))
|
||||
paint.drawRect(self.thememanager.mainwindow.renderer.get_footer_rectangle(self.theme))
|
||||
paint.drawRect(self.renderer.get_footer_rectangle(self.theme))
|
||||
paint.end()
|
||||
self.themeLayoutForm.exec_(pixmap)
|
||||
|
||||
@ -444,18 +449,30 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
self.setBackgroundPageValues()
|
||||
|
||||
def onMainColorButtonClicked(self):
|
||||
"""
|
||||
Set the main colour value
|
||||
"""
|
||||
self.theme.font_main_color = self._colorButton(self.theme.font_main_color)
|
||||
self.setMainAreaPageValues()
|
||||
|
||||
def onOutlineColorButtonClicked(self):
|
||||
"""
|
||||
Set the outline colour value
|
||||
"""
|
||||
self.theme.font_main_outline_color = self._colorButton(self.theme.font_main_outline_color)
|
||||
self.setMainAreaPageValues()
|
||||
|
||||
def onShadowColorButtonClicked(self):
|
||||
"""
|
||||
Set the shadow colour value
|
||||
"""
|
||||
self.theme.font_main_shadow_color = self._colorButton(self.theme.font_main_shadow_color)
|
||||
self.setMainAreaPageValues()
|
||||
|
||||
def onFooterColorButtonClicked(self):
|
||||
"""
|
||||
Set the footer colour value
|
||||
"""
|
||||
self.theme.font_footer_color = self._colorButton(self.theme.font_footer_color)
|
||||
self.setFooterAreaPageValues()
|
||||
|
||||
@ -514,9 +531,9 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
filename = os.path.split(unicode(self.theme.background_filename))[1]
|
||||
saveTo = os.path.join(self.path, self.theme.theme_name, filename)
|
||||
saveFrom = self.theme.background_filename
|
||||
if not self.edit_mode and not self.thememanager.checkIfThemeExists(self.theme.theme_name):
|
||||
if not self.edit_mode and not self.theme_manager.check_if_theme_exists(self.theme.theme_name):
|
||||
return
|
||||
self.thememanager.saveTheme(self.theme, saveFrom, saveTo)
|
||||
self.theme_manager.save_theme(self.theme, saveFrom, saveTo)
|
||||
return QtGui.QDialog.accept(self)
|
||||
|
||||
def _colorButton(self, field):
|
||||
@ -527,3 +544,23 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
|
||||
if new_color.isValid():
|
||||
field = new_color.name()
|
||||
return field
|
||||
|
||||
def _get_renderer(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_renderer'):
|
||||
self._renderer = Registry().get(u'renderer')
|
||||
return self._renderer
|
||||
|
||||
renderer = property(_get_renderer)
|
||||
|
||||
def _get_theme_manager(self):
|
||||
"""
|
||||
Adds the theme manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_theme_manager'):
|
||||
self._theme_manager = Registry().get(u'theme_manager')
|
||||
return self._theme_manager
|
||||
|
||||
theme_manager = property(_get_theme_manager)
|
||||
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The layout of the theme
|
||||
"""
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import translate
|
||||
@ -34,7 +36,13 @@ from openlp.core.lib.ui import create_button_box
|
||||
|
||||
|
||||
class Ui_ThemeLayoutDialog(object):
|
||||
"""
|
||||
The layout of the theme
|
||||
"""
|
||||
def setupUi(self, themeLayoutDialog):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
themeLayoutDialog.setObjectName(u'themeLayoutDialogDialog')
|
||||
#themeLayoutDialog.resize(300, 200)
|
||||
self.previewLayout = QtGui.QVBoxLayout(themeLayoutDialog)
|
||||
@ -58,12 +66,14 @@ class Ui_ThemeLayoutDialog(object):
|
||||
self.footerColourLabel = QtGui.QLabel(self.previewArea)
|
||||
self.footerColourLabel.setObjectName(u'footerColourLabel')
|
||||
self.previewLayout.addWidget(self.footerColourLabel)
|
||||
self.buttonBox = create_button_box(themeLayoutDialog, u'buttonBox', [u'ok'])
|
||||
self.previewLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(themeLayoutDialog, u'button_box', [u'ok'])
|
||||
self.previewLayout.addWidget(self.button_box)
|
||||
self.retranslateUi(themeLayoutDialog)
|
||||
|
||||
def retranslateUi(self, themeLayoutDialog):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
themeLayoutDialog.setWindowTitle(translate('OpenLP.StartTimeForm', 'Theme Layout'))
|
||||
self.mainColourLabel.setText(translate('OpenLP.StartTimeForm', 'The blue box shows the main area.'))
|
||||
self.footerColourLabel.setText(translate('OpenLP.StartTimeForm', 'The red box shows the footer.'))
|
||||
|
||||
|
@ -26,16 +26,22 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The form layout
|
||||
"""
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
from themelayoutdialog import Ui_ThemeLayoutDialog
|
||||
|
||||
|
||||
class ThemeLayoutForm(QtGui.QDialog, Ui_ThemeLayoutDialog):
|
||||
"""
|
||||
The exception dialog
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
|
||||
@ -44,11 +50,7 @@ class ThemeLayoutForm(QtGui.QDialog, Ui_ThemeLayoutDialog):
|
||||
Run the Dialog with correct heading.
|
||||
"""
|
||||
pixmap = image.scaledToHeight(400, QtCore.Qt.SmoothTransformation)
|
||||
self.themeDisplayLabel.setPixmap(image)
|
||||
self.themeDisplayLabel.setPixmap(pixmap)
|
||||
displayAspectRatio = float(image.width()) / image.height()
|
||||
self.themeDisplayLabel.setFixedSize(400, 400 / displayAspectRatio)
|
||||
return QtGui.QDialog.exec_(self)
|
||||
|
||||
def accept(self):
|
||||
return QtGui.QDialog.accept(self)
|
||||
|
||||
|
@ -26,7 +26,9 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The Theme Manager manages adding, deleteing and modifying of themes.
|
||||
"""
|
||||
import os
|
||||
import zipfile
|
||||
import shutil
|
||||
@ -36,23 +38,28 @@ import re
|
||||
from xml.etree.ElementTree import ElementTree, XML
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, Receiver, SettingsManager, translate, \
|
||||
check_item_selected, check_directory_exists, create_thumb, validate_thumb, ImageSource, Settings
|
||||
from openlp.core.lib import ImageSource, OpenLPToolbar, Receiver, Registry, SettingsManager, Settings, UiStrings, \
|
||||
get_text_file_string, build_icon, translate, check_item_selected, check_directory_exists, create_thumb, \
|
||||
validate_thumb
|
||||
from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, BackgroundGradientType
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box, create_widget_action
|
||||
from openlp.core.lib.ui import critical_error_message_box, create_widget_action
|
||||
from openlp.core.theme import Theme
|
||||
from openlp.core.ui import FileRenameForm, ThemeForm
|
||||
from openlp.core.utils import AppLocation, delete_file, locale_compare, get_filesystem_encoding
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
Manages the orders of Theme.
|
||||
"""
|
||||
def __init__(self, mainwindow, parent=None):
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
self.mainwindow = mainwindow
|
||||
Registry().register(u'theme_manager', self)
|
||||
self.settingsSection = u'themes'
|
||||
self.themeForm = ThemeForm(self)
|
||||
self.fileRenameForm = FileRenameForm(self)
|
||||
@ -71,67 +78,67 @@ class ThemeManager(QtGui.QWidget):
|
||||
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',
|
||||
triggers=self.on_edit_theme)
|
||||
self.deleteToolbarAction = self.toolbar.addToolbarAction(u'delete_theme',
|
||||
text=translate('OpenLP.ThemeManager', 'Delete Theme'),
|
||||
icon=u':/general/general_delete.png',
|
||||
tooltip=translate('OpenLP.ThemeManager', 'Delete a theme.'),
|
||||
triggers=self.onDeleteTheme)
|
||||
triggers=self.on_delete_theme)
|
||||
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)
|
||||
triggers=self.on_import_theme)
|
||||
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)
|
||||
triggers=self.on_export_theme)
|
||||
self.layout.addWidget(self.toolbar)
|
||||
self.themeWidget = QtGui.QWidgetAction(self.toolbar)
|
||||
self.themeWidget.setObjectName(u'themeWidget')
|
||||
self.theme_widget = QtGui.QWidgetAction(self.toolbar)
|
||||
self.theme_widget.setObjectName(u'theme_widget')
|
||||
# create theme manager list
|
||||
self.themeListWidget = QtGui.QListWidget(self)
|
||||
self.themeListWidget.setAlternatingRowColors(True)
|
||||
self.themeListWidget.setIconSize(QtCore.QSize(88, 50))
|
||||
self.themeListWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.themeListWidget.setObjectName(u'themeListWidget')
|
||||
self.layout.addWidget(self.themeListWidget)
|
||||
QtCore.QObject.connect(self.themeListWidget, QtCore.SIGNAL('customContextMenuRequested(QPoint)'),
|
||||
self.contextMenu)
|
||||
self.theme_list_widget = QtGui.QListWidget(self)
|
||||
self.theme_list_widget.setAlternatingRowColors(True)
|
||||
self.theme_list_widget.setIconSize(QtCore.QSize(88, 50))
|
||||
self.theme_list_widget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
||||
self.theme_list_widget.setObjectName(u'theme_list_widget')
|
||||
self.layout.addWidget(self.theme_list_widget)
|
||||
QtCore.QObject.connect(self.theme_list_widget, QtCore.SIGNAL('customContextMenuRequested(QPoint)'),
|
||||
self.context_menu)
|
||||
# build the context menu
|
||||
self.menu = QtGui.QMenu()
|
||||
self.editAction = create_widget_action(self.menu,
|
||||
self.edit_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ThemeManager', '&Edit Theme'),
|
||||
icon=u':/themes/theme_edit.png', triggers=self.onEditTheme)
|
||||
self.copyAction = create_widget_action(self.menu,
|
||||
icon=u':/themes/theme_edit.png', triggers=self.on_edit_theme)
|
||||
self.copy_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ThemeManager', '&Copy Theme'),
|
||||
icon=u':/themes/theme_edit.png', triggers=self.onCopyTheme)
|
||||
self.renameAction = create_widget_action(self.menu,
|
||||
icon=u':/themes/theme_edit.png', triggers=self.on_copy_theme)
|
||||
self.rename_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ThemeManager', '&Rename Theme'),
|
||||
icon=u':/themes/theme_edit.png', triggers=self.onRenameTheme)
|
||||
self.deleteAction = create_widget_action(self.menu,
|
||||
icon=u':/themes/theme_edit.png', triggers=self.on_rename_theme)
|
||||
self.delete_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ThemeManager', '&Delete Theme'),
|
||||
icon=u':/general/general_delete.png', triggers=self.onDeleteTheme)
|
||||
icon=u':/general/general_delete.png', triggers=self.on_delete_theme)
|
||||
self.menu.addSeparator()
|
||||
self.globalAction = create_widget_action(self.menu,
|
||||
self.global_action = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ThemeManager', 'Set As &Global Default'),
|
||||
icon=u':/general/general_export.png',
|
||||
triggers=self.changeGlobalFromScreen)
|
||||
self.exportAction = create_widget_action(self.menu,
|
||||
text=translate('OpenLP.ThemeManager', '&Export Theme'),
|
||||
icon=u':/general/general_export.png', triggers=self.onExportTheme)
|
||||
icon=u':/general/general_export.png', triggers=self.on_export_theme)
|
||||
# Signals
|
||||
QtCore.QObject.connect(self.themeListWidget,
|
||||
QtCore.QObject.connect(self.theme_list_widget,
|
||||
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.changeGlobalFromScreen)
|
||||
QtCore.QObject.connect(self.themeListWidget,
|
||||
QtCore.SIGNAL(u'currentItemChanged(QListWidgetItem *, QListWidgetItem *)'), self.checkListState)
|
||||
QtCore.QObject.connect(self.theme_list_widget,
|
||||
QtCore.SIGNAL(u'currentItemChanged(QListWidgetItem *, QListWidgetItem *)'), self.check_list_state)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'theme_update_global'), self.changeGlobalFromTab)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated)
|
||||
QtCore.SIGNAL(u'theme_update_global'), self.change_global_from_tab)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.config_updated)
|
||||
# Variables
|
||||
self.themeList = []
|
||||
self.theme_list = []
|
||||
self.path = AppLocation.get_section_data_path(self.settingsSection)
|
||||
check_directory_exists(self.path)
|
||||
self.thumbPath = os.path.join(self.path, u'thumbnails')
|
||||
@ -140,27 +147,28 @@ class ThemeManager(QtGui.QWidget):
|
||||
self.oldBackgroundImage = None
|
||||
self.badV1NameChars = re.compile(r'[%+\[\]]')
|
||||
# Last little bits of setting up
|
||||
self.configUpdated()
|
||||
self.config_updated()
|
||||
|
||||
def firstTime(self):
|
||||
def first_time(self):
|
||||
"""
|
||||
Import new themes downloaded by the first time wizard
|
||||
"""
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
files = SettingsManager.get_files(self.settingsSection, u'.otz')
|
||||
for file in files:
|
||||
file = os.path.join(self.path, file)
|
||||
self.unzipTheme(file, self.path)
|
||||
delete_file(file)
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
for theme_file in files:
|
||||
theme_file = os.path.join(self.path, theme_file)
|
||||
self.unzipTheme(theme_file, self.path)
|
||||
delete_file(theme_file)
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def configUpdated(self):
|
||||
|
||||
def config_updated(self):
|
||||
"""
|
||||
Triggered when Config dialog is updated.
|
||||
"""
|
||||
self.global_theme = Settings().value(self.settingsSection + u'/global theme', u'')
|
||||
self.global_theme = Settings().value(self.settingsSection + u'/global theme')
|
||||
|
||||
def checkListState(self, item):
|
||||
def check_list_state(self, item):
|
||||
"""
|
||||
If Default theme selected remove delete button.
|
||||
"""
|
||||
@ -174,41 +182,41 @@ class ThemeManager(QtGui.QWidget):
|
||||
else:
|
||||
self.deleteToolbarAction.setVisible(False)
|
||||
|
||||
def contextMenu(self, point):
|
||||
def context_menu(self, point):
|
||||
"""
|
||||
Build the Right Click Context menu and set state depending on
|
||||
the type of theme.
|
||||
"""
|
||||
item = self.themeListWidget.itemAt(point)
|
||||
item = self.theme_list_widget.itemAt(point)
|
||||
if item is None:
|
||||
return
|
||||
real_theme_name = item.data(QtCore.Qt.UserRole)
|
||||
theme_name = unicode(item.text())
|
||||
visible = real_theme_name == theme_name
|
||||
self.deleteAction.setVisible(visible)
|
||||
self.renameAction.setVisible(visible)
|
||||
self.globalAction.setVisible(visible)
|
||||
self.menu.exec_(self.themeListWidget.mapToGlobal(point))
|
||||
self.delete_action.setVisible(visible)
|
||||
self.rename_action.setVisible(visible)
|
||||
self.global_action.setVisible(visible)
|
||||
self.menu.exec_(self.theme_list_widget.mapToGlobal(point))
|
||||
|
||||
def changeGlobalFromTab(self, theme_name):
|
||||
def change_global_from_tab(self, theme_name):
|
||||
"""
|
||||
Change the global theme when it is changed through the Themes settings
|
||||
tab
|
||||
"""
|
||||
log.debug(u'changeGlobalFromTab %s', theme_name)
|
||||
for count in range (0, self.themeListWidget.count()):
|
||||
log.debug(u'change_global_from_tab %s', theme_name)
|
||||
for count in range(0, self.theme_list_widget.count()):
|
||||
# reset the old name
|
||||
item = self.themeListWidget.item(count)
|
||||
item = self.theme_list_widget.item(count)
|
||||
old_name = item.text()
|
||||
new_name = item.data(QtCore.Qt.UserRole)
|
||||
if old_name != new_name:
|
||||
self.themeListWidget.item(count).setText(new_name)
|
||||
self.theme_list_widget.item(count).setText(new_name)
|
||||
# Set the new name
|
||||
if theme_name == new_name:
|
||||
name = translate('OpenLP.ThemeManager', '%s (default)') % new_name
|
||||
self.themeListWidget.item(count).setText(name)
|
||||
self.theme_list_widget.item(count).setText(name)
|
||||
self.deleteToolbarAction.setVisible(
|
||||
item not in self.themeListWidget.selectedItems())
|
||||
item not in self.theme_list_widget.selectedItems())
|
||||
|
||||
def changeGlobalFromScreen(self, index=-1):
|
||||
"""
|
||||
@ -216,21 +224,21 @@ class ThemeManager(QtGui.QWidget):
|
||||
Theme Manager list
|
||||
"""
|
||||
log.debug(u'changeGlobalFromScreen %s', index)
|
||||
selected_row = self.themeListWidget.currentRow()
|
||||
for count in range (0, self.themeListWidget.count()):
|
||||
item = self.themeListWidget.item(count)
|
||||
selected_row = self.theme_list_widget.currentRow()
|
||||
for count in range(0, self.theme_list_widget.count()):
|
||||
item = self.theme_list_widget.item(count)
|
||||
old_name = item.text()
|
||||
# reset the old name
|
||||
if old_name != item.data(QtCore.Qt.UserRole):
|
||||
self.themeListWidget.item(count).setText(item.data(QtCore.Qt.UserRole))
|
||||
self.theme_list_widget.item(count).setText(item.data(QtCore.Qt.UserRole))
|
||||
# Set the new name
|
||||
if count == selected_row:
|
||||
self.global_theme = self.themeListWidget.item(count).text()
|
||||
self.global_theme = self.theme_list_widget.item(count).text()
|
||||
name = translate('OpenLP.ThemeManager', '%s (default)') % self.global_theme
|
||||
self.themeListWidget.item(count).setText(name)
|
||||
self.theme_list_widget.item(count).setText(name)
|
||||
Settings().setValue(self.settingsSection + u'/global theme', self.global_theme)
|
||||
Receiver.send_message(u'theme_update_global', self.global_theme)
|
||||
self._pushThemes()
|
||||
self._push_themes()
|
||||
|
||||
def onAddTheme(self):
|
||||
"""
|
||||
@ -241,45 +249,44 @@ class ThemeManager(QtGui.QWidget):
|
||||
theme.set_default_header_footer()
|
||||
self.themeForm.theme = theme
|
||||
self.themeForm.exec_()
|
||||
self.loadThemes()
|
||||
self.load_themes()
|
||||
|
||||
def onRenameTheme(self):
|
||||
def on_rename_theme(self):
|
||||
"""
|
||||
Renames an existing theme to a new name
|
||||
"""
|
||||
if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to rename.'),
|
||||
translate('OpenLP.ThemeManager', 'Rename Confirmation'),
|
||||
translate('OpenLP.ThemeManager', 'Rename %s theme?'), False, False):
|
||||
item = self.themeListWidget.currentItem()
|
||||
item = self.theme_list_widget.currentItem()
|
||||
old_theme_name = item.data(QtCore.Qt.UserRole)
|
||||
self.fileRenameForm.fileNameEdit.setText(old_theme_name)
|
||||
if self.fileRenameForm.exec_():
|
||||
new_theme_name = self.fileRenameForm.fileNameEdit.text()
|
||||
if old_theme_name == new_theme_name:
|
||||
return
|
||||
if self.checkIfThemeExists(new_theme_name):
|
||||
old_theme_data = self.getThemeData(old_theme_name)
|
||||
if self.check_if_theme_exists(new_theme_name):
|
||||
old_theme_data = self.get_theme_data(old_theme_name)
|
||||
self.cloneThemeData(old_theme_data, new_theme_name)
|
||||
self.deleteTheme(old_theme_name)
|
||||
for plugin in self.mainwindow.pluginManager.plugins:
|
||||
self.delete_theme(old_theme_name)
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
if plugin.usesTheme(old_theme_name):
|
||||
plugin.renameTheme(old_theme_name, new_theme_name)
|
||||
self.mainwindow.renderer.update_theme(
|
||||
new_theme_name, old_theme_name)
|
||||
self.loadThemes()
|
||||
self.renderer.update_theme(new_theme_name, old_theme_name)
|
||||
self.load_themes()
|
||||
|
||||
def onCopyTheme(self):
|
||||
def on_copy_theme(self):
|
||||
"""
|
||||
Copies an existing theme to a new name
|
||||
"""
|
||||
item = self.themeListWidget.currentItem()
|
||||
item = self.theme_list_widget.currentItem()
|
||||
old_theme_name = item.data(QtCore.Qt.UserRole)
|
||||
self.fileRenameForm.fileNameEdit.setText(translate('OpenLP.ThemeManager',
|
||||
'Copy of %s', 'Copy of <theme name>') % old_theme_name)
|
||||
if self.fileRenameForm.exec_(True):
|
||||
new_theme_name = self.fileRenameForm.fileNameEdit.text()
|
||||
if self.checkIfThemeExists(new_theme_name):
|
||||
theme_data = self.getThemeData(old_theme_name)
|
||||
if self.check_if_theme_exists(new_theme_name):
|
||||
theme_data = self.get_theme_data(old_theme_name)
|
||||
self.cloneThemeData(theme_data, new_theme_name)
|
||||
|
||||
def cloneThemeData(self, theme_data, new_theme_name):
|
||||
@ -295,100 +302,100 @@ class ThemeManager(QtGui.QWidget):
|
||||
save_from = theme_data.background_filename
|
||||
theme_data.theme_name = new_theme_name
|
||||
theme_data.extend_image_filename(self.path)
|
||||
self.saveTheme(theme_data, save_from, save_to)
|
||||
self.loadThemes()
|
||||
self.save_theme(theme_data, save_from, save_to)
|
||||
self.load_themes()
|
||||
|
||||
def onEditTheme(self):
|
||||
def on_edit_theme(self):
|
||||
"""
|
||||
Loads the settings for the theme that is to be edited and launches the
|
||||
theme editing form so the user can make their changes.
|
||||
"""
|
||||
if check_item_selected(self.themeListWidget,
|
||||
if check_item_selected(self.theme_list_widget,
|
||||
translate('OpenLP.ThemeManager', 'You must select a theme to edit.')):
|
||||
item = self.themeListWidget.currentItem()
|
||||
theme = self.getThemeData(item.data(QtCore.Qt.UserRole))
|
||||
item = self.theme_list_widget.currentItem()
|
||||
theme = self.get_theme_data(item.data(QtCore.Qt.UserRole))
|
||||
if theme.background_type == u'image':
|
||||
self.oldBackgroundImage = theme.background_filename
|
||||
self.themeForm.theme = theme
|
||||
self.themeForm.exec_(True)
|
||||
self.oldBackgroundImage = None
|
||||
self.mainwindow.renderer.update_theme(theme.theme_name)
|
||||
self.loadThemes()
|
||||
self.renderer.update_theme(theme.theme_name)
|
||||
self.load_themes()
|
||||
|
||||
def onDeleteTheme(self):
|
||||
def on_delete_theme(self):
|
||||
"""
|
||||
Delete a theme
|
||||
"""
|
||||
if self._validate_theme_action(translate('OpenLP.ThemeManager', 'You must select a theme to delete.'),
|
||||
translate('OpenLP.ThemeManager', 'Delete Confirmation'),
|
||||
translate('OpenLP.ThemeManager', 'Delete %s theme?')):
|
||||
item = self.themeListWidget.currentItem()
|
||||
item = self.theme_list_widget.currentItem()
|
||||
theme = item.text()
|
||||
row = self.themeListWidget.row(item)
|
||||
self.themeListWidget.takeItem(row)
|
||||
self.deleteTheme(theme)
|
||||
self.mainwindow.renderer.update_theme(theme, only_delete=True)
|
||||
row = self.theme_list_widget.row(item)
|
||||
self.theme_list_widget.takeItem(row)
|
||||
self.delete_theme(theme)
|
||||
self.renderer.update_theme(theme, only_delete=True)
|
||||
# As we do not reload the themes, push out the change. Reload the
|
||||
# list as the internal lists and events need to be triggered.
|
||||
self._pushThemes()
|
||||
self._push_themes()
|
||||
|
||||
def deleteTheme(self, theme):
|
||||
def delete_theme(self, theme):
|
||||
"""
|
||||
Delete a theme.
|
||||
|
||||
``theme``
|
||||
The theme to delete.
|
||||
"""
|
||||
self.themeList.remove(theme)
|
||||
self.theme_list.remove(theme)
|
||||
thumb = u'%s.png' % theme
|
||||
delete_file(os.path.join(self.path, thumb))
|
||||
delete_file(os.path.join(self.thumbPath, thumb))
|
||||
try:
|
||||
encoding = get_filesystem_encoding()
|
||||
shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
|
||||
except OSError:
|
||||
except OSError, shutil.Error:
|
||||
log.exception(u'Error deleting theme %s', theme)
|
||||
|
||||
def onExportTheme(self):
|
||||
def on_export_theme(self):
|
||||
"""
|
||||
Export the theme in a zip file
|
||||
"""
|
||||
item = self.themeListWidget.currentItem()
|
||||
item = self.theme_list_widget.currentItem()
|
||||
if item is None:
|
||||
critical_error_message_box(message=translate('OpenLP.ThemeManager', 'You have not selected a theme.'))
|
||||
return
|
||||
theme = item.data(QtCore.Qt.UserRole)
|
||||
path = QtGui.QFileDialog.getExistingDirectory(self,
|
||||
translate('OpenLP.ThemeManager', 'Save Theme - (%s)') % theme,
|
||||
SettingsManager.get_last_dir(self.settingsSection, 1))
|
||||
path = unicode(path)
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
Settings().value(self.settingsSection + u'/last directory export'))
|
||||
self.application.set_busy_cursor()
|
||||
if path:
|
||||
SettingsManager.set_last_dir(self.settingsSection, path, 1)
|
||||
Settings().setValue(self.settingsSection + u'/last directory export', path)
|
||||
theme_path = os.path.join(path, theme + u'.otz')
|
||||
zip = None
|
||||
theme_zip = None
|
||||
try:
|
||||
zip = zipfile.ZipFile(theme_path, u'w')
|
||||
theme_zip = zipfile.ZipFile(theme_path, u'w')
|
||||
source = os.path.join(self.path, theme)
|
||||
for files in os.walk(source):
|
||||
for name in files[2]:
|
||||
zip.write(
|
||||
theme_zip.write(
|
||||
os.path.join(source, name).encode(u'utf-8'),
|
||||
os.path.join(theme, name).encode(u'utf-8'))
|
||||
os.path.join(theme, name).encode(u'utf-8')
|
||||
)
|
||||
QtGui.QMessageBox.information(self,
|
||||
translate('OpenLP.ThemeManager', 'Theme Exported'),
|
||||
translate('OpenLP.ThemeManager', 'Your theme has been successfully exported.'))
|
||||
except (IOError, OSError):
|
||||
log.exception(u'Export Theme Failed')
|
||||
critical_error_message_box(
|
||||
translate('OpenLP.ThemeManager', 'Theme Export Failed'),
|
||||
critical_error_message_box(translate('OpenLP.ThemeManager', 'Theme Export Failed'),
|
||||
translate('OpenLP.ThemeManager', 'Your theme could not be exported due to an error.'))
|
||||
finally:
|
||||
if zip:
|
||||
zip.close()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
if theme_zip:
|
||||
theme_zip.close()
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def onImportTheme(self):
|
||||
|
||||
def on_import_theme(self):
|
||||
"""
|
||||
Opens a file dialog to select the theme file(s) to import before
|
||||
attempting to extract OpenLP themes from those files. This process
|
||||
@ -396,42 +403,41 @@ class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
files = QtGui.QFileDialog.getOpenFileNames(self,
|
||||
translate('OpenLP.ThemeManager', 'Select Theme Import File'),
|
||||
SettingsManager.get_last_dir(self.settingsSection),
|
||||
Settings().value(self.settingsSection + u'/last directory import'),
|
||||
translate('OpenLP.ThemeManager', 'OpenLP Themes (*.theme *.otz)'))
|
||||
log.info(u'New Themes %s', unicode(files))
|
||||
if not files:
|
||||
return
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
for file in files:
|
||||
SettingsManager.set_last_dir(self.settingsSection, unicode(file))
|
||||
self.unzipTheme(file, self.path)
|
||||
self.loadThemes()
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_busy_cursor()
|
||||
for file_name in files:
|
||||
Settings().setValue(self.settingsSection + u'/last directory import', unicode(file_name))
|
||||
self.unzip_theme(file_name, self.path)
|
||||
self.load_themes()
|
||||
self.application.set_normal_cursor()
|
||||
|
||||
def loadThemes(self, firstTime=False):
|
||||
def load_themes(self, first_time=False):
|
||||
"""
|
||||
Loads the theme lists and triggers updates accross the whole system
|
||||
using direct calls or core functions and events for the plugins.
|
||||
The plugins will call back in to get the real list if they want it.
|
||||
"""
|
||||
log.debug(u'Load themes from dir')
|
||||
self.themeList = []
|
||||
self.themeListWidget.clear()
|
||||
self.theme_list = []
|
||||
self.theme_list_widget.clear()
|
||||
files = SettingsManager.get_files(self.settingsSection, u'.png')
|
||||
if firstTime:
|
||||
self.firstTime()
|
||||
if first_time:
|
||||
self.first_time()
|
||||
files = SettingsManager.get_files(self.settingsSection, u'.png')
|
||||
# No themes have been found so create one
|
||||
if not files:
|
||||
theme = ThemeXML()
|
||||
theme.theme_name = UiStrings().Default
|
||||
self._writeTheme(theme, None, None)
|
||||
self._write_theme(theme, None, None)
|
||||
Settings().setValue(self.settingsSection + u'/global theme', theme.theme_name)
|
||||
self.configUpdated()
|
||||
self.config_updated()
|
||||
files = SettingsManager.get_files(self.settingsSection, u'.png')
|
||||
# Sort the themes by its name considering language specific
|
||||
files.sort(key=lambda file_name: unicode(file_name),
|
||||
cmp=locale_compare)
|
||||
files.sort(key=lambda file_name: unicode(file_name), cmp=locale_compare)
|
||||
# now process the file list of png files
|
||||
for name in files:
|
||||
# check to see file is in theme root directory
|
||||
@ -450,23 +456,23 @@ class ThemeManager(QtGui.QWidget):
|
||||
icon = create_thumb(theme, thumb)
|
||||
item_name.setIcon(icon)
|
||||
item_name.setData(QtCore.Qt.UserRole, text_name)
|
||||
self.themeListWidget.addItem(item_name)
|
||||
self.themeList.append(text_name)
|
||||
self._pushThemes()
|
||||
self.theme_list_widget.addItem(item_name)
|
||||
self.theme_list.append(text_name)
|
||||
self._push_themes()
|
||||
|
||||
def _pushThemes(self):
|
||||
def _push_themes(self):
|
||||
"""
|
||||
Notify listeners that the theme list has been updated
|
||||
"""
|
||||
Receiver.send_message(u'theme_update_list', self.getThemes())
|
||||
Receiver.send_message(u'theme_update_list', self.get_themes())
|
||||
|
||||
def getThemes(self):
|
||||
def get_themes(self):
|
||||
"""
|
||||
Return the list of loaded themes
|
||||
"""
|
||||
return self.themeList
|
||||
return self.theme_list
|
||||
|
||||
def getThemeData(self, theme_name):
|
||||
def get_theme_data(self, theme_name):
|
||||
"""
|
||||
Returns a theme object from an XML file
|
||||
|
||||
@ -474,25 +480,26 @@ class ThemeManager(QtGui.QWidget):
|
||||
Name of the theme to load from file
|
||||
"""
|
||||
log.debug(u'getthemedata for theme %s', theme_name)
|
||||
xml_file = os.path.join(self.path, unicode(theme_name),
|
||||
unicode(theme_name) + u'.xml')
|
||||
xml_file = os.path.join(self.path, unicode(theme_name), unicode(theme_name) + u'.xml')
|
||||
xml = get_text_file_string(xml_file)
|
||||
if not xml:
|
||||
log.debug(u'No theme data - using default theme')
|
||||
return ThemeXML()
|
||||
else:
|
||||
return self._createThemeFromXml(xml, self.path)
|
||||
return self._create_theme_fom_Xml(xml, self.path)
|
||||
|
||||
def overWriteMessageBox(self, theme_name):
|
||||
ret = QtGui.QMessageBox.question(self,
|
||||
translate('OpenLP.ThemeManager', 'Theme Already Exists'),
|
||||
def over_write_message_box(self, theme_name):
|
||||
"""
|
||||
Display a warning box to the user that a theme already exists
|
||||
"""
|
||||
ret = QtGui.QMessageBox.question(self, translate('OpenLP.ThemeManager', 'Theme Already Exists'),
|
||||
translate('OpenLP.ThemeManager',
|
||||
'Theme %s already exists. Do you want to replace it?').replace('%s', 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):
|
||||
def unzip_theme(self, file_name, directory):
|
||||
"""
|
||||
Unzip the theme, remove the preview file if stored
|
||||
Generate a new preview file. Check the XML theme version and upgrade if
|
||||
@ -500,32 +507,31 @@ class ThemeManager(QtGui.QWidget):
|
||||
"""
|
||||
log.debug(u'Unzipping theme %s', file_name)
|
||||
file_name = unicode(file_name)
|
||||
zip = None
|
||||
theme_zip = None
|
||||
out_file = None
|
||||
file_xml = None
|
||||
abort_import = True
|
||||
try:
|
||||
zip = zipfile.ZipFile(file_name)
|
||||
xml_file = filter(lambda name:
|
||||
os.path.splitext(name)[1].lower() == u'.xml', zip.namelist())
|
||||
theme_zip = zipfile.ZipFile(file_name)
|
||||
xml_file = filter(lambda name: os.path.splitext(name)[1].lower() == u'.xml', theme_zip.namelist())
|
||||
if len(xml_file) != 1:
|
||||
log.exception(u'Theme contains "%s" XML files' % len(xml_file))
|
||||
raise Exception(u'validation')
|
||||
xml_tree = ElementTree(element=XML(zip.read(xml_file[0]))).getroot()
|
||||
raise Exception('validation')
|
||||
xml_tree = ElementTree(element=XML(theme_zip.read(xml_file[0]))).getroot()
|
||||
v1_background = xml_tree.find(u'BackgroundType')
|
||||
if v1_background is not None:
|
||||
theme_name, file_xml, out_file, abort_import = self.unzipVersion122(
|
||||
dir, zip, xml_file[0], xml_tree, v1_background, out_file)
|
||||
theme_name, file_xml, out_file, abort_import = self.unzip_version_122(
|
||||
directory, theme_zip, xml_file[0], xml_tree, v1_background, out_file)
|
||||
else:
|
||||
theme_name = xml_tree.find(u'name').text.strip()
|
||||
theme_folder = os.path.join(dir, theme_name)
|
||||
theme_folder = os.path.join(directory, theme_name)
|
||||
theme_exists = os.path.exists(theme_folder)
|
||||
if theme_exists and not self.overWriteMessageBox(theme_name):
|
||||
if theme_exists and not self.over_write_message_box(theme_name):
|
||||
abort_import = True
|
||||
return
|
||||
else:
|
||||
abort_import = False
|
||||
for name in zip.namelist():
|
||||
for name in theme_zip.namelist():
|
||||
try:
|
||||
uname = unicode(name, u'utf-8')
|
||||
except UnicodeDecodeError:
|
||||
@ -537,15 +543,15 @@ class ThemeManager(QtGui.QWidget):
|
||||
if split_name[-1] == u'' or len(split_name) == 1:
|
||||
# is directory or preview file
|
||||
continue
|
||||
full_name = os.path.join(dir, uname)
|
||||
full_name = os.path.join(directory, 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')
|
||||
file_xml = unicode(theme_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.write(theme_zip.read(name))
|
||||
out_file.close()
|
||||
except (IOError, zipfile.BadZipfile):
|
||||
log.exception(u'Importing theme from zip failed %s' % file_name)
|
||||
@ -558,39 +564,38 @@ class ThemeManager(QtGui.QWidget):
|
||||
raise
|
||||
finally:
|
||||
# Close the files, to be able to continue creating the theme.
|
||||
if zip:
|
||||
zip.close()
|
||||
if theme_zip:
|
||||
theme_zip.close()
|
||||
if out_file:
|
||||
out_file.close()
|
||||
if not abort_import:
|
||||
# As all files are closed, we can create the Theme.
|
||||
if file_xml:
|
||||
theme = self._createThemeFromXml(file_xml, self.path)
|
||||
self.generateAndSaveImage(dir, theme_name, theme)
|
||||
theme = self._create_theme_fom_Xml(file_xml, self.path)
|
||||
self.generate_and_save_image(directory, theme_name, theme)
|
||||
# Only show the error message, when IOError was not raised (in
|
||||
# this case the error message has already been shown).
|
||||
elif zip is not None:
|
||||
elif theme_zip is not None:
|
||||
critical_error_message_box(
|
||||
translate('OpenLP.ThemeManager', 'Validation Error'),
|
||||
translate('OpenLP.ThemeManager', 'File is not a valid theme.'))
|
||||
log.exception(u'Theme file does not contain XML data %s' % file_name)
|
||||
|
||||
def unzipVersion122(self, dir, zip, xml_file, xml_tree, background,
|
||||
out_file):
|
||||
def unzip_version_122(self, dir_name, zip_file, 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.badV1NameChars.sub(u'', theme_name)
|
||||
theme_folder = os.path.join(dir, theme_name)
|
||||
theme_folder = os.path.join(dir_name, theme_name)
|
||||
theme_exists = os.path.exists(theme_folder)
|
||||
if theme_exists and not self.overWriteMessageBox(theme_name):
|
||||
if theme_exists and not self.over_write_message_box(theme_name):
|
||||
return '', '', '', True
|
||||
themedir = os.path.join(dir, theme_name)
|
||||
themedir = os.path.join(dir_name, theme_name)
|
||||
check_directory_exists(themedir)
|
||||
file_xml = unicode(zip.read(xml_file), u'utf-8')
|
||||
file_xml = self._migrateVersion122(file_xml)
|
||||
file_xml = unicode(zip_file.read(xml_file), u'utf-8')
|
||||
file_xml = self._migrate_version_122(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()
|
||||
@ -598,18 +603,17 @@ class ThemeManager(QtGui.QWidget):
|
||||
image_name = xml_tree.find(u'BackgroundParameter1').text.strip()
|
||||
# image file has same extension and is in subfolder
|
||||
image_file = filter(lambda name: os.path.splitext(name)[1].lower()
|
||||
== os.path.splitext(image_name)[1].lower() and name.find(r'/'),
|
||||
zip.namelist())
|
||||
== os.path.splitext(image_name)[1].lower() and name.find(r'/'), zip_file.namelist())
|
||||
if len(image_file) >= 1:
|
||||
out_file = open(os.path.join(themedir, image_name), u'wb')
|
||||
out_file.write(zip.read(image_file[0]))
|
||||
out_file.write(zip_file.read(image_file[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):
|
||||
def check_if_theme_exists(self, theme_name):
|
||||
"""
|
||||
Check if theme already exists and displays error message
|
||||
|
||||
@ -624,25 +628,25 @@ class ThemeManager(QtGui.QWidget):
|
||||
return False
|
||||
return True
|
||||
|
||||
def saveTheme(self, theme, image_from, image_to):
|
||||
def save_theme(self, theme, image_from, image_to):
|
||||
"""
|
||||
Called by thememaintenance Dialog to save the theme
|
||||
and to trigger the reload of the theme list
|
||||
"""
|
||||
self._writeTheme(theme, image_from, image_to)
|
||||
self._write_theme(theme, image_from, image_to)
|
||||
if theme.background_type == BackgroundType.to_string(BackgroundType.Image):
|
||||
self.mainwindow.imageManager.updateImageBorder(theme.background_filename,
|
||||
self.image_manager.update_image_border(theme.background_filename,
|
||||
ImageSource.Theme, QtGui.QColor(theme.background_border_color))
|
||||
self.mainwindow.imageManager.processUpdates()
|
||||
self.image_manager.process_updates()
|
||||
|
||||
def _writeTheme(self, theme, image_from, image_to):
|
||||
def _write_theme(self, theme, image_from, image_to):
|
||||
"""
|
||||
Writes the theme to the disk and handles the background image if
|
||||
necessary
|
||||
"""
|
||||
name = theme.theme_name
|
||||
theme_pretty_xml = theme.extract_formatted_xml()
|
||||
log.debug(u'saveTheme %s %s', name, theme_pretty_xml.decode(u'utf-8'))
|
||||
log.debug(u'save_theme %s %s', name, theme_pretty_xml.decode(u'utf-8'))
|
||||
theme_dir = os.path.join(self.path, name)
|
||||
check_directory_exists(theme_dir)
|
||||
theme_file = os.path.join(theme_dir, name + u'.xml')
|
||||
@ -661,13 +665,16 @@ class ThemeManager(QtGui.QWidget):
|
||||
try:
|
||||
encoding = get_filesystem_encoding()
|
||||
shutil.copyfile(unicode(image_from).encode(encoding), unicode(image_to).encode(encoding))
|
||||
except IOError:
|
||||
except IOError, shutil.Error:
|
||||
log.exception(u'Failed to save theme image')
|
||||
self.generateAndSaveImage(self.path, name, theme)
|
||||
self.generate_and_save_image(self.path, name, theme)
|
||||
|
||||
def generateAndSaveImage(self, dir, name, theme):
|
||||
log.debug(u'generateAndSaveImage %s %s', dir, name)
|
||||
frame = self.generateImage(theme)
|
||||
def generate_and_save_image(self, directory, name, theme):
|
||||
"""
|
||||
Generate and save a preview image
|
||||
"""
|
||||
log.debug(u'generate_and_save_image %s %s', directory, name)
|
||||
frame = self.generate_image(theme)
|
||||
sample_path_name = os.path.join(self.path, name + u'.png')
|
||||
if os.path.exists(sample_path_name):
|
||||
os.unlink(sample_path_name)
|
||||
@ -676,18 +683,18 @@ class ThemeManager(QtGui.QWidget):
|
||||
create_thumb(sample_path_name, thumb, False)
|
||||
log.debug(u'Theme image written to %s', sample_path_name)
|
||||
|
||||
def updatePreviewImages(self):
|
||||
def update_preview_images(self):
|
||||
"""
|
||||
Called to update the themes' preview images.
|
||||
"""
|
||||
self.mainwindow.displayProgressBar(len(self.themeList))
|
||||
for theme in self.themeList:
|
||||
self.mainwindow.incrementProgressBar()
|
||||
self.generateAndSaveImage(self.path, theme, self.getThemeData(theme))
|
||||
self.mainwindow.finishedProgressBar()
|
||||
self.loadThemes()
|
||||
self.main_window.displayProgressBar(len(self.theme_list))
|
||||
for theme in self.theme_list:
|
||||
self.main_window.incrementProgressBar()
|
||||
self.generate_and_save_image(self.path, theme, self.get_theme_data(theme))
|
||||
self.main_window.finishedProgressBar()
|
||||
self.load_themes()
|
||||
|
||||
def generateImage(self, theme_data, forcePage=False):
|
||||
def generate_image(self, theme_data, forcePage=False):
|
||||
"""
|
||||
Call the renderer to build a Sample Image
|
||||
|
||||
@ -697,21 +704,21 @@ class ThemeManager(QtGui.QWidget):
|
||||
``forcePage``
|
||||
Flag to tell message lines per page need to be generated.
|
||||
"""
|
||||
log.debug(u'generateImage \n%s ', theme_data)
|
||||
return self.mainwindow.renderer.generate_preview(theme_data, forcePage)
|
||||
log.debug(u'generate_image \n%s ', theme_data)
|
||||
return self.renderer.generate_preview(theme_data, forcePage)
|
||||
|
||||
def getPreviewImage(self, theme):
|
||||
def get_preview_image(self, theme):
|
||||
"""
|
||||
Return an image representing the look of the theme
|
||||
|
||||
``theme``
|
||||
The theme to return the image for
|
||||
"""
|
||||
log.debug(u'getPreviewImage %s ', theme)
|
||||
log.debug(u'get_preview_image %s ', theme)
|
||||
image = os.path.join(self.path, theme + u'.png')
|
||||
return image
|
||||
|
||||
def _createThemeFromXml(self, theme_xml, path):
|
||||
def _create_theme_fom_Xml(self, theme_xml, path):
|
||||
"""
|
||||
Return a theme object using information parsed from XML
|
||||
|
||||
@ -723,16 +730,14 @@ class ThemeManager(QtGui.QWidget):
|
||||
theme.extend_image_filename(path)
|
||||
return theme
|
||||
|
||||
def _validate_theme_action(self, select_text, confirm_title, confirm_text,
|
||||
testPlugin=True, confirm=True):
|
||||
def _validate_theme_action(self, select_text, confirm_title, confirm_text, testPlugin=True, confirm=True):
|
||||
"""
|
||||
Check to see if theme has been selected and the destructive action
|
||||
is allowed.
|
||||
"""
|
||||
self.global_theme = Settings().value(
|
||||
self.settingsSection + u'/global theme', u'')
|
||||
if check_item_selected(self.themeListWidget, select_text):
|
||||
item = self.themeListWidget.currentItem()
|
||||
self.global_theme = Settings().value(self.settingsSection + u'/global theme')
|
||||
if check_item_selected(self.theme_list_widget, select_text):
|
||||
item = self.theme_list_widget.currentItem()
|
||||
theme = item.text()
|
||||
# confirm deletion
|
||||
if confirm:
|
||||
@ -748,7 +753,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
return False
|
||||
# check for use in the system else where.
|
||||
if testPlugin:
|
||||
for plugin in self.mainwindow.pluginManager.plugins:
|
||||
for plugin in self.plugin_manager.plugins:
|
||||
if plugin.usesTheme(theme):
|
||||
critical_error_message_box(translate('OpenLP.ThemeManager', 'Validation Error'),
|
||||
translate('OpenLP.ThemeManager', 'Theme %s is used in the %s plugin.') %
|
||||
@ -757,7 +762,7 @@ class ThemeManager(QtGui.QWidget):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _migrateVersion122(self, xml_data):
|
||||
def _migrate_version_122(self, xml_data):
|
||||
"""
|
||||
Convert the xml data from version 1 format to the current format.
|
||||
|
||||
@ -806,3 +811,52 @@ class ThemeManager(QtGui.QWidget):
|
||||
new_theme.display_vertical_align = vAlignCorrection
|
||||
return new_theme.extract_xml()
|
||||
|
||||
def _get_renderer(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_renderer'):
|
||||
self._renderer = Registry().get(u'renderer')
|
||||
return self._renderer
|
||||
|
||||
renderer = property(_get_renderer)
|
||||
|
||||
def _get_image_manager(self):
|
||||
"""
|
||||
Adds the image manager to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_image_manager'):
|
||||
self._image_manager = Registry().get(u'image_manager')
|
||||
return self._image_manager
|
||||
|
||||
image_manager = property(_get_image_manager)
|
||||
|
||||
def _get_plugin_manager(self):
|
||||
"""
|
||||
Adds the Renderer to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_plugin_manager'):
|
||||
self._plugin_manager = Registry().get(u'plugin_manager')
|
||||
return self._plugin_manager
|
||||
|
||||
plugin_manager = property(_get_plugin_manager)
|
||||
|
||||
def _get_main_window(self):
|
||||
"""
|
||||
Adds the main window to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_main_window'):
|
||||
self._main_window = Registry().get(u'main_window')
|
||||
return self._main_window
|
||||
|
||||
main_window = property(_get_main_window)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -26,24 +26,32 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The Themes configuration tab
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, Settings, SettingsTab, translate
|
||||
from openlp.core.lib import Receiver, Settings, SettingsTab, UiStrings, translate
|
||||
from openlp.core.lib.theme import ThemeLevel
|
||||
from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box
|
||||
from openlp.core.lib.ui import find_and_set_in_combo_box
|
||||
|
||||
|
||||
class ThemesTab(SettingsTab):
|
||||
"""
|
||||
ThemesTab is the theme settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, parent, mainwindow):
|
||||
self.mainwindow = mainwindow
|
||||
def __init__(self, parent):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
generalTranslated = translate('OpenLP.ThemesTab', 'Themes')
|
||||
SettingsTab.__init__(self, parent, u'Themes', generalTranslated)
|
||||
self.iconPath = u':/themes/theme_new.png'
|
||||
|
||||
def setupUi(self):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
self.setObjectName(u'ThemesTab')
|
||||
SettingsTab.setupUi(self)
|
||||
self.GlobalGroupBox = QtGui.QGroupBox(self.leftColumn)
|
||||
@ -99,6 +107,9 @@ class ThemesTab(SettingsTab):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList)
|
||||
|
||||
def retranslateUi(self):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
self.tabTitleVisible = UiStrings().Themes
|
||||
self.GlobalGroupBox.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
|
||||
self.LevelGroupBox.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
|
||||
@ -116,10 +127,13 @@ class ThemesTab(SettingsTab):
|
||||
'any themes associated with either the service or the songs.'))
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load the theme settings into the tab
|
||||
"""
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.theme_level = settings.value(u'theme level', ThemeLevel.Song)
|
||||
self.global_theme = settings.value(u'global theme', u'')
|
||||
self.theme_level = settings.value(u'theme level')
|
||||
self.global_theme = settings.value(u'global theme')
|
||||
settings.endGroup()
|
||||
if self.theme_level == ThemeLevel.Global:
|
||||
self.GlobalLevelRadioButton.setChecked(True)
|
||||
@ -129,30 +143,48 @@ class ThemesTab(SettingsTab):
|
||||
self.SongLevelRadioButton.setChecked(True)
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
Save the settings
|
||||
"""
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'theme level', self.theme_level)
|
||||
settings.setValue(u'global theme', self.global_theme)
|
||||
settings.endGroup()
|
||||
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||
self.renderer.set_global_theme(self.global_theme)
|
||||
self.renderer.set_theme_level(self.theme_level)
|
||||
Receiver.send_message(u'theme_update_global', self.global_theme)
|
||||
|
||||
def postSetUp(self):
|
||||
"""
|
||||
After setting things up...
|
||||
"""
|
||||
Receiver.send_message(u'theme_update_global', self.global_theme)
|
||||
|
||||
def onSongLevelButtonClicked(self):
|
||||
"""
|
||||
Set the theme level
|
||||
"""
|
||||
self.theme_level = ThemeLevel.Song
|
||||
|
||||
def onServiceLevelButtonClicked(self):
|
||||
"""
|
||||
Set the theme level
|
||||
"""
|
||||
self.theme_level = ThemeLevel.Service
|
||||
|
||||
def onGlobalLevelButtonClicked(self):
|
||||
"""
|
||||
Set the theme level
|
||||
"""
|
||||
self.theme_level = ThemeLevel.Global
|
||||
|
||||
def onDefaultComboBoxChanged(self, value):
|
||||
"""
|
||||
Set the global default theme
|
||||
"""
|
||||
self.global_theme = self.DefaultComboBox.currentText()
|
||||
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||
self.renderer.set_global_theme(self.global_theme)
|
||||
self.__previewGlobalTheme()
|
||||
|
||||
def updateThemeList(self, theme_list):
|
||||
@ -165,12 +197,12 @@ class ThemesTab(SettingsTab):
|
||||
[u'Bible Theme', u'Song Theme']
|
||||
"""
|
||||
# Reload as may have been triggered by the ThemeManager.
|
||||
self.global_theme = Settings().value(self.settingsSection + u'/global theme', u'')
|
||||
self.global_theme = Settings().value(self.settingsSection + u'/global theme')
|
||||
self.DefaultComboBox.clear()
|
||||
self.DefaultComboBox.addItems(theme_list)
|
||||
find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme)
|
||||
self.mainwindow.renderer.set_global_theme(self.global_theme)
|
||||
self.mainwindow.renderer.set_theme_level(self.theme_level)
|
||||
self.renderer.set_global_theme(self.global_theme)
|
||||
self.renderer.set_theme_level(self.theme_level)
|
||||
if self.global_theme is not u'':
|
||||
self.__previewGlobalTheme()
|
||||
|
||||
@ -178,7 +210,7 @@ class ThemesTab(SettingsTab):
|
||||
"""
|
||||
Utility method to update the global theme preview image.
|
||||
"""
|
||||
image = self.mainwindow.themeManagerContents.getPreviewImage(self.global_theme)
|
||||
image = self.theme_manager.get_preview_image(self.global_theme)
|
||||
preview = QtGui.QPixmap(unicode(image))
|
||||
if not preview.isNull():
|
||||
preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)
|
||||
|
@ -26,15 +26,24 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
"""
|
||||
The Create/Edit theme wizard
|
||||
"""
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, build_icon
|
||||
from openlp.core.lib import UiStrings, build_icon, translate
|
||||
from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
|
||||
from openlp.core.lib.ui import UiStrings, add_welcome_page, create_valign_selection_widgets
|
||||
from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
|
||||
|
||||
|
||||
class Ui_ThemeWizard(object):
|
||||
"""
|
||||
The Create/Edit theme wizard
|
||||
"""
|
||||
def setupUi(self, themeWizard):
|
||||
"""
|
||||
Set up the UI
|
||||
"""
|
||||
themeWizard.setObjectName(u'OpenLP.ThemeWizard')
|
||||
themeWizard.setModal(True)
|
||||
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
|
||||
@ -382,8 +391,11 @@ class Ui_ThemeWizard(object):
|
||||
QtCore.SLOT(u'setDisabled(bool)'))
|
||||
|
||||
def retranslateUi(self, themeWizard):
|
||||
"""
|
||||
Translate the UI on the fly
|
||||
"""
|
||||
themeWizard.setWindowTitle(translate('OpenLP.ThemeWizard', 'Theme Wizard'))
|
||||
self.titleLabel.setText(u'<span style="font-size:14pt; font-weight:600;">%s</span>' % \
|
||||
self.titleLabel.setText(u'<span style="font-size:14pt; font-weight:600;">%s</span>' %
|
||||
translate('OpenLP.ThemeWizard', 'Welcome to the Theme Wizard'))
|
||||
self.informationLabel.setText(
|
||||
translate('OpenLP.ThemeWizard', 'This wizard will help you to '
|
||||
|
@ -34,11 +34,12 @@ import os
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import build_icon, Receiver, SettingsManager, translate
|
||||
from openlp.core.lib.ui import UiStrings, add_welcome_page
|
||||
from openlp.core.lib import Receiver, Registry, Settings, UiStrings, build_icon, translate
|
||||
from openlp.core.lib.ui import add_welcome_page
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WizardStrings(object):
|
||||
"""
|
||||
Provide standard strings for wizards to use.
|
||||
@ -80,6 +81,9 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
and feel.
|
||||
"""
|
||||
def __init__(self, parent, plugin, name, image):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QWizard.__init__(self, parent)
|
||||
self.plugin = plugin
|
||||
self.setObjectName(name)
|
||||
@ -215,7 +219,7 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
self.progressLabel.setText(status_text)
|
||||
if increment > 0:
|
||||
self.progressBar.setValue(self.progressBar.value() + increment)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def preWizard(self):
|
||||
"""
|
||||
@ -233,9 +237,9 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
self.progressBar.setValue(self.progressBar.maximum())
|
||||
self.finishButton.setVisible(True)
|
||||
self.cancelButton.setVisible(False)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def getFileName(self, title, editbox, filters=u''):
|
||||
def getFileName(self, title, editbox, setting_name, filters=u''):
|
||||
"""
|
||||
Opens a QFileDialog and saves the filename to the given editbox.
|
||||
|
||||
@ -245,6 +249,9 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
``editbox``
|
||||
An editbox (QLineEdit).
|
||||
|
||||
``setting_name``
|
||||
The place where to save the last opened directory.
|
||||
|
||||
``filters``
|
||||
The file extension filters. It should contain the file description
|
||||
as well as the file extension. For example::
|
||||
@ -254,15 +261,13 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
if filters:
|
||||
filters += u';;'
|
||||
filters += u'%s (*)' % UiStrings().AllFiles
|
||||
filename = unicode(QtGui.QFileDialog.getOpenFileName(self, title,
|
||||
os.path.dirname(SettingsManager.get_last_dir(
|
||||
self.plugin.settingsSection, 1)), filters))
|
||||
filename = QtGui.QFileDialog.getOpenFileName(self, title,
|
||||
os.path.dirname(Settings().value(self.plugin.settingsSection + u'/' + setting_name)), filters)
|
||||
if filename:
|
||||
editbox.setText(filename)
|
||||
SettingsManager.set_last_dir(self.plugin.settingsSection,
|
||||
filename, 1)
|
||||
Settings().setValue(self.plugin.settingsSection + u'/' + setting_name, filename)
|
||||
|
||||
def getFolder(self, title, editbox):
|
||||
def getFolder(self, title, editbox, setting_name):
|
||||
"""
|
||||
Opens a QFileDialog and saves the selected folder to the given editbox.
|
||||
|
||||
@ -271,10 +276,23 @@ class OpenLPWizard(QtGui.QWizard):
|
||||
|
||||
``editbox``
|
||||
An editbox (QLineEdit).
|
||||
|
||||
``setting_name``
|
||||
The place where to save the last opened directory.
|
||||
"""
|
||||
folder = unicode(QtGui.QFileDialog.getExistingDirectory(self, title,
|
||||
os.path.dirname(SettingsManager.get_last_dir(self.plugin.settingsSection, 1)),
|
||||
QtGui.QFileDialog.ShowDirsOnly))
|
||||
folder = QtGui.QFileDialog.getExistingDirectory(self, title,
|
||||
Settings().value(self.plugin.settingsSection + u'/' + setting_name),
|
||||
QtGui.QFileDialog.ShowDirsOnly)
|
||||
if folder:
|
||||
editbox.setText(folder)
|
||||
SettingsManager.set_last_dir(self.plugin.settingsSection, folder, 1)
|
||||
Settings().setValue(self.plugin.settingsSection + u'/' + setting_name, folder)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -39,7 +39,7 @@ from subprocess import Popen, PIPE
|
||||
import sys
|
||||
import urllib2
|
||||
|
||||
from openlp.core.lib import Settings
|
||||
from openlp.core.lib import Registry, Settings
|
||||
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
||||
@ -61,14 +61,12 @@ UNO_CONNECTION_TYPE = u'pipe'
|
||||
CONTROL_CHARS = re.compile(r'[\x00-\x1F\x7F-\x9F]', re.UNICODE)
|
||||
INVALID_FILE_CHARS = re.compile(r'[\\/:\*\?"<>\|\+\[\]%]', re.UNICODE)
|
||||
|
||||
|
||||
class VersionThread(QtCore.QThread):
|
||||
"""
|
||||
A special Qt thread class to fetch the version of OpenLP from the website.
|
||||
This is threaded so that it doesn't affect the loading time of OpenLP.
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
QtCore.QThread.__init__(self, parent)
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run the thread.
|
||||
@ -127,7 +125,7 @@ class AppLocation(object):
|
||||
"""
|
||||
# Check if we have a different data location.
|
||||
if Settings().contains(u'advanced/data path'):
|
||||
path = Settings().value(u'advanced/data path', u'')
|
||||
path = Settings().value(u'advanced/data path')
|
||||
else:
|
||||
path = AppLocation.get_directory(AppLocation.DataDir)
|
||||
check_directory_exists(path)
|
||||
@ -154,16 +152,14 @@ def _get_os_dir_path(dir_type):
|
||||
return os.path.join(unicode(os.getenv(u'APPDATA'), encoding), u'openlp', u'data')
|
||||
elif dir_type == AppLocation.LanguageDir:
|
||||
return os.path.split(openlp.__file__)[0]
|
||||
return os.path.join(unicode(os.getenv(u'APPDATA'), encoding),
|
||||
u'openlp')
|
||||
return os.path.join(unicode(os.getenv(u'APPDATA'), encoding), u'openlp')
|
||||
elif sys.platform == u'darwin':
|
||||
if dir_type == AppLocation.DataDir:
|
||||
return os.path.join(unicode(os.getenv(u'HOME'), encoding),
|
||||
u'Library', u'Application Support', u'openlp', u'Data')
|
||||
elif dir_type == AppLocation.LanguageDir:
|
||||
return os.path.split(openlp.__file__)[0]
|
||||
return os.path.join(unicode(os.getenv(u'HOME'), encoding),
|
||||
u'Library', u'Application Support', u'openlp')
|
||||
return os.path.join(unicode(os.getenv(u'HOME'), encoding), u'Library', u'Application Support', u'openlp')
|
||||
else:
|
||||
if dir_type == AppLocation.LanguageDir:
|
||||
prefixes = [u'/usr/local', u'/usr']
|
||||
@ -277,17 +273,27 @@ def check_latest_version(current_version):
|
||||
|
||||
``current_version``
|
||||
The current version of OpenLP.
|
||||
|
||||
**Rules around versions and version files:**
|
||||
|
||||
* If a version number has a build (i.e. -bzr1234), then it is a nightly.
|
||||
* If a version number's minor version is an odd number, it is a development release.
|
||||
* If a version number's minor version is an even number, it is a stable release.
|
||||
"""
|
||||
version_string = current_version[u'full']
|
||||
# set to prod in the distribution config file.
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'general')
|
||||
last_test = settings.value(u'last version test', datetime.now().date())
|
||||
last_test = settings.value(u'last version test')
|
||||
this_test = datetime.now().date()
|
||||
settings.setValue(u'last version test', this_test)
|
||||
settings.endGroup()
|
||||
if last_test != this_test:
|
||||
if current_version[u'build']:
|
||||
req = urllib2.Request(u'http://www.openlp.org/files/nightly_version.txt')
|
||||
else:
|
||||
version_parts = current_version[u'version'].split(u'.')
|
||||
if int(version_parts[1]) % 2 != 0:
|
||||
req = urllib2.Request(u'http://www.openlp.org/files/dev_version.txt')
|
||||
else:
|
||||
req = urllib2.Request(u'http://www.openlp.org/files/version.txt')
|
||||
@ -322,8 +328,7 @@ def add_actions(target, actions):
|
||||
|
||||
def get_filesystem_encoding():
|
||||
"""
|
||||
Returns the name of the encoding used to convert Unicode filenames into
|
||||
system file names.
|
||||
Returns the name of the encoding used to convert Unicode filenames into system file names.
|
||||
"""
|
||||
encoding = sys.getfilesystemencoding()
|
||||
if encoding is None:
|
||||
@ -333,8 +338,7 @@ def get_filesystem_encoding():
|
||||
|
||||
def get_images_filter():
|
||||
"""
|
||||
Returns a filter string for a file dialog containing all the supported
|
||||
image formats.
|
||||
Returns a filter string for a file dialog containing all the supported image formats.
|
||||
"""
|
||||
global IMAGES_FILTER
|
||||
if not IMAGES_FILTER:
|
||||
@ -420,7 +424,7 @@ def get_web_page(url, header=None, update_openlp=False):
|
||||
if not page:
|
||||
return None
|
||||
if update_openlp:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Registry().get(u'application').process_events()
|
||||
log.debug(page)
|
||||
return page
|
||||
|
||||
@ -454,7 +458,7 @@ def get_uno_instance(resolver):
|
||||
|
||||
def format_time(text, local_time):
|
||||
"""
|
||||
Workaround for Python built-in time formatting fuction time.strftime().
|
||||
Workaround for Python built-in time formatting function time.strftime().
|
||||
|
||||
time.strftime() accepts only ascii characters. This function accepts
|
||||
unicode string and passes individual % placeholders to time.strftime().
|
||||
@ -462,10 +466,14 @@ def format_time(text, local_time):
|
||||
|
||||
``text``
|
||||
The text to be processed.
|
||||
|
||||
``local_time``
|
||||
The time to be used to add to the string. This is a time object
|
||||
"""
|
||||
def match_formatting(match):
|
||||
"""
|
||||
Format the match
|
||||
"""
|
||||
return local_time.strftime(match.group())
|
||||
return re.sub('\%[a-zA-Z]', match_formatting, text)
|
||||
|
||||
@ -478,22 +486,18 @@ def locale_compare(string1, string2):
|
||||
or 0, depending on whether string1 collates before or after string2 or
|
||||
is equal to it. Comparison is case insensitive.
|
||||
"""
|
||||
# Function locale.strcoll() from standard Python library does not work
|
||||
# properly on Windows.
|
||||
# Function locale.strcoll() from standard Python library does not work properly on Windows.
|
||||
return locale.strcoll(string1.lower(), string2.lower())
|
||||
|
||||
|
||||
# For performance reasons provide direct reference to compare function
|
||||
# without wrapping it in another function making te string lowercase.
|
||||
# This is needed for sorting songs.
|
||||
# For performance reasons provide direct reference to compare function without wrapping it in another function making
|
||||
# the string lowercase. This is needed for sorting songs.
|
||||
locale_direct_compare = locale.strcoll
|
||||
|
||||
|
||||
from languagemanager import LanguageManager
|
||||
from actions import ActionList
|
||||
|
||||
__all__ = [u'AppLocation', u'get_application_version', u'check_latest_version',
|
||||
u'add_actions', u'get_filesystem_encoding', u'LanguageManager',
|
||||
u'ActionList', u'get_web_page', u'get_uno_command', u'get_uno_instance',
|
||||
u'delete_file', u'clean_filename', u'format_time', u'locale_compare',
|
||||
u'locale_direct_compare']
|
||||
__all__ = [u'AppLocation', u'ActionList', u'LanguageManager', u'get_application_version', u'check_latest_version',
|
||||
u'add_actions', u'get_filesystem_encoding', u'get_web_page', u'get_uno_command', u'get_uno_instance',
|
||||
u'delete_file', u'clean_filename', u'format_time', u'locale_compare', u'locale_direct_compare']
|
||||
|
@ -41,6 +41,9 @@ class ActionCategory(object):
|
||||
category for the :class:`~openlp.core.utils.CategoryList` class.
|
||||
"""
|
||||
def __init__(self, name, weight=0):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.name = name
|
||||
self.weight = weight
|
||||
self.actions = CategoryActionList()
|
||||
@ -52,22 +55,37 @@ class CategoryActionList(object):
|
||||
list of actions within a category.
|
||||
"""
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.index = 0
|
||||
self.actions = []
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Implement the __getitem__() method to make this class a dictionary type
|
||||
"""
|
||||
for weight, action in self.actions:
|
||||
if action.text() == key:
|
||||
return action
|
||||
raise KeyError(u'Action "%s" does not exist.' % key)
|
||||
|
||||
def __contains__(self, item):
|
||||
"""
|
||||
Implement the __contains__() method to make this class a dictionary type
|
||||
"""
|
||||
return self.has_key(item)
|
||||
|
||||
def __len__(self):
|
||||
"""
|
||||
Implement the __len__() method to make this class a dictionary type
|
||||
"""
|
||||
return len(self.actions)
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Implement the __getitem__() method to make this class iterable
|
||||
"""
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
@ -88,22 +106,34 @@ class CategoryActionList(object):
|
||||
return self.__next__()
|
||||
|
||||
def has_key(self, key):
|
||||
"""
|
||||
Implement the has_key() method to make this class a dictionary type
|
||||
"""
|
||||
for weight, action in self.actions:
|
||||
if action.text() == key:
|
||||
return True
|
||||
return False
|
||||
|
||||
def append(self, name):
|
||||
"""
|
||||
Append an action
|
||||
"""
|
||||
weight = 0
|
||||
if self.actions:
|
||||
weight = self.actions[-1][0] + 1
|
||||
self.add(name, weight)
|
||||
|
||||
def add(self, action, weight=0):
|
||||
"""
|
||||
Add an action.
|
||||
"""
|
||||
self.actions.append((weight, action))
|
||||
self.actions.sort(key=lambda act: act[0])
|
||||
|
||||
def remove(self, remove_action):
|
||||
"""
|
||||
Remove an action
|
||||
"""
|
||||
for action in self.actions:
|
||||
if action[1] == remove_action:
|
||||
self.actions.remove(action)
|
||||
@ -118,22 +148,37 @@ class CategoryList(object):
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.index = 0
|
||||
self.categories = []
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Implement the __getitem__() method to make this class like a dictionary
|
||||
"""
|
||||
for category in self.categories:
|
||||
if category.name == key:
|
||||
return category
|
||||
raise KeyError(u'Category "%s" does not exist.' % key)
|
||||
|
||||
def __contains__(self, item):
|
||||
"""
|
||||
Implement the __contains__() method to make this class like a dictionary
|
||||
"""
|
||||
return self.has_key(item)
|
||||
|
||||
def __len__(self):
|
||||
"""
|
||||
Implement the __len__() method to make this class like a dictionary
|
||||
"""
|
||||
return len(self.categories)
|
||||
|
||||
def __iter__(self):
|
||||
"""
|
||||
Implement the __iter__() method to make this class like a dictionary
|
||||
"""
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
@ -154,12 +199,18 @@ class CategoryList(object):
|
||||
return self.__next__()
|
||||
|
||||
def has_key(self, key):
|
||||
"""
|
||||
Implement the has_key() method to make this class like a dictionary
|
||||
"""
|
||||
for category in self.categories:
|
||||
if category.name == key:
|
||||
return True
|
||||
return False
|
||||
|
||||
def append(self, name, actions=None):
|
||||
"""
|
||||
Append a category
|
||||
"""
|
||||
weight = 0
|
||||
if self.categories:
|
||||
weight = self.categories[-1].weight + 1
|
||||
@ -169,6 +220,9 @@ class CategoryList(object):
|
||||
self.add(name, weight)
|
||||
|
||||
def add(self, name, weight=0, actions=None):
|
||||
"""
|
||||
Add a category
|
||||
"""
|
||||
category = ActionCategory(name, weight)
|
||||
if actions:
|
||||
for action in actions:
|
||||
@ -180,6 +234,9 @@ class CategoryList(object):
|
||||
self.categories.sort(key=lambda cat: cat.weight)
|
||||
|
||||
def remove(self, name):
|
||||
"""
|
||||
Remove a category
|
||||
"""
|
||||
for category in self.categories:
|
||||
if category.name == name:
|
||||
self.categories.remove(category)
|
||||
@ -196,10 +253,16 @@ class ActionList(object):
|
||||
shortcut_map = {}
|
||||
|
||||
def __init__(self):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.categories = CategoryList()
|
||||
|
||||
@staticmethod
|
||||
def get_instance():
|
||||
"""
|
||||
Get the instance of this class.
|
||||
"""
|
||||
if ActionList.instance is None:
|
||||
ActionList.instance = ActionList()
|
||||
return ActionList.instance
|
||||
@ -233,7 +296,7 @@ class ActionList(object):
|
||||
# Load the shortcut from the config.
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'shortcuts')
|
||||
shortcuts = settings.value(action.objectName(), action.shortcuts())
|
||||
shortcuts = settings.value(action.objectName())
|
||||
settings.endGroup()
|
||||
if not shortcuts:
|
||||
action.setShortcuts([])
|
||||
|
@ -27,8 +27,7 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`languagemanager` module provides all the translation settings and
|
||||
language file loading for OpenLP.
|
||||
The :mod:`languagemanager` module provides all the translation settings and language file loading for OpenLP.
|
||||
"""
|
||||
import logging
|
||||
import re
|
||||
@ -37,10 +36,11 @@ import sys
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.utils import AppLocation
|
||||
from openlp.core.lib import translate, Settings
|
||||
from openlp.core.lib import Settings, translate
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LanguageManager(object):
|
||||
"""
|
||||
Helper for Language selection
|
||||
@ -98,7 +98,7 @@ class LanguageManager(object):
|
||||
"""
|
||||
Retrieve a saved language to use from settings
|
||||
"""
|
||||
language = Settings().value(u'general/language', u'[en]')
|
||||
language = Settings().value(u'general/language')
|
||||
language = str(language)
|
||||
log.info(u'Language file: \'%s\' Loaded from conf file' % language)
|
||||
if re.match(r'[[].*[]]', language):
|
||||
|
@ -29,12 +29,13 @@
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings
|
||||
from openlp.core.lib import Plugin, Settings, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.core.lib.ui import create_action, UiStrings
|
||||
from openlp.core.lib.theme import VerticalType
|
||||
from openlp.core.ui import AlertLocation
|
||||
from openlp.core.utils.actions import ActionList
|
||||
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
|
||||
from openlp.plugins.alerts.lib.db import init_schema
|
||||
@ -113,11 +114,22 @@ HTML = """
|
||||
<div id="alert" style="visibility:hidden"></div>
|
||||
"""
|
||||
|
||||
__default_settings__ = {
|
||||
u'alerts/font face': QtGui.QFont().family(),
|
||||
u'alerts/font size': 40,
|
||||
u'alerts/db type': u'sqlite',
|
||||
u'alerts/location': AlertLocation.Bottom,
|
||||
u'alerts/background color': u'#660000',
|
||||
u'alerts/font color': u'#ffffff',
|
||||
u'alerts/timeout': 5
|
||||
}
|
||||
|
||||
|
||||
class AlertsPlugin(Plugin):
|
||||
log.info(u'Alerts Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'alerts', plugin_helpers, settings_tab_class=AlertsTab)
|
||||
def __init__(self):
|
||||
Plugin.__init__(self, u'alerts', __default_settings__, settings_tab_class=AlertsTab)
|
||||
self.weight = -3
|
||||
self.iconPath = u':/plugins/plugin_alerts.png'
|
||||
self.icon = build_icon(self.iconPath)
|
||||
@ -139,7 +151,7 @@ class AlertsPlugin(Plugin):
|
||||
text=translate('AlertsPlugin', '&Alert'), icon=u':/plugins/plugin_alerts.png',
|
||||
statustip=translate('AlertsPlugin', 'Show an alert message.'),
|
||||
visible=False, shortcuts=[u'F7'], triggers=self.onAlertsTrigger)
|
||||
self.serviceManager.mainwindow.toolsMenu.addAction(self.toolsAlertItem)
|
||||
self.main_window.toolsMenu.addAction(self.toolsAlertItem)
|
||||
|
||||
def initialise(self):
|
||||
log.info(u'Alerts Initialising')
|
||||
|
@ -26,5 +26,31 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
Forms in OpenLP are made up of two classes. One class holds all the graphical
|
||||
elements, like buttons and lists, and the other class holds all the functional
|
||||
code, like slots and loading and saving.
|
||||
|
||||
The first class, commonly known as the **Dialog** class, is typically named
|
||||
``Ui_<name>Dialog``. It is a slightly modified version of the class that the
|
||||
``pyuic4`` command produces from Qt4's .ui file. Typical modifications will be
|
||||
converting most strings from "" to u'' and using OpenLP's ``translate()``
|
||||
function for translating strings.
|
||||
|
||||
The second class, commonly known as the **Form** class, is typically named
|
||||
``<name>Form``. This class is the one which is instantiated and used. It uses
|
||||
dual inheritance to inherit from (usually) QtGui.QDialog and the Ui class
|
||||
mentioned above, like so::
|
||||
|
||||
class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
|
||||
This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
|
||||
them separate from the functionality, so that it is easier to recreate the GUI
|
||||
from the .ui files later if necessary.
|
||||
"""
|
||||
|
||||
from alertform import AlertForm
|
||||
|
@ -77,9 +77,9 @@ class Ui_AlertDialog(object):
|
||||
displayIcon = build_icon(u':/general/general_live.png')
|
||||
self.displayButton = create_button(alertDialog, u'displayButton', icon=displayIcon, enabled=False)
|
||||
self.displayCloseButton = create_button(alertDialog, u'displayCloseButton', icon=displayIcon, enabled=False)
|
||||
self.buttonBox = create_button_box(alertDialog, u'buttonBox', [u'close'],
|
||||
self.button_box = create_button_box(alertDialog, u'button_box', [u'close'],
|
||||
[self.displayButton, self.displayCloseButton])
|
||||
self.alertDialogLayout.addWidget(self.buttonBox, 2, 0, 1, 2)
|
||||
self.alertDialogLayout.addWidget(self.button_box, 2, 0, 1, 2)
|
||||
self.retranslateUi(alertDialog)
|
||||
|
||||
def retranslateUi(self, alertDialog):
|
||||
|
@ -34,6 +34,7 @@ from openlp.plugins.alerts.lib.db import AlertItem
|
||||
|
||||
from alertdialog import Ui_AlertDialog
|
||||
|
||||
|
||||
class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
"""
|
||||
Provide UI for the alert system
|
||||
@ -45,7 +46,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
self.manager = plugin.manager
|
||||
self.plugin = plugin
|
||||
self.item_id = None
|
||||
QtGui.QDialog.__init__(self, plugin.formParent)
|
||||
super(AlertForm, self).__init__(self.plugin.main_window)
|
||||
self.setupUi(self)
|
||||
QtCore.QObject.connect(self.displayButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked)
|
||||
QtCore.QObject.connect(self.displayCloseButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayCloseClicked)
|
||||
@ -57,6 +58,9 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
QtCore.QObject.connect(self.alertListWidget, QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
|
||||
|
||||
def exec_(self):
|
||||
"""
|
||||
Execute the dialog and return the exit code.
|
||||
"""
|
||||
self.displayButton.setEnabled(False)
|
||||
self.displayCloseButton.setEnabled(False)
|
||||
self.alertTextEdit.setText(u'')
|
||||
@ -77,9 +81,15 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
self.alertListWidget.setCurrentRow(self.alertListWidget.row(item_name))
|
||||
|
||||
def onDisplayClicked(self):
|
||||
"""
|
||||
Display the current alert text.
|
||||
"""
|
||||
self.triggerAlert(self.alertTextEdit.text())
|
||||
|
||||
def onDisplayCloseClicked(self):
|
||||
"""
|
||||
Close the alert preview.
|
||||
"""
|
||||
if self.triggerAlert(self.alertTextEdit.text()):
|
||||
self.close()
|
||||
|
||||
@ -97,6 +107,9 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
self.alertTextEdit.setText(u'')
|
||||
|
||||
def onNewClick(self):
|
||||
"""
|
||||
Create a new alert.
|
||||
"""
|
||||
if not self.alertTextEdit.text():
|
||||
QtGui.QMessageBox.information(self,
|
||||
translate('AlertsPlugin.AlertForm', 'New Alert'),
|
||||
|
@ -26,6 +26,10 @@
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`~openlp.plugins.alerts.lib.alertsmanager` module contains the part of
|
||||
the plugin which manages storing and displaying of alerts.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
|
@ -29,9 +29,8 @@
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver, Settings
|
||||
from openlp.core.ui import AlertLocation
|
||||
from openlp.core.lib.ui import UiStrings, create_valign_selection_widgets
|
||||
from openlp.core.lib import SettingsTab, Receiver, Settings, UiStrings, translate
|
||||
from openlp.core.lib.ui import create_valign_selection_widgets
|
||||
|
||||
class AlertsTab(SettingsTab):
|
||||
"""
|
||||
@ -141,12 +140,12 @@ class AlertsTab(SettingsTab):
|
||||
def load(self):
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.timeout = settings.value(u'timeout', 5)
|
||||
self.font_color = settings.value(u'font color', u'#ffffff')
|
||||
self.font_size = settings.value(u'font size', 40)
|
||||
self.bg_color = settings.value(u'background color', u'#660000')
|
||||
self.font_face = settings.value(u'font face', QtGui.QFont().family())
|
||||
self.location = settings.value(u'location', AlertLocation.Bottom)
|
||||
self.timeout = settings.value(u'timeout')
|
||||
self.font_color = settings.value(u'font color')
|
||||
self.font_size = settings.value(u'font size')
|
||||
self.bg_color = settings.value(u'background color')
|
||||
self.font_face = settings.value(u'font face')
|
||||
self.location = settings.value(u'location')
|
||||
settings.endGroup()
|
||||
self.fontSizeSpinBox.setValue(self.font_size)
|
||||
self.timeoutSpinBox.setValue(self.timeout)
|
||||
@ -163,7 +162,7 @@ class AlertsTab(SettingsTab):
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
# Check value has changed as no event handles this field
|
||||
if settings.value(u'location', 1) != self.verticalComboBox.currentIndex():
|
||||
if settings.value(u'location') != self.verticalComboBox.currentIndex():
|
||||
self.changed = True
|
||||
settings.setValue(u'background color', self.bg_color)
|
||||
settings.setValue(u'font color', self.font_color)
|
||||
|
@ -29,21 +29,47 @@
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate, Settings
|
||||
from openlp.core.lib.ui import create_action, UiStrings
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.ui import UiStrings, create_action
|
||||
from openlp.core.utils.actions import ActionList
|
||||
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
|
||||
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem, LayoutStyle, DisplayStyle, \
|
||||
LanguageSelection
|
||||
from openlp.plugins.bibles.lib.mediaitem import BibleSearch
|
||||
from openlp.plugins.bibles.forms import BibleUpgradeForm
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
__default_settings__ = {
|
||||
u'bibles/db type': u'sqlite',
|
||||
u'bibles/last search type': BibleSearch.Reference,
|
||||
u'bibles/verse layout style': LayoutStyle.VersePerSlide,
|
||||
u'bibles/book name language': LanguageSelection.Bible,
|
||||
u'bibles/display brackets': DisplayStyle.NoBrackets,
|
||||
u'bibles/display new chapter': False,
|
||||
u'bibles/second bibles': True,
|
||||
u'bibles/advanced bible': u'',
|
||||
u'bibles/quick bible': u'',
|
||||
u'bibles/proxy name': u'',
|
||||
u'bibles/proxy address': u'',
|
||||
u'bibles/proxy username': u'',
|
||||
u'bibles/proxy password': u'',
|
||||
u'bibles/bible theme': u'',
|
||||
u'bibles/verse separator': u'',
|
||||
u'bibles/range separator': u'',
|
||||
u'bibles/list separator': u'',
|
||||
u'bibles/end separator': u'',
|
||||
u'bibles/last directory import': u''
|
||||
}
|
||||
|
||||
|
||||
class BiblePlugin(Plugin):
|
||||
log.info(u'Bible Plugin loaded')
|
||||
|
||||
def __init__(self, plugin_helpers):
|
||||
Plugin.__init__(self, u'bibles', plugin_helpers, BibleMediaItem, BiblesTab)
|
||||
def __init__(self):
|
||||
Plugin.__init__(self, u'bibles', __default_settings__, BibleMediaItem, BiblesTab)
|
||||
self.weight = -9
|
||||
self.iconPath = u':/plugins/plugin_bibles.png'
|
||||
self.icon = build_icon(self.iconPath)
|
||||
@ -76,24 +102,19 @@ class BiblePlugin(Plugin):
|
||||
#action_list.remove_action(self.exportBibleItem, UiStrings().Export)
|
||||
self.exportBibleItem.setVisible(False)
|
||||
|
||||
def appStartup(self):
|
||||
def app_startup(self):
|
||||
"""
|
||||
Perform tasks on application startup
|
||||
"""
|
||||
Plugin.app_startup(self)
|
||||
if self.manager.old_bible_databases:
|
||||
if QtGui.QMessageBox.information(self.formParent,
|
||||
if QtGui.QMessageBox.information(self.main_window,
|
||||
translate('OpenLP', 'Information'),
|
||||
translate('OpenLP', 'Bible format has changed.\nYou have to upgrade your existing Bibles.\n'
|
||||
'Should OpenLP upgrade now?'),
|
||||
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) == \
|
||||
QtGui.QMessageBox.Yes:
|
||||
self.onToolsUpgradeItemTriggered()
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
if settings.contains(u'bookname language'):
|
||||
settings.setValue(u'book name language', settings.value(u'bookname language', 0))
|
||||
settings.remove(u'bookname language')
|
||||
settings.endGroup()
|
||||
|
||||
def addImportMenuItem(self, import_menu):
|
||||
self.importBibleItem = create_action(import_menu, u'importBibleItem',
|
||||
@ -128,7 +149,7 @@ class BiblePlugin(Plugin):
|
||||
Upgrade older bible databases.
|
||||
"""
|
||||
if not hasattr(self, u'upgrade_wizard'):
|
||||
self.upgrade_wizard = BibleUpgradeForm(self.formParent, self.manager, self)
|
||||
self.upgrade_wizard = BibleUpgradeForm(self.main_window, self.manager, self)
|
||||
# If the import was not cancelled then reload.
|
||||
if self.upgrade_wizard.exec_():
|
||||
self.mediaItem.reloadBibles()
|
||||
|
@ -34,9 +34,9 @@ import os
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, translate, Settings
|
||||
from openlp.core.lib import Settings, UiStrings, translate
|
||||
from openlp.core.lib.db import delete_database
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||
from openlp.core.utils import AppLocation, locale_compare
|
||||
from openlp.plugins.bibles.lib.manager import BibleFormat
|
||||
@ -469,34 +469,34 @@ class BibleImportForm(OpenLPWizard):
|
||||
"""
|
||||
Show the file open dialog for the OSIS file.
|
||||
"""
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OSIS, self.osisFileEdit)
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OSIS, self.osisFileEdit, u'last directory import')
|
||||
|
||||
def onCsvBooksBrowseButtonClicked(self):
|
||||
"""
|
||||
Show the file open dialog for the books CSV file.
|
||||
"""
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, self.csvBooksEdit, u'%s (*.csv)'
|
||||
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, self.csvBooksEdit, u'last directory import',
|
||||
u'%s (*.csv)' % translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
|
||||
|
||||
def onCsvVersesBrowseButtonClicked(self):
|
||||
"""
|
||||
Show the file open dialog for the verses CSV file.
|
||||
"""
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, self.csvVersesEdit, u'%s (*.csv)'
|
||||
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, self.csvVersesEdit, u'last directory import',
|
||||
u'%s (*.csv)' % translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
|
||||
|
||||
def onOpenSongBrowseButtonClicked(self):
|
||||
"""
|
||||
Show the file open dialog for the OpenSong file.
|
||||
"""
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OS, self.openSongFileEdit)
|
||||
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OS, self.openSongFileEdit, u'last directory import')
|
||||
|
||||
def onOpenlp1BrowseButtonClicked(self):
|
||||
"""
|
||||
Show the file open dialog for the openlp.org 1.x file.
|
||||
"""
|
||||
self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV1, self.openlp1FileEdit, u'%s (*.bible)' %
|
||||
translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x Bible Files'))
|
||||
self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV1, self.openlp1FileEdit, u'last directory import',
|
||||
u'%s (*.bible)' % translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x Bible Files'))
|
||||
|
||||
def registerFields(self):
|
||||
"""
|
||||
@ -533,9 +533,9 @@ class BibleImportForm(OpenLPWizard):
|
||||
self.setField(u'opensong_file', '')
|
||||
self.setField(u'web_location', WebDownload.Crosswalk)
|
||||
self.setField(u'web_biblename', self.webTranslationComboBox.currentIndex())
|
||||
self.setField(u'proxy_server', settings.value(u'proxy address', u''))
|
||||
self.setField(u'proxy_username', settings.value(u'proxy username', u''))
|
||||
self.setField(u'proxy_password', settings.value(u'proxy password', u''))
|
||||
self.setField(u'proxy_server', settings.value(u'proxy address'))
|
||||
self.setField(u'proxy_username', settings.value(u'proxy username'))
|
||||
self.setField(u'proxy_password', settings.value(u'proxy password'))
|
||||
self.setField(u'openlp1_location', '')
|
||||
self.setField(u'license_version', self.versionNameEdit.text())
|
||||
self.setField(u'license_copyright', self.copyrightEdit.text())
|
||||
@ -578,7 +578,7 @@ class BibleImportForm(OpenLPWizard):
|
||||
self.progressLabel.setText(translate('BiblesPlugin.ImportWizardForm', 'Registering Bible...'))
|
||||
else:
|
||||
self.progressLabel.setText(WizardStrings.StartingImport)
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def performWizard(self):
|
||||
"""
|
||||
|
@ -36,8 +36,8 @@ from tempfile import gettempdir
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, SettingsManager, translate, check_directory_exists, Settings
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.lib import Receiver, Settings, UiStrings, translate, check_directory_exists
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
|
||||
from openlp.core.utils import AppLocation, delete_file, get_filesystem_encoding
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB, BiblesResourcesDB
|
||||
@ -116,11 +116,9 @@ class BibleUpgradeForm(OpenLPWizard):
|
||||
Show the file open dialog for the OSIS file.
|
||||
"""
|
||||
filename = QtGui.QFileDialog.getExistingDirectory(self,
|
||||
translate('BiblesPlugin.UpgradeWizardForm', 'Select a Backup Directory'),
|
||||
os.path.dirname(SettingsManager.get_last_dir(self.plugin.settingsSection, 1)))
|
||||
translate('BiblesPlugin.UpgradeWizardForm', 'Select a Backup Directory'), u'')
|
||||
if filename:
|
||||
self.backupDirectoryEdit.setText(filename)
|
||||
SettingsManager.set_last_dir(self.plugin.settingsSection, filename, 1)
|
||||
|
||||
def onNoBackupCheckBoxToggled(self, checked):
|
||||
"""
|
||||
@ -337,7 +335,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
||||
"""
|
||||
OpenLPWizard.preWizard(self)
|
||||
self.progressLabel.setText(translate('BiblesPlugin.UpgradeWizardForm', 'Starting upgrade...'))
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
|
||||
def performWizard(self):
|
||||
"""
|
||||
@ -467,7 +465,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
||||
self.newbibles[number].create_verse(db_book.id,
|
||||
int(verse[u'chapter']),
|
||||
int(verse[u'verse']), unicode(verse[u'text']))
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
self.newbibles[number].session.commit()
|
||||
else:
|
||||
language_id = self.newbibles[number].get_object(BibleMeta, u'language_id')
|
||||
@ -513,7 +511,7 @@ class BibleUpgradeForm(OpenLPWizard):
|
||||
self.newbibles[number].create_verse(db_book.id,
|
||||
int(verse[u'chapter']),
|
||||
int(verse[u'verse']), unicode(verse[u'text']))
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
self.newbibles[number].session.commit()
|
||||
if not self.success.get(number, True):
|
||||
self.incrementProgressBar(translate('BiblesPlugin.UpgradeWizardForm',
|
||||
|
@ -80,8 +80,8 @@ class Ui_BookNameDialog(object):
|
||||
self.apocryphaCheckBox.setCheckState(QtCore.Qt.Checked)
|
||||
self.optionsLayout.addWidget(self.apocryphaCheckBox)
|
||||
self.bookNameLayout.addWidget(self.optionsGroupBox)
|
||||
self.buttonBox = create_button_box(bookNameDialog, u'buttonBox', [u'cancel', u'ok'])
|
||||
self.bookNameLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(bookNameDialog, u'button_box', [u'cancel', u'ok'])
|
||||
self.bookNameLayout.addWidget(self.button_box)
|
||||
|
||||
self.retranslateUi(bookNameDialog)
|
||||
|
||||
|
@ -44,7 +44,7 @@ class Ui_EditBibleDialog(object):
|
||||
self.dialogLayout = QtGui.QVBoxLayout(editBibleDialog)
|
||||
self.dialogLayout.setSpacing(8)
|
||||
self.dialogLayout.setContentsMargins(8, 8, 8, 8)
|
||||
self.dialogLayout.setObjectName(u'dialogLayout')
|
||||
self.dialogLayout.setObjectName(u'dialog_layout')
|
||||
self.bibleTabWidget = QtGui.QTabWidget(editBibleDialog)
|
||||
self.bibleTabWidget.setObjectName(u'BibleTabWidget')
|
||||
# Meta tab
|
||||
@ -121,8 +121,8 @@ class Ui_EditBibleDialog(object):
|
||||
self.bibleTabWidget.addTab(self.bookNameTab, u'')
|
||||
# Last few bits
|
||||
self.dialogLayout.addWidget(self.bibleTabWidget)
|
||||
self.buttonBox = create_button_box(editBibleDialog, u'buttonBox', [u'cancel', u'save'])
|
||||
self.dialogLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(editBibleDialog, u'button_box', [u'cancel', u'save'])
|
||||
self.dialogLayout.addWidget(self.button_box)
|
||||
self.retranslateUi(editBibleDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(editBibleDialog)
|
||||
|
||||
|
@ -32,8 +32,8 @@ import re
|
||||
|
||||
from PyQt4 import QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.lib.ui import UiStrings, critical_error_message_box
|
||||
from openlp.core.lib import Registry, UiStrings, translate
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from editbibledialog import Ui_EditBibleDialog
|
||||
from openlp.plugins.bibles.lib import BibleStrings
|
||||
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
|
||||
@ -122,8 +122,7 @@ class EditBibleForm(QtGui.QDialog, Ui_EditBibleDialog):
|
||||
if book.name != custom_names[abbr]:
|
||||
if not self.validateBook(custom_names[abbr], abbr):
|
||||
return
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
Receiver.send_message(u'cursor_busy')
|
||||
self.application.set_busy_cursor()
|
||||
self.manager.save_meta_data(self.bible, version, copyright, permissions, book_name_language)
|
||||
if not self.webbible:
|
||||
for abbr, book in self.books.iteritems():
|
||||
@ -132,7 +131,7 @@ class EditBibleForm(QtGui.QDialog, Ui_EditBibleDialog):
|
||||
book.name = custom_names[abbr]
|
||||
self.manager.update_book(self.bible, book)
|
||||
self.bible = None
|
||||
Receiver.send_message(u'cursor_normal')
|
||||
self.application.set_normal_cursor()
|
||||
QtGui.QDialog.accept(self)
|
||||
|
||||
def validateMeta(self, name, copyright):
|
||||
@ -189,3 +188,13 @@ class EditBibleForm(QtGui.QDialog, Ui_EditBibleDialog):
|
||||
% new_book_name)
|
||||
return False
|
||||
return True
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
@ -62,8 +62,8 @@ class Ui_LanguageDialog(object):
|
||||
self.languageComboBox.setObjectName(u'languageComboBox')
|
||||
self.languageHBoxLayout.addWidget(self.languageComboBox)
|
||||
self.languageLayout.addLayout(self.languageHBoxLayout)
|
||||
self.buttonBox = create_button_box(languageDialog, u'buttonBox', [u'cancel', u'ok'])
|
||||
self.languageLayout.addWidget(self.buttonBox)
|
||||
self.button_box = create_button_box(languageDialog, u'button_box', [u'cancel', u'ok'])
|
||||
self.languageLayout.addWidget(self.button_box)
|
||||
|
||||
self.retranslateUi(languageDialog)
|
||||
|
||||
|
@ -33,8 +33,8 @@ plugin.
|
||||
import logging
|
||||
import re
|
||||
|
||||
from openlp.core.lib import translate, Settings
|
||||
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
|
||||
from openlp.core.lib import Settings, translate
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -187,10 +187,10 @@ def update_reference_separators():
|
||||
settings = Settings()
|
||||
settings.beginGroup(u'bibles')
|
||||
custom_separators = [
|
||||
settings.value(u'verse separator', u''),
|
||||
settings.value(u'range separator', u''),
|
||||
settings.value(u'list separator', u''),
|
||||
settings.value(u'end separator', u'')]
|
||||
settings.value(u'verse separator'),
|
||||
settings.value(u'range separator'),
|
||||
settings.value(u'list separator'),
|
||||
settings.value(u'end separator')]
|
||||
settings.endGroup()
|
||||
for index, role in enumerate([u'v', u'r', u'l', u'e']):
|
||||
if custom_separators[index].strip(u'|') == u'':
|
||||
|
@ -31,8 +31,8 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, SettingsTab, translate, Settings
|
||||
from openlp.core.lib.ui import UiStrings, find_and_set_in_combo_box
|
||||
from openlp.core.lib import Receiver, SettingsTab, Settings, UiStrings, translate
|
||||
from openlp.core.lib.ui import find_and_set_in_combo_box
|
||||
from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, update_reference_separators, \
|
||||
get_reference_separator, LanguageSelection
|
||||
|
||||
@ -331,16 +331,16 @@ class BiblesTab(SettingsTab):
|
||||
def load(self):
|
||||
settings = Settings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
self.show_new_chapters = settings.value(u'display new chapter', False)
|
||||
self.display_style = settings.value(u'display brackets', 0)
|
||||
self.layout_style = settings.value(u'verse layout style', 0)
|
||||
self.bible_theme = settings.value(u'bible theme', u'')
|
||||
self.second_bibles = settings.value(u'second bibles', True)
|
||||
self.show_new_chapters = settings.value(u'display new chapter')
|
||||
self.display_style = settings.value(u'display brackets')
|
||||
self.layout_style = settings.value(u'verse layout style')
|
||||
self.bible_theme = settings.value(u'bible theme')
|
||||
self.second_bibles = settings.value(u'second bibles')
|
||||
self.newChaptersCheckBox.setChecked(self.show_new_chapters)
|
||||
self.displayStyleComboBox.setCurrentIndex(self.display_style)
|
||||
self.layoutStyleComboBox.setCurrentIndex(self.layout_style)
|
||||
self.bibleSecondCheckBox.setChecked(self.second_bibles)
|
||||
verse_separator = settings.value(u'verse separator', u'')
|
||||
verse_separator = settings.value(u'verse separator')
|
||||
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))
|
||||
@ -349,7 +349,7 @@ class BiblesTab(SettingsTab):
|
||||
self.verseSeparatorLineEdit.setText(verse_separator)
|
||||
self.verseSeparatorLineEdit.setPalette(self.getGreyTextPalette(False))
|
||||
self.verseSeparatorCheckBox.setChecked(True)
|
||||
range_separator = settings.value(u'range separator', u'')
|
||||
range_separator = settings.value(u'range separator')
|
||||
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))
|
||||
@ -358,7 +358,7 @@ class BiblesTab(SettingsTab):
|
||||
self.rangeSeparatorLineEdit.setText(range_separator)
|
||||
self.rangeSeparatorLineEdit.setPalette(self.getGreyTextPalette(False))
|
||||
self.rangeSeparatorCheckBox.setChecked(True)
|
||||
list_separator = settings.value(u'list separator', u'')
|
||||
list_separator = settings.value(u'list separator')
|
||||
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))
|
||||
@ -367,7 +367,7 @@ class BiblesTab(SettingsTab):
|
||||
self.listSeparatorLineEdit.setText(list_separator)
|
||||
self.listSeparatorLineEdit.setPalette(self.getGreyTextPalette(False))
|
||||
self.listSeparatorCheckBox.setChecked(True)
|
||||
end_separator = settings.value(u'end separator', u'')
|
||||
end_separator = settings.value(u'end separator')
|
||||
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))
|
||||
@ -376,7 +376,7 @@ class BiblesTab(SettingsTab):
|
||||
self.endSeparatorLineEdit.setText(end_separator)
|
||||
self.endSeparatorLineEdit.setPalette(self.getGreyTextPalette(False))
|
||||
self.endSeparatorCheckBox.setChecked(True)
|
||||
self.language_selection = settings.value(u'book name language', 0)
|
||||
self.language_selection = settings.value(u'book name language')
|
||||
self.languageSelectionComboBox.setCurrentIndex(self.language_selection)
|
||||
settings.endGroup()
|
||||
|
||||
|
@ -62,7 +62,7 @@ import logging
|
||||
import chardet
|
||||
import csv
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.lib import translate
|
||||
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -118,7 +118,7 @@ class CSVBible(BibleDB):
|
||||
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
|
||||
self.create_book(unicode(line[2], details['encoding']), book_ref_id, book_details[u'testament_id'])
|
||||
book_list[int(line[0])] = unicode(line[2], details['encoding'])
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
except (IOError, IndexError):
|
||||
log.exception(u'Loading books from file failed')
|
||||
success = False
|
||||
@ -157,7 +157,7 @@ class CSVBible(BibleDB):
|
||||
verse_text = unicode(line[3], u'cp1252')
|
||||
self.create_verse(book.id, line[1], line[2], verse_text)
|
||||
self.wizard.incrementProgressBar(translate('BiblesPlugin.CSVBible', 'Importing verses... done.'))
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
self.application.process_events()
|
||||
self.session.commit()
|
||||
except IOError:
|
||||
log.exception(u'Loading verses from file failed')
|
||||
|
@ -34,11 +34,11 @@ import re
|
||||
import sqlite3
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from sqlalchemy import Column, ForeignKey, or_, Table, types, func
|
||||
from sqlalchemy import Column, ForeignKey, Table, or_, types, func
|
||||
from sqlalchemy.orm import class_mapper, mapper, relation
|
||||
from sqlalchemy.orm.exc import UnmappedClassError
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from openlp.core.lib import Receiver, Registry, translate
|
||||
from openlp.core.lib.db import BaseModel, init_db, Manager
|
||||
from openlp.core.lib.ui import critical_error_message_box
|
||||
from openlp.core.utils import AppLocation, clean_filename
|
||||
@ -549,6 +549,16 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
verses = self.session.query(Verse).all()
|
||||
log.debug(verses)
|
||||
|
||||
def _get_application(self):
|
||||
"""
|
||||
Adds the openlp to the class dynamically
|
||||
"""
|
||||
if not hasattr(self, u'_application'):
|
||||
self._application = Registry().get(u'application')
|
||||
return self._application
|
||||
|
||||
application = property(_get_application)
|
||||
|
||||
|
||||
class BiblesResourcesDB(QtCore.QObject, Manager):
|
||||
"""
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user