diff --git a/.bzrignore b/.bzrignore
index 7bea0adb9..00884055d 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -10,3 +10,7 @@ openlp.org 2.0.e4*
documentation/build/html
documentation/build/doctrees
*.log*
+dist
+OpenLP.egg-info
+build
+resources/innosetup/Output
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 000000000..73ff3c545
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,12 @@
+recursive-include openlp *.py
+recursive-include openlp *.sqlite
+recursive-include openlp *.csv
+recursive-include documentation *
+recursive-include resources/forms *
+recursive-include resources/i18n *
+recursive-include resources/images *
+recursive-include scripts *.py
+include resources/*.desktop
+include copyright.txt
+include LICENSE
+include openlp/.version
diff --git a/OpenLP.spec b/OpenLP.spec
new file mode 100644
index 000000000..366bdf31d
--- /dev/null
+++ b/OpenLP.spec
@@ -0,0 +1,19 @@
+# -*- mode: python -*-
+a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'openlp.pyw'],
+ pathex=['c:\\Documents and Settings\\raoul\\My Documents\\My Projects\\openlp\\pyinstaller'])
+pyz = PYZ(a.pure)
+exe = EXE(pyz,
+ a.scripts,
+ exclude_binaries=1,
+ name=os.path.join('build\\pyi.win32\\OpenLP', 'OpenLP.exe'),
+ debug=False,
+ strip=False,
+ upx=True,
+ console=False , icon='resources\\images\\OpenLP.ico')
+coll = COLLECT( exe,
+ a.binaries,
+ a.zipfiles,
+ a.datas,
+ strip=False,
+ upx=True,
+ name=os.path.join('dist', 'OpenLP'))
diff --git a/openlp.pyw b/openlp.pyw
index 8b847c0ec..c4a5fb428 100755
--- a/openlp.pyw
+++ b/openlp.pyw
@@ -28,16 +28,17 @@ import os
import sys
import logging
-from logging.handlers import RotatingFileHandler
+from logging import FileHandler
from optparse import OptionParser
from PyQt4 import QtCore, QtGui
+log = logging.getLogger()
+
+import openlp
from openlp.core.lib import Receiver, str_to_bool
from openlp.core.resources import qInitResources
-from openlp.core.ui import MainWindow, SplashScreen
-from openlp.core.utils import ConfigHelper
-
-log = logging.getLogger()
+from openlp.core.ui import MainWindow, SplashScreen, ScreenList
+from openlp.core.utils import AppLocation, ConfigHelper
application_stylesheet = u"""
QMainWindow::separator
@@ -47,9 +48,11 @@ QMainWindow::separator
QDockWidget::title
{
- border: none;
+ /*background: palette(dark);*/
+ border: 1px solid palette(dark);
padding-left: 5px;
- padding-top: 3px;
+ padding-top: 2px;
+ margin: 1px 0;
}
QToolBar
@@ -65,16 +68,21 @@ class OpenLP(QtGui.QApplication):
The core application class. This class inherits from Qt's QApplication
class in order to provide the core of the application.
"""
- global log
log.info(u'OpenLP Application Loaded')
+ def notify(self, obj, evt):
+ #TODO needed for presentation exceptions
+ return QtGui.QApplication.notify(self, obj, evt)
+
def run(self):
"""
Run the OpenLP application.
"""
#Load and store current Application Version
- filepath = os.path.split(os.path.abspath(__file__))[0]
- filepath = os.path.abspath(os.path.join(filepath, u'version.txt'))
+ filepath = AppLocation.get_directory(AppLocation.AppDir)
+ if not hasattr(sys, u'frozen'):
+ filepath = os.path.join(filepath, u'openlp')
+ filepath = os.path.join(filepath, u'.version')
fversion = None
try:
fversion = open(filepath, u'r')
@@ -91,9 +99,9 @@ class OpenLP(QtGui.QApplication):
app_version[u'version'], app_version[u'build']))
except:
app_version = {
- u'full': u'1.9.0-000',
+ u'full': u'1.9.0-bzr000',
u'version': u'1.9.0',
- u'build': u'000'
+ u'build': u'bzr000'
}
finally:
if fversion:
@@ -117,10 +125,10 @@ class OpenLP(QtGui.QApplication):
self.splash.show()
# make sure Qt really display the splash screen
self.processEvents()
- screens = []
+ screens = ScreenList()
# Decide how many screens we have and their size
for screen in xrange(0, self.desktop().numScreens()):
- screens.append({u'number': screen,
+ screens.add_screen({u'number': screen,
u'size': self.desktop().availableGeometry(screen),
u'primary': (self.desktop().primaryScreen() == screen)})
log.info(u'Screen %d found with resolution %s',
@@ -131,7 +139,8 @@ class OpenLP(QtGui.QApplication):
if show_splash:
# now kill the splashscreen
self.splash.finish(self.mainWindow)
- self.mainWindow.versionCheck()
+ self.mainWindow.repaint()
+ self.mainWindow.versionThread()
return self.exec_()
def main():
@@ -143,7 +152,7 @@ def main():
usage = u'Usage: %prog [options] [qt-options]'
parser = OptionParser(usage=usage)
parser.add_option("-l", "--log-level", dest="loglevel",
- default="info", metavar="LEVEL",
+ default="warning", metavar="LEVEL",
help="Set logging to LEVEL level. Valid values are "
"\"debug\", \"info\", \"warning\".")
parser.add_option("-p", "--portable", dest="portable",
@@ -153,10 +162,13 @@ def main():
parser.add_option("-s", "--style", dest="style",
help="Set the Qt4 style (passed directly to Qt4).")
# Set up logging
- filename = u'openlp.log'
- logfile = RotatingFileHandler(filename, maxBytes=200000, backupCount=5)
+ log_path = AppLocation.get_directory(AppLocation.ConfigDir)
+ if not os.path.exists(log_path):
+ os.makedirs(log_path)
+ filename = os.path.join(log_path, u'openlp.log')
+ logfile = FileHandler(filename, u'w')
logfile.setFormatter(logging.Formatter(
- u'%(asctime)s %(name)-15s %(levelname)-8s %(message)s'))
+ u'%(asctime)s %(name)-20s %(levelname)-8s %(message)s'))
log.addHandler(logfile)
logging.addLevelName(15, u'Timer')
# Parse command line options and deal with them.
@@ -164,6 +176,7 @@ def main():
qt_args = []
if options.loglevel.lower() in ['d', 'debug']:
log.setLevel(logging.DEBUG)
+ print 'Logging to:', filename
elif options.loglevel.lower() in ['w', 'warning']:
log.setLevel(logging.WARNING)
else:
@@ -182,4 +195,4 @@ if __name__ == u'__main__':
"""
Instantiate and run the application.
"""
- main()
\ No newline at end of file
+ main()
diff --git a/openlp/.version b/openlp/.version
new file mode 100644
index 000000000..4489023a7
--- /dev/null
+++ b/openlp/.version
@@ -0,0 +1 @@
+1.9.0-bzr722
diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py
index 22df9a926..899b5cf73 100644
--- a/openlp/core/lib/__init__.py
+++ b/openlp/core/lib/__init__.py
@@ -136,6 +136,26 @@ def contextMenuSeparator(base):
action.setSeparator(True)
return action
+def resize_image(image, width, height):
+ """
+ Resize an image to fit on the current screen.
+
+ ``image``
+ The image to resize.
+ """
+ preview = QtGui.QImage(image)
+ preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
+ QtCore.Qt.SmoothTransformation)
+ realw = preview.width()
+ realh = preview.height()
+ # and move it to the centre of the preview space
+ newImage = QtGui.QImage(width, height, QtGui.QImage.Format_ARGB32_Premultiplied)
+ newImage.fill(QtCore.Qt.black)
+ painter = QtGui.QPainter(newImage)
+ painter.drawImage((width - realw) / 2, (height - realh) / 2, preview)
+ return newImage
+
+
class ThemeLevel(object):
Global = 1
Service = 2
@@ -160,6 +180,3 @@ from renderer import Renderer
from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem
from baselistwithdnd import BaseListWithDnD
-
-#__all__ = [ 'translate', 'get_text_file_string', 'str_to_bool',
-# 'contextMenuAction', 'contextMenuSeparator', 'ServiceItem']
\ No newline at end of file
diff --git a/openlp/core/lib/baselistwithdnd.py b/openlp/core/lib/baselistwithdnd.py
index d2537e0e4..f7095550a 100644
--- a/openlp/core/lib/baselistwithdnd.py
+++ b/openlp/core/lib/baselistwithdnd.py
@@ -32,6 +32,7 @@ class BaseListWithDnD(QtGui.QListWidget):
def __init__(self, parent=None):
QtGui.QListWidget.__init__(self, parent)
+ self.parent = parent
# this must be set by the class which is inheriting
assert(self.PluginName)
@@ -47,4 +48,5 @@ class BaseListWithDnD(QtGui.QListWidget):
mimeData = QtCore.QMimeData()
drag.setMimeData(mimeData)
mimeData.setText(self.PluginName)
- dropAction = drag.start(QtCore.Qt.CopyAction)
\ No newline at end of file
+ dropAction = drag.start(QtCore.Qt.CopyAction)
+
diff --git a/openlp/core/lib/dockwidget.py b/openlp/core/lib/dockwidget.py
index 6d205cb29..ce8302b43 100644
--- a/openlp/core/lib/dockwidget.py
+++ b/openlp/core/lib/dockwidget.py
@@ -27,6 +27,8 @@ import logging
from PyQt4 import QtGui
+log = logging.getLogger(__name__)
+
class OpenLPDockWidget(QtGui.QDockWidget):
"""
Custom DockWidget class to handle events
@@ -40,10 +42,9 @@ class OpenLPDockWidget(QtGui.QDockWidget):
if name:
self.setObjectName(name)
self.setFloating(False)
- self.log = logging.getLogger(u'OpenLPDockWidget')
- self.log.debug(u'Init done')
+ log.debug(u'Init done')
def closeEvent(self, event):
self.parent.settingsmanager.setUIItemVisibility(
self.objectName(), False)
- event.accept()
\ No newline at end of file
+ event.accept()
diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py
index f3b43d2b7..be7dff67a 100644
--- a/openlp/core/lib/eventreceiver.py
+++ b/openlp/core/lib/eventreceiver.py
@@ -27,6 +27,8 @@ import logging
from PyQt4 import QtCore
+log = logging.getLogger(__name__)
+
class EventReceiver(QtCore.QObject):
"""
Class to allow events to be passed from different parts of the
@@ -104,10 +106,10 @@ class EventReceiver(QtCore.QObject):
``remote_edit_clear``
Informs all components that remote edit has been aborted.
- """
- global log
- log = logging.getLogger(u'EventReceiver')
+ ``presentation types``
+ Informs all components of the presentation types supported.
+ """
def __init__(self):
"""
Initialise the event receiver, calling the parent constructor.
@@ -161,4 +163,5 @@ class Receiver():
"""
Get the global ``eventreceiver`` instance.
"""
- return Receiver.eventreceiver
\ No newline at end of file
+ return Receiver.eventreceiver
+
diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py
index 6f6f82818..fd6d37ca6 100644
--- a/openlp/core/lib/mediamanageritem.py
+++ b/openlp/core/lib/mediamanageritem.py
@@ -32,6 +32,8 @@ from openlp.core.lib.toolbar import *
from openlp.core.lib import contextMenuAction, contextMenuSeparator
from serviceitem import ServiceItem
+log = logging.getLogger(__name__)
+
class MediaManagerItem(QtGui.QWidget):
"""
MediaManagerItem is a helper widget for plugins.
@@ -92,9 +94,6 @@ class MediaManagerItem(QtGui.QWidget):
method is not defined, a default will be used (treat the
filename as an image).
"""
-
- global log
- log = logging.getLogger(u'MediaManagerItem')
log.info(u'Media Item loaded')
def __init__(self, parent=None, icon=None, title=None):
@@ -253,7 +252,7 @@ class MediaManagerItem(QtGui.QWidget):
def addListViewToToolBar(self):
#Add the List widget
- self.ListView = self.ListViewWithDnD_class()
+ self.ListView = self.ListViewWithDnD_class(self)
self.ListView.uniformItemSizes = True
self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591))
self.ListView.setSpacing(1)
@@ -315,7 +314,7 @@ class MediaManagerItem(QtGui.QWidget):
self, self.OnNewPrompt,
self.parent.config.get_last_dir(), self.OnNewFileMasks)
log.info(u'New files(s)%s', unicode(files))
- if len(files) > 0:
+ if files:
self.loadList(files)
dir, filename = os.path.split(unicode(files[0]))
self.parent.config.set_last_dir(dir)
@@ -400,4 +399,4 @@ class MediaManagerItem(QtGui.QWidget):
if self.generateSlideData(service_item):
return service_item
else:
- return None
\ No newline at end of file
+ return None
diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py
index 598c594fd..e98c789d0 100644
--- a/openlp/core/lib/plugin.py
+++ b/openlp/core/lib/plugin.py
@@ -28,6 +28,8 @@ from PyQt4 import QtCore
from openlp.core.lib import PluginConfig, Receiver
+log = logging.getLogger(__name__)
+
class PluginStatus(object):
"""
Defines the status of the plugin
@@ -88,8 +90,6 @@ class Plugin(QtCore.QObject):
Used in the plugin manager, when a person clicks on the 'About' button.
"""
- global log
- log = logging.getLogger(u'Plugin')
log.info(u'loaded')
def __init__(self, name, version=None, plugin_helpers=None):
@@ -127,6 +127,7 @@ class Plugin(QtCore.QObject):
self.service_manager = plugin_helpers[u'service']
self.settings = plugin_helpers[u'settings']
self.mediadock = plugin_helpers[u'toolbox']
+ self.maindisplay = plugin_helpers[u'maindisplay']
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_add_service_item' % self.name),
self.process_add_service_event)
@@ -252,4 +253,10 @@ class Plugin(QtCore.QObject):
if self.media_item:
self.mediadock.insert_dock(self.media_item, self.icon, self.weight)
if self.settings_tab:
- self.settings.insertTab(self.settings_tab, self.weight)
\ No newline at end of file
+ self.settings.insertTab(self.settings_tab, self.weight)
+
+ def can_delete_theme(self, theme):
+ """
+ Called to ask the plugin if a theme can be deleted
+ """
+ return True
diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py
index c580555ff..2518f88be 100644
--- a/openlp/core/lib/pluginmanager.py
+++ b/openlp/core/lib/pluginmanager.py
@@ -29,13 +29,13 @@ import logging
from openlp.core.lib import Plugin, PluginStatus
+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.
"""
- global log
- log = logging.getLogger(u'PluginMgr')
log.info(u'Plugin manager loaded')
def __init__(self, dir):
@@ -54,7 +54,7 @@ class PluginManager(object):
log.debug(u'Base path %s ', self.basepath)
self.plugins = []
# this has to happen after the UI is sorted self.find_plugins(dir)
- log.info(u'Plugin manager done init')
+ log.info(u'Plugin manager Initialised')
def find_plugins(self, dir, plugin_helpers):
"""
@@ -77,7 +77,7 @@ class PluginManager(object):
if name.endswith(u'.py') and not name.startswith(u'__'):
path = os.path.abspath(os.path.join(root, name))
thisdepth = len(path.split(os.sep))
- if thisdepth-startdepth > 2:
+ if thisdepth - startdepth > 2:
# skip anything lower down
continue
modulename, pyext = os.path.splitext(path)
@@ -101,7 +101,7 @@ class PluginManager(object):
log.debug(u'Loaded plugin %s with helpers', unicode(p))
plugin_objects.append(plugin)
except TypeError:
- log.error(u'loaded plugin %s has no helpers', unicode(p))
+ log.exception(u'loaded plugin %s has no helpers', unicode(p))
plugins_list = sorted(plugin_objects, self.order_by_weight)
for plugin in plugins_list:
if plugin.check_pre_conditions():
@@ -200,6 +200,7 @@ class PluginManager(object):
% (plugin.name, plugin.is_active()))
if plugin.is_active():
plugin.initialise()
+ log.info(u'Initialisation Complete for %s ' % plugin.name)
if not plugin.is_active():
plugin.remove_toolbox_item()
@@ -211,4 +212,5 @@ class PluginManager(object):
log.info(u'finalising plugins')
for plugin in self.plugins:
if plugin.is_active():
- plugin.finalise()
\ No newline at end of file
+ plugin.finalise()
+ log.info(u'Finalisation Complete for %s ' % plugin.name)
diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py
index c4d7444c4..f0da82b0e 100644
--- a/openlp/core/lib/renderer.py
+++ b/openlp/core/lib/renderer.py
@@ -26,14 +26,15 @@
import logging
from PyQt4 import QtGui, QtCore
+from openlp.core.lib import resize_image
+
+log = logging.getLogger(__name__)
class Renderer(object):
"""
Genarates a pixmap image of a array of text. The Text is formatted to
make sure it fits on the screen and if not extra frames are generated.
"""
- global log
- log = logging.getLogger(u'Renderer')
log.info(u'Renderer Loaded')
def __init__(self):
@@ -41,7 +42,7 @@ class Renderer(object):
Initialise the renderer.
"""
self._rect = None
- self._debug = 0
+ self._debug = False
self._right_margin = 64 # the amount of right indent
self._display_shadow_size_footer = 0
self._display_outline_size_footer = 0
@@ -90,31 +91,9 @@ class Renderer(object):
log.debug(u'set bg image %s', filename)
self._bg_image_filename = unicode(filename)
if self._frame:
- self.scale_bg_image()
-
- def scale_bg_image(self):
- """
- Scale the background image to fit the screen.
- """
- assert self._frame
- preview = QtGui.QImage(self._bg_image_filename)
- width = self._frame.width()
- height = self._frame.height()
- preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
- QtCore.Qt.SmoothTransformation)
- realwidth = preview.width()
- realheight = preview.height()
- # and move it to the centre of the preview space
- self.bg_image = QtGui.QImage(width, height,
- QtGui.QImage.Format_ARGB32_Premultiplied)
- self.bg_image.fill(QtCore.Qt.black)
- painter = QtGui.QPainter()
- painter.begin(self.bg_image)
- self.background_offsetx = (width - realwidth) / 2
- self.background_offsety = (height - realheight) / 2
- painter.drawImage(self.background_offsetx,
- self.background_offsety, preview)
- painter.end()
+ self.bg_image = resize_image(self._bg_image_filename,
+ self._frame.width(),
+ self._frame.height())
def set_frame_dest(self, frame_width, frame_height, preview=False):
"""
@@ -138,7 +117,9 @@ class Renderer(object):
self._frameOp = QtGui.QImage(frame_width, frame_height,
QtGui.QImage.Format_ARGB32_Premultiplied)
if self._bg_image_filename and not self.bg_image:
- self.scale_bg_image()
+ self.bg_image = resize_image(self._bg_image_filename,
+ self._frame.width(),
+ self._frame.height())
if self.bg_frame is None:
self._generate_background_frame()
@@ -167,17 +148,22 @@ class Renderer(object):
def pre_render_text(self, text):
metrics = QtGui.QFontMetrics(self.mainFont)
- #take the width work out approx how many characters and add 50%
+ #work out line width
line_width = self._rect.width() - self._right_margin
#number of lines on a page - adjust for rounding up.
- page_length = int(self._rect.height() / metrics.height() - 2 ) - 1
+ line_height = metrics.height()
+ if self._theme.display_shadow:
+ line_height += int(self._theme.display_shadow_size)
+ if self._theme.display_outline:
+ # pixels top/bottom
+ line_height += 2 * int(self._theme.display_outline_size)
+ page_length = int(self._rect.height() / line_height )
#Average number of characters in line
ave_line_width = line_width / metrics.averageCharWidth()
#Maximum size of a character
max_char_width = metrics.maxWidth()
- #Min size of a character
- min_char_width = metrics.width(u'i')
- char_per_line = line_width / min_char_width
+ #Max characters pre line based on min size of a character
+ char_per_line = line_width / metrics.width(u'i')
log.debug(u'Page Length area height %s , metrics %s , lines %s' %
(int(self._rect.height()), metrics.height(), page_length ))
split_pages = []
@@ -188,7 +174,7 @@ class Renderer(object):
#Must be a blank line so keep it.
if len(line) == 0:
line = u' '
- while len(line) > 0:
+ while line:
pos = char_per_line
split_text = line[:pos]
#line needs splitting
@@ -213,7 +199,7 @@ class Renderer(object):
split_lines.append(split_text)
line = line[pos:].lstrip()
#if we have more text add up to 10 spaces on the front.
- if len(line) > 0 and self._theme.font_main_indentation > 0:
+ if line and self._theme.font_main_indentation > 0:
line = u'%s%s' % \
(u' '[:int(self._theme.font_main_indentation)], line)
#Text fits in a line now
@@ -224,7 +210,7 @@ class Renderer(object):
len(page) == page_length:
split_pages.append(page)
page = []
- if len(page) > 0 and page != u' ':
+ if page and page != u' ':
split_pages.append(page)
return split_pages
@@ -276,8 +262,13 @@ class Renderer(object):
Results are cached for performance reasons.
"""
assert(self._theme)
- self.bg_frame = QtGui.QImage(self._frame.width(), self._frame.height(),
- QtGui.QImage.Format_ARGB32_Premultiplied)
+ if self._theme.background_mode == u'transparent':
+ self.bg_frame = \
+ QtGui.QPixmap(self._frame.width(), self._frame.height())
+ self.bg_frame.fill(QtCore.Qt.transparent)
+ else:
+ self.bg_frame = QtGui.QImage(self._frame.width(), self._frame.height(),
+ QtGui.QImage.Format_ARGB32_Premultiplied)
log.debug(u'render background %s start', self._theme.background_type)
painter = QtGui.QPainter()
painter.begin(self.bg_frame)
@@ -415,13 +406,21 @@ class Renderer(object):
Defaults to *False*. Whether or not this is a live screen.
"""
x, y = tlcorner
- maxx = self._rect.width();
- maxy = self._rect.height();
+ maxx = self._rect.width()
+ maxy = self._rect.height()
lines = []
lines.append(line)
startx = x
starty = y
rightextent = None
+ self.painter = QtGui.QPainter()
+ self.painter.begin(self._frame)
+ self.painter.setRenderHint(QtGui.QPainter.Antialiasing)
+ if self._theme.display_slideTransition:
+ self.painter2 = QtGui.QPainter()
+ self.painter2.begin(self._frameOp)
+ self.painter2.setRenderHint(QtGui.QPainter.Antialiasing)
+ self.painter2.setOpacity(0.7)
# dont allow alignment messing with footers
if footer:
align = 0
@@ -459,7 +458,7 @@ class Renderer(object):
x = maxx - w
# centre
elif align == 2:
- x = (maxx - w) / 2;
+ x = (maxx - w) / 2
rightextent = x + w
if live:
# now draw the text, and any outlines/shadows
@@ -467,49 +466,21 @@ class Renderer(object):
self._get_extent_and_render(line, footer,
tlcorner=(x + display_shadow_size, y + display_shadow_size),
draw=True, color = self._theme.display_shadow_color)
- if self._theme.display_outline:
- self._get_extent_and_render(line, footer,
- (x + display_outline_size, y), draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,
- (x, y + display_outline_size), draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,
- (x, y - display_outline_size), draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,
- (x - display_outline_size, y), draw=True,
- color = self._theme.display_outline_color)
- if display_outline_size > 1:
- self._get_extent_and_render(line, footer,
- (x + display_outline_size, y + display_outline_size),
- draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,
- (x - display_outline_size, y + display_outline_size),
- draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,
- (x + display_outline_size, y - display_outline_size),
- draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,
- (x - display_outline_size, y - display_outline_size),
- draw=True,
- color = self._theme.display_outline_color)
- self._get_extent_and_render(line, footer,tlcorner=(x, y),
- draw=True)
+ self._get_extent_and_render(line, footer, tlcorner=(x, y), draw=True,
+ outline_size=display_outline_size,
+ outline_color=self._theme.display_outline_color)
y += h
if linenum == 0:
self._first_line_right_extent = rightextent
# draw a box around the text - debug only
+
if self._debug:
- painter = QtGui.QPainter()
- painter.begin(self._frame)
- painter.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
- painter.drawRect(startx, starty, rightextent-startx, y-starty)
- painter.end()
+ self.painter.setPen(QtGui.QPen(QtGui.QColor(0,255,0)))
+ self.painter.drawRect(startx, starty, rightextent-startx, y-starty)
brcorner = (rightextent, y)
+ self.painter.end()
+ if self._theme.display_slideTransition:
+ self.painter2.end()
return brcorner
def _set_theme_font(self):
@@ -519,6 +490,7 @@ class Renderer(object):
footer_weight = 50
if self._theme.font_footer_weight == u'Bold':
footer_weight = 75
+ #TODO Add myfont.setPixelSize((screen_height / 100) * font_size)
self.footerFont = QtGui.QFont(self._theme.font_footer_name,
self._theme.font_footer_proportion, # size
footer_weight, # weight
@@ -534,7 +506,7 @@ class Renderer(object):
self.mainFont.setPixelSize(self._theme.font_main_proportion)
def _get_extent_and_render(self, line, footer, tlcorner=(0, 0), draw=False,
- color=None):
+ color=None, outline_size=None, outline_color=None):
"""
Find bounding box of text - as render_single_line. If draw is set,
actually draw the text to the current DC as well return width and
@@ -556,45 +528,42 @@ class Renderer(object):
Defaults to *None*. The colour to draw with.
"""
# setup defaults
- painter = QtGui.QPainter()
- painter.begin(self._frame)
- painter.setRenderHint(QtGui.QPainter.Antialiasing);
if footer :
font = self.footerFont
else:
font = self.mainFont
- painter.setFont(font)
- if color is None:
- if footer:
- painter.setPen(QtGui.QColor(self._theme.font_footer_color))
- else:
- painter.setPen(QtGui.QColor(self._theme.font_main_color))
- else:
- painter.setPen(QtGui.QColor(color))
- x, y = tlcorner
metrics = QtGui.QFontMetrics(font)
w = metrics.width(line)
- h = metrics.height() - 2
+ h = metrics.height()
if draw:
- painter.drawText(x, y + metrics.ascent(), line)
- painter.end()
- if self._theme.display_slideTransition:
- # Print 2nd image with 70% weight
- painter = QtGui.QPainter()
- painter.begin(self._frameOp)
- painter.setRenderHint(QtGui.QPainter.Antialiasing);
- painter.setOpacity(0.7)
- painter.setFont(font)
+ self.painter.setFont(font)
if color is None:
if footer:
- painter.setPen(QtGui.QColor(self._theme.font_footer_color))
+ pen = QtGui.QColor(self._theme.font_footer_color)
else:
- painter.setPen(QtGui.QColor(self._theme.font_main_color))
+ pen = QtGui.QColor(self._theme.font_main_color)
else:
- painter.setPen(QtGui.QColor(color))
- if draw:
- painter.drawText(x, y + metrics.ascent(), line)
- painter.end()
+ pen = QtGui.QColor(color)
+ x, y = tlcorner
+ if outline_size:
+ path = QtGui.QPainterPath()
+ path.addText(QtCore.QPointF(x, y + metrics.ascent()), font, line)
+ self.painter.setBrush(self.painter.pen().brush())
+ self.painter.setPen(QtGui.QPen(QtGui.QColor(outline_color), outline_size))
+ self.painter.drawPath(path)
+ self.painter.setPen(pen)
+ self.painter.drawText(x, y + metrics.ascent(), line)
+ if self._theme.display_slideTransition:
+ # Print 2nd image with 70% weight
+ if outline_size:
+ path = QtGui.QPainterPath()
+ path.addText(QtCore.QPointF(x, y + metrics.ascent()), font, line)
+ self.painter2.setBrush(self.painter2.pen().brush())
+ self.painter2.setPen(QtGui.QPen(QtGui.QColor(outline_color), outline_size))
+ self.painter2.drawPath(path)
+ self.painter2.setFont(font)
+ self.painter2.setPen(pen)
+ self.painter2.drawText(x, y + metrics.ascent(), line)
return (w, h)
def snoop_Image(self, image, image2=None):
@@ -609,4 +578,4 @@ class Renderer(object):
"""
image.save(u'renderer.png', u'png')
if image2:
- image2.save(u'renderer2.png', u'png')
\ No newline at end of file
+ image2.save(u'renderer2.png', u'png')
diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py
index a0e2ce0af..edab3d309 100644
--- a/openlp/core/lib/rendermanager.py
+++ b/openlp/core/lib/rendermanager.py
@@ -25,11 +25,13 @@
import logging
-from PyQt4 import QtGui, QtCore
+from PyQt4 import QtCore
from renderer import Renderer
from openlp.core.lib import ThemeLevel
+log = logging.getLogger(__name__)
+
class RenderManager(object):
"""
Class to pull all Renderer interactions into one place. The plugins will
@@ -39,37 +41,29 @@ class RenderManager(object):
``theme_manager``
The ThemeManager instance, used to get the current theme details.
- ``screen_list``
- The list of screens available.
+ ``screens``
+ Contains information about the Screens.
``screen_number``
Defaults to *0*. The index of the output/display screen.
"""
- global log
- log = logging.getLogger(u'RenderManager')
log.info(u'RenderManager Loaded')
- def __init__(self, theme_manager, screen_list, screen_number=0):
+ def __init__(self, theme_manager, screens, screen_number=0):
"""
Initialise the render manager.
"""
log.debug(u'Initilisation started')
- self.screen_list = screen_list
+ self.screens = screens
self.theme_manager = theme_manager
- self.displays = len(screen_list)
- if (screen_number + 1) > len(screen_list):
- self.current_display = 0
- else:
- self.current_display = screen_number
self.renderer = Renderer()
- self.calculate_default(self.screen_list[self.current_display][u'size'])
+ self.screens.set_current_display(screen_number)
+ self.calculate_default(self.screens.current[u'size'])
self.theme = u''
self.service_theme = u''
self.theme_level = u''
self.override_background = None
self.themedata = None
- self.save_bg_frame = None
- self.override_background_changed = False
def update_display(self, screen_number):
"""
@@ -79,10 +73,8 @@ class RenderManager(object):
The updated index of the output/display screen.
"""
log.debug(u'Update Display')
- if self.current_display != screen_number:
- self.current_display = screen_number
- self.calculate_default(
- self.screen_list[self.current_display][u'size'])
+ self.calculate_default(self.screens.current[u'size'])
+ self.renderer.bg_frame = None
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
"""
@@ -137,31 +129,14 @@ class RenderManager(object):
if self.theme != self.renderer.theme_name or self.themedata is None:
log.debug(u'theme is now %s', self.theme)
self.themedata = self.theme_manager.getThemeData(self.theme)
- self.calculate_default(
- self.screen_list[self.current_display][u'size'])
+ self.calculate_default(self.screens.current[u'size'])
self.renderer.set_theme(self.themedata)
self.build_text_rectangle(self.themedata)
- #Replace the backgrount image from renderer with one from image
- if self.override_background:
- if self.save_bg_frame is None:
- self.save_bg_frame = self.renderer.bg_frame
- if self.override_background_changed:
- self.renderer.bg_frame = self.resize_image(
- self.override_background)
- self.override_background_changed = False
- else:
- if self.override_background_changed:
- self.renderer.bg_frame = self.resize_image(
- self.override_background)
- self.override_background_changed = False
- if self.save_bg_frame:
- self.renderer.bg_frame = self.save_bg_frame
- self.save_bg_frame = None
def build_text_rectangle(self, theme):
"""
- Builds a text block using the settings in ``theme``.
- One is needed per slide
+ Builds a text block using the settings in ``theme``
+ and the size of the display screen.height.
``theme``
The theme to build a text block for.
@@ -170,14 +145,14 @@ class RenderManager(object):
main_rect = None
footer_rect = None
if not theme.font_main_override:
- main_rect = QtCore.QRect(10, 0, self.width - 1,
- self.footer_start - 20)
+ main_rect = QtCore.QRect(10, 0,
+ self.width - 1, self.footer_start)
else:
main_rect = QtCore.QRect(theme.font_main_x, theme.font_main_y,
theme.font_main_width - 1, theme.font_main_height - 1)
if not theme.font_footer_override:
- footer_rect = QtCore.QRect(10, self.footer_start, self.width - 1,
- self.height-self.footer_start)
+ footer_rect = QtCore.QRect(10, self.footer_start,
+ self.width - 1, self.height - self.footer_start)
else:
footer_rect = QtCore.QRect(theme.font_footer_x,
theme.font_footer_y, theme.font_footer_width - 1,
@@ -192,10 +167,13 @@ class RenderManager(object):
The theme to generated a preview for.
"""
log.debug(u'generate preview')
- self.calculate_default(QtCore.QSize(1024, 768))
+ #set the default image size for previews
+ self.calculate_default(self.screens.preview[u'size'])
self.renderer.set_theme(themedata)
self.build_text_rectangle(themedata)
self.renderer.set_frame_dest(self.width, self.height, True)
+ #Reset the real screen size for subsequent render requests
+ self.calculate_default(self.screens.current[u'size'])
verse = u'Amazing Grace!\n'\
'How sweet the sound\n'\
'To save a wretch like me;\n'\
@@ -206,6 +184,7 @@ class RenderManager(object):
footer.append(u'Public Domain')
footer.append(u'CCLI 123456')
formatted = self.renderer.format_slide(verse, False)
+ #Only Render the first slide page returned
return self.renderer.generate_frame_from_lines(formatted[0], footer)[u'main']
def format_slide(self, words):
@@ -234,48 +213,18 @@ class RenderManager(object):
self.renderer.set_frame_dest(self.width, self.height)
return self.renderer.generate_frame_from_lines(main_text, footer_text)
- def resize_image(self, image, width=0, height=0):
- """
- Resize an image to fit on the current screen.
-
- ``image``
- The image to resize.
- """
- preview = QtGui.QImage(image)
- if width == 0:
- w = self.width
- h = self.height
- else:
- w = width
- h = height
- preview = preview.scaled(w, h, QtCore.Qt.KeepAspectRatio,
- QtCore.Qt.SmoothTransformation)
- realw = preview.width();
- realh = preview.height()
- # and move it to the centre of the preview space
- newImage = QtGui.QImage(w, h, QtGui.QImage.Format_ARGB32_Premultiplied)
- newImage.fill(QtCore.Qt.black)
- painter = QtGui.QPainter(newImage)
- painter.drawImage((w - realw) / 2, (h - realh) / 2, preview)
- return newImage
-
def calculate_default(self, screen):
"""
Calculate the default dimentions of the screen.
``screen``
- The QWidget instance of the screen.
+ The QSize of the screen.
"""
log.debug(u'calculate default %s', screen)
- #size fixed so reflects the preview size.
- if self.current_display == 0:
- self.width = 1024
- self.height = 768
- else:
- self.width = screen.width()
- self.height = screen.height()
+ self.width = screen.width()
+ self.height = screen.height()
self.screen_ratio = float(self.height) / float(self.width)
log.debug(u'calculate default %d, %d, %f',
self.width, self.height, self.screen_ratio )
# 90% is start of footer
- self.footer_start = int(self.height * 0.90)
\ No newline at end of file
+ self.footer_start = int(self.height * 0.90)
diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py
index 004973462..7d869a610 100644
--- a/openlp/core/lib/serviceitem.py
+++ b/openlp/core/lib/serviceitem.py
@@ -30,7 +30,9 @@ import uuid
from PyQt4 import QtGui
-from openlp.core.lib import build_icon, Receiver
+from openlp.core.lib import build_icon, Receiver, resize_image
+
+log = logging.getLogger(__name__)
class ServiceItemType(object):
"""
@@ -46,8 +48,6 @@ class ServiceItem(object):
the service manager, the slide controller, and the projection screen
compositor.
"""
- global log
- log = logging.getLogger(u'ServiceItem')
log.info(u'Service Item created')
def __init__(self, plugin=None):
@@ -72,6 +72,8 @@ class ServiceItem(object):
self._raw_frames = []
self._display_frames = []
self._uuid = unicode(uuid.uuid1())
+ self.autoPreviewAllowed = False
+ self.notes = u''
def addIcon(self, icon):
"""
@@ -102,16 +104,19 @@ class ServiceItem(object):
formated = self.RenderManager.format_slide(slide[u'raw_slide'])
for format in formated:
lines = u''
+ title = u''
for line in format:
+ if title == u'':
+ title = line
lines += line + u'\n'
- title = lines.split(u'\n')[0]
self._display_frames.append({u'title': title, \
- u'text': lines, u'verseTag': slide[u'verseTag'] })
+ u'text': lines.rstrip(), u'verseTag': slide[u'verseTag'] })
log.log(15, u'Formatting took %4s' % (time.time() - before))
elif self.service_item_type == ServiceItemType.Image:
for slide in self._raw_frames:
slide[u'image'] = \
- self.RenderManager.resize_image(slide[u'image'])
+ resize_image(slide[u'image'], self.RenderManager.width,
+ self.RenderManager.height)
elif self.service_item_type == ServiceItemType.Command:
pass
else:
@@ -119,7 +124,7 @@ class ServiceItem(object):
def render_individual(self, row):
"""
- Takes an array of text and geneates an Image from the
+ Takes an array of text and generates an Image from the
theme. It assumes the text will fit on the screen as it
has generated by the render method above.
"""
@@ -129,8 +134,12 @@ class ServiceItem(object):
else:
self.RenderManager.set_override_theme(self.theme)
format = self._display_frames[row][u'text'].split(u'\n')
- frame = self.RenderManager.generate_slide(format,
- self.raw_footer)
+ #if screen blank then do not display footer
+ if format[0]:
+ frame = self.RenderManager.generate_slide(format,
+ self.raw_footer)
+ else:
+ frame = self.RenderManager.generate_slide(format,u'')
return frame
def add_from_image(self, path, title, image):
@@ -197,7 +206,9 @@ class ServiceItem(object):
u'icon':self.icon,
u'footer':self.raw_footer,
u'type':self.service_item_type,
- u'audit':self.audit
+ u'audit':self.audit,
+ u'notes':self.notes,
+ u'preview':self.autoPreviewAllowed
}
service_data = []
if self.service_item_type == ServiceItemType.Text:
@@ -231,6 +242,8 @@ class ServiceItem(object):
self.addIcon(header[u'icon'])
self.raw_footer = header[u'footer']
self.audit = header[u'audit']
+ self.autoPreviewAllowed = header[u'preview']
+ self.notes = header[u'notes']
if self.service_item_type == ServiceItemType.Text:
for slide in serviceitem[u'serviceitem'][u'data']:
self._raw_frames.append(slide)
@@ -309,4 +322,4 @@ class ServiceItem(object):
def request_audit(self):
if self.audit:
- Receiver.send_message(u'songusage_live', self.audit)
\ No newline at end of file
+ Receiver.send_message(u'songusage_live', self.audit)
diff --git a/openlp/core/lib/settingsmanager.py b/openlp/core/lib/settingsmanager.py
index 580ec9b31..be5c14af1 100644
--- a/openlp/core/lib/settingsmanager.py
+++ b/openlp/core/lib/settingsmanager.py
@@ -33,7 +33,7 @@ class SettingsManager(object):
individual components.
"""
def __init__(self, screen):
- self.screen = screen[0]
+ self.screen = screen.current
self.width = self.screen[u'size'].width()
self.height = self.screen[u'size'].height()
self.mainwindow_height = self.height * 0.8
@@ -72,4 +72,4 @@ class SettingsManager(object):
u'media manager', isVisible)
def togglePreviewPanel(self, isVisible):
- ConfigHelper.set_config(u'user interface', u'preview panel', isVisible)
\ No newline at end of file
+ ConfigHelper.set_config(u'user interface', u'preview panel', isVisible)
diff --git a/openlp/core/lib/songxmlhandler.py b/openlp/core/lib/songxmlhandler.py
index 596866934..7a532970d 100644
--- a/openlp/core/lib/songxmlhandler.py
+++ b/openlp/core/lib/songxmlhandler.py
@@ -27,6 +27,8 @@ import logging
from xml.dom.minidom import Document
from xml.etree.ElementTree import ElementTree, XML, dump
+log = logging.getLogger(__name__)
+
class SongXMLBuilder(object):
"""
This class builds the XML used to describe songs.
@@ -42,8 +44,6 @@ class SongXMLBuilder(object):
"""
- global log
- log = logging.getLogger(u'SongXMLBuilder')
log.info(u'SongXMLBuilder Loaded')
def __init__(self):
@@ -123,8 +123,6 @@ class SongXMLParser(object):
"""
- global log
- log = logging.getLogger(u'SongXMLParser')
log.info(u'SongXMLParser Loaded')
def __init__(self, xml):
@@ -158,4 +156,4 @@ class SongXMLParser(object):
"""
Debugging aid to dump XML so that we can see what we have.
"""
- return dump(self.song_xml)
\ No newline at end of file
+ return dump(self.song_xml)
diff --git a/openlp/core/lib/themexmlhandler.py b/openlp/core/lib/themexmlhandler.py
index 697c161e2..cbd46d597 100644
--- a/openlp/core/lib/themexmlhandler.py
+++ b/openlp/core/lib/themexmlhandler.py
@@ -171,7 +171,8 @@ class ThemeXML(object):
self.child_element(background, u'filename', filename)
def add_font(self, name, color, proportion, override, fonttype=u'main',
- weight=u'Normal', italics=u'False', indentation=0, xpos=0, ypos=0, width=0, height=0):
+ weight=u'Normal', italics=u'False', indentation=0, xpos=0, ypos=0,
+ width=0, height=0):
"""
Add a Font.
@@ -363,14 +364,14 @@ class ThemeXML(object):
master = u''
for element in iter:
element.text = unicode(element.text).decode('unicode-escape')
- if len(element.getchildren()) > 0:
+ if element.getchildren():
master = element.tag + u'_'
else:
#background transparent tags have no children so special case
if element.tag == u'background':
for e in element.attrib.iteritems():
setattr(self, element.tag + u'_' + e[0], e[1])
- if len(element.attrib) > 0:
+ if element.attrib:
for e in element.attrib.iteritems():
if master == u'font_' and e[0] == u'type':
master += e[1] + u'_'
@@ -402,4 +403,4 @@ class ThemeXML(object):
for key in dir(self):
if key[0:1] != u'_':
theme_strings.append(u'%30s: %s' % (key, getattr(self, key)))
- return u'\n'.join(theme_strings)
\ No newline at end of file
+ return u'\n'.join(theme_strings)
diff --git a/openlp/core/lib/toolbar.py b/openlp/core/lib/toolbar.py
index d4985fd70..3753fedc0 100644
--- a/openlp/core/lib/toolbar.py
+++ b/openlp/core/lib/toolbar.py
@@ -29,6 +29,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon
+log = logging.getLogger(__name__)
+
class OpenLPToolbar(QtGui.QToolBar):
"""
Lots of toolbars around the place, so it makes sense to have a common way
@@ -43,8 +45,7 @@ class OpenLPToolbar(QtGui.QToolBar):
self.icons = {}
self.setIconSize(QtCore.QSize(20, 20))
self.actions = {}
- self.log = logging.getLogger(u'OpenLPToolbar')
- self.log.debug(u'Init done')
+ log.debug(u'Init done')
def addToolbarButton(self, title, icon, tooltip=None, slot=None,
checkable=False):
@@ -119,7 +120,7 @@ class OpenLPToolbar(QtGui.QToolBar):
if self.icons[title]:
return self.icons[title]
else:
- self.log.error(u'getIconFromTitle - no icon for %s' % title)
+ log.error(u'getIconFromTitle - no icon for %s' % title)
return QtGui.QIcon()
def makeWidgetsInvisible(self, widgets):
@@ -152,4 +153,4 @@ class OpenLPToolbar(QtGui.QToolBar):
push_button.setCheckable(True)
push_button.setFlat(True)
self.addWidget(push_button)
- return push_button
\ No newline at end of file
+ return push_button
diff --git a/openlp/core/theme/theme.py b/openlp/core/theme/theme.py
index 92ffbfed2..27969c9d9 100644
--- a/openlp/core/theme/theme.py
+++ b/openlp/core/theme/theme.py
@@ -30,7 +30,7 @@ from PyQt4 import QtGui
DelphiColors={"clRed":0xFF0000,
"clBlue":0x0000FF,
- "clYellow":0x0FFFF00,
+ "clYellow":0xFFFF00,
"clBlack":0x000000,
"clWhite":0xFFFFFF}
@@ -113,6 +113,7 @@ class Theme(object):
root = ElementTree(element=XML(xml))
iter = root.getiterator()
for element in iter:
+ delphiColorChange = False
if element.tag != u'Theme':
t = element.text
val = 0
@@ -128,6 +129,7 @@ class Theme(object):
pass
elif DelphiColors.has_key(t):
val = DelphiColors[t]
+ delphiColorChange = True
else:
try:
val = int(t)
@@ -136,7 +138,10 @@ class Theme(object):
if (element.tag.find(u'Color') > 0 or
(element.tag.find(u'BackgroundParameter') == 0 and type(val) == type(0))):
# convert to a wx.Colour
- val = QtGui.QColor((val>>16) & 0xFF, (val>>8)&0xFF, val&0xFF)
+ if not delphiColorChange:
+ val = QtGui.QColor(val&0xFF, (val>>8)&0xFF, (val>>16)&0xFF)
+ else:
+ val = QtGui.QColor((val>>16)&0xFF, (val>>8)&0xFF, val&0xFF)
setattr(self, element.tag, val)
def __str__(self):
diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py
index 6b187f5fc..c2f571c3b 100644
--- a/openlp/core/ui/__init__.py
+++ b/openlp/core/ui/__init__.py
@@ -23,16 +23,15 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
-#from slidecontroller import MasterToolbar
+from serviceitemform import ServiceItemNoteForm
+from screen import ScreenList
from maindisplay import MainDisplay
from amendthemeform import AmendThemeForm
from slidecontroller import SlideController
from splashscreen import SplashScreen
-from alertstab import AlertsTab
from generaltab import GeneralTab
from themestab import ThemesTab
from aboutform import AboutForm
-from alertform import AlertForm
from pluginform import PluginForm
from settingsform import SettingsForm
from mediadockmanager import MediaDockManager
@@ -42,4 +41,4 @@ from mainwindow import MainWindow
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainWindow',
'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager',
- 'AmendThemeForm', 'MediaDockManager', 'ThemeLevel']
\ No newline at end of file
+ 'AmendThemeForm', 'MediaDockManager', 'ServiceItemNoteForm']
diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py
index d6a97e2c9..c3eb7bdcb 100644
--- a/openlp/core/ui/aboutform.py
+++ b/openlp/core/ui/aboutform.py
@@ -25,7 +25,6 @@
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import build_icon
from aboutdialog import Ui_AboutDialog
class AboutForm(QtGui.QDialog, Ui_AboutDialog):
diff --git a/openlp/core/ui/alertform.py b/openlp/core/ui/alertform.py
deleted file mode 100644
index 4b099b954..000000000
--- a/openlp/core/ui/alertform.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman #
-# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
-# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
-# Carsten Tinggaard #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-
-import logging
-from PyQt4 import QtCore, QtGui
-from openlp.core.lib import build_icon
-
-class AlertForm(QtGui.QDialog):
- global log
- log = logging.getLogger(u'AlertForm')
-
- def __init__(self, parent=None):
- QtGui.QDialog.__init__(self, parent)
- self.parent = parent
- self.setupUi(self)
- log.debug(u'Defined')
-
- def setupUi(self, AlertForm):
- AlertForm.setObjectName(u'AlertForm')
- AlertForm.resize(370, 110)
- icon = build_icon(u':/icon/openlp-logo-16x16.png')
- AlertForm.setWindowIcon(icon)
- self.AlertFormLayout = QtGui.QVBoxLayout(AlertForm)
- self.AlertFormLayout.setSpacing(8)
- self.AlertFormLayout.setMargin(8)
- self.AlertFormLayout.setObjectName(u'AlertFormLayout')
- self.AlertEntryWidget = QtGui.QWidget(AlertForm)
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.AlertEntryWidget.sizePolicy().hasHeightForWidth())
- self.AlertEntryWidget.setSizePolicy(sizePolicy)
- self.AlertEntryWidget.setObjectName(u'AlertEntryWidget')
- self.AlertEntryLabel = QtGui.QLabel(self.AlertEntryWidget)
- self.AlertEntryLabel.setGeometry(QtCore.QRect(0, 0, 353, 16))
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.AlertEntryLabel.sizePolicy().hasHeightForWidth())
- self.AlertEntryLabel.setSizePolicy(sizePolicy)
- self.AlertEntryLabel.setObjectName(u'AlertEntryLabel')
- self.AlertEntryEditItem = QtGui.QLineEdit(self.AlertEntryWidget)
- self.AlertEntryEditItem.setGeometry(QtCore.QRect(0, 20, 353, 26))
- self.AlertEntryEditItem.setObjectName(u'AlertEntryEditItem')
- self.AlertFormLayout.addWidget(self.AlertEntryWidget)
- self.ButtonBoxWidget = QtGui.QWidget(AlertForm)
- sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
- sizePolicy.setHorizontalStretch(0)
- sizePolicy.setVerticalStretch(0)
- sizePolicy.setHeightForWidth(self.ButtonBoxWidget.sizePolicy().hasHeightForWidth())
- self.ButtonBoxWidget.setSizePolicy(sizePolicy)
- self.ButtonBoxWidget.setObjectName(u'ButtonBoxWidget')
- self.horizontalLayout = QtGui.QHBoxLayout(self.ButtonBoxWidget)
- self.horizontalLayout.setSpacing(8)
- self.horizontalLayout.setMargin(0)
- self.horizontalLayout.setObjectName(u'horizontalLayout')
- spacerItem = QtGui.QSpacerItem(267, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
- self.horizontalLayout.addItem(spacerItem)
- self.DisplayButton = QtGui.QPushButton(self.ButtonBoxWidget)
- self.DisplayButton.setObjectName(u'DisplayButton')
- self.horizontalLayout.addWidget(self.DisplayButton)
- self.CancelButton = QtGui.QPushButton(self.ButtonBoxWidget)
- self.CancelButton.setObjectName(u'CancelButton')
- self.horizontalLayout.addWidget(self.CancelButton)
- self.AlertFormLayout.addWidget(self.ButtonBoxWidget)
-
- self.retranslateUi(AlertForm)
-
- QtCore.QObject.connect(self.CancelButton, QtCore.SIGNAL(u'clicked()'), AlertForm.close)
- QtCore.QObject.connect(self.DisplayButton, QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked)
- QtCore.QMetaObject.connectSlotsByName(AlertForm)
-
- def retranslateUi(self, AlertForm):
- AlertForm.setWindowTitle(self.trUtf8('Alert Message'))
- self.AlertEntryLabel.setText(self.trUtf8('Alert Text:'))
- self.DisplayButton.setText(self.trUtf8('Display'))
- self.CancelButton.setText(self.trUtf8('Cancel'))
-
- def onDisplayClicked(self):
- self.parent.mainDisplay.displayAlert(unicode(self.AlertEntryEditItem.text()))
\ No newline at end of file
diff --git a/openlp/core/ui/amendthemeform.py b/openlp/core/ui/amendthemeform.py
index 24a22a7cf..97eecd1e8 100644
--- a/openlp/core/ui/amendthemeform.py
+++ b/openlp/core/ui/amendthemeform.py
@@ -694,8 +694,14 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
if self.allowPreview:
#calculate main number of rows
metrics = self._getThemeMetrics()
+ line_height = metrics.height()
+ if self.theme.display_shadow:
+ line_height += int(self.theme.display_shadow_size)
+ if self.theme.display_outline:
+ # pixels top/bottom
+ line_height += 2 * int(self.theme.display_outline_size)
page_length = \
- (self.FontMainHeightSpinBox.value() / metrics.height() - 2) - 1
+ ((self.FontMainHeightSpinBox.value()) / line_height )
log.debug(u'Page Length area height %s, metrics %s, lines %s' %
(self.FontMainHeightSpinBox.value(), metrics.height(),
page_length))
@@ -719,4 +725,4 @@ class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
if self.theme.font_main_width < metrics.maxWidth() * 2 + 64:
self.theme.font_main_width = metrics.maxWidth() * 2 + 64
self.FontMainWidthSpinBox.setValue(self.theme.font_main_width)
- return metrics
\ No newline at end of file
+ return metrics
diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py
index b5abc2a2e..c65ea3dd0 100644
--- a/openlp/core/ui/generaltab.py
+++ b/openlp/core/ui/generaltab.py
@@ -87,6 +87,10 @@ class GeneralTab(SettingsTab):
self.SaveCheckServiceCheckBox.setObjectName(u'SaveCheckServiceCheckBox')
self.SettingsLayout.addWidget(self.SaveCheckServiceCheckBox)
self.GeneralLeftLayout.addWidget(self.SettingsGroupBox)
+ self.AutoPreviewCheckBox = QtGui.QCheckBox(self.SettingsGroupBox)
+ self.AutoPreviewCheckBox.setObjectName(u'AutoPreviewCheckBox')
+ self.SettingsLayout.addWidget(self.AutoPreviewCheckBox)
+ self.GeneralLeftLayout.addWidget(self.SettingsGroupBox)
self.GeneralLeftSpacer = QtGui.QSpacerItem(20, 40,
QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.GeneralLeftLayout.addItem(self.GeneralLeftSpacer)
@@ -137,6 +141,8 @@ class GeneralTab(SettingsTab):
QtCore.SIGNAL(u'stateChanged(int)'), self.onShowSplashCheckBoxChanged)
QtCore.QObject.connect(self.SaveCheckServiceCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onSaveCheckServiceCheckBox)
+ QtCore.QObject.connect(self.AutoPreviewCheckBox,
+ QtCore.SIGNAL(u'stateChanged(int)'), self.onAutoPreviewCheckBox)
QtCore.QObject.connect(self.NumberEdit,
QtCore.SIGNAL(u'editingFinished()'), self.onNumberEditLostFocus)
QtCore.QObject.connect(self.UsernameEdit,
@@ -153,6 +159,7 @@ class GeneralTab(SettingsTab):
self.ShowSplashCheckBox.setText(self.trUtf8('Show the splash screen'))
self.SettingsGroupBox.setTitle(self.trUtf8('Application Settings'))
self.SaveCheckServiceCheckBox.setText(self.trUtf8('Prompt to save Service before starting New'))
+ self.AutoPreviewCheckBox.setText(self.trUtf8('Preview Next Song from Service Manager'))
self.CCLIGroupBox.setTitle(self.trUtf8('CCLI Details'))
self.NumberLabel.setText(self.trUtf8('CCLI Number:'))
self.UsernameLabel.setText(self.trUtf8('SongSelect Username:'))
@@ -173,6 +180,9 @@ class GeneralTab(SettingsTab):
def onSaveCheckServiceCheckBox(self, value):
self.PromptSaveService = (value == QtCore.Qt.Checked)
+ def onAutoPreviewCheckBox(self, value):
+ self.AutoPreview = (value == QtCore.Qt.Checked)
+
def onNumberEditLostFocus(self):
self.CCLINumber = self.NumberEdit.displayText()
@@ -183,7 +193,7 @@ class GeneralTab(SettingsTab):
self.Password = self.PasswordEdit.displayText()
def load(self):
- for screen in self.screen_list:
+ for screen in self.screen_list.screen_list:
screen_name = u'%s %d' % (self.trUtf8('Screen'), screen[u'number'] + 1)
if screen[u'primary']:
screen_name = u'%s (%s)' % (screen_name, self.trUtf8('primary'))
@@ -194,6 +204,7 @@ class GeneralTab(SettingsTab):
self.AutoOpen = str_to_bool(self.config.get_config(u'auto open', u'False'))
self.ShowSplash = str_to_bool(self.config.get_config(u'show splash', u'True'))
self.PromptSaveService = str_to_bool(self.config.get_config(u'save prompt', u'False'))
+ self.AutoPreview = str_to_bool(self.config.get_config(u'auto preview', u'False'))
self.CCLINumber = unicode(self.config.get_config(u'ccli number', u''))
self.Username = unicode(self.config.get_config(u'songselect username', u''))
self.Password = unicode(self.config.get_config(u'songselect password', u''))
@@ -203,6 +214,7 @@ class GeneralTab(SettingsTab):
self.WarningCheckBox.setChecked(self.Warning)
self.AutoOpenCheckBox.setChecked(self.AutoOpen)
self.ShowSplashCheckBox.setChecked(self.ShowSplash)
+ self.AutoPreviewCheckBox.setChecked(self.AutoPreview)
self.NumberEdit.setText(self.CCLINumber)
self.UsernameEdit.setText(self.Username)
self.PasswordEdit.setText(self.Password)
@@ -213,6 +225,7 @@ class GeneralTab(SettingsTab):
self.config.set_config(u'auto open', self.AutoOpen)
self.config.set_config(u'show splash', self.ShowSplash)
self.config.set_config(u'save prompt', self.PromptSaveService)
+ self.config.set_config(u'auto preview', self.AutoPreview)
self.config.set_config(u'ccli number', self.CCLINumber)
self.config.set_config(u'songselect username', self.Username)
- self.config.set_config(u'songselect password', self.Password)
\ No newline at end of file
+ self.config.set_config(u'songselect password', self.Password)
diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py
index 46da99ac2..510b0ecc7 100644
--- a/openlp/core/ui/maindisplay.py
+++ b/openlp/core/ui/maindisplay.py
@@ -25,25 +25,29 @@
import logging
import os
-import time
from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
-from openlp.core.lib import Receiver
+from openlp.core.lib import Receiver, resize_image
+
+log = logging.getLogger(__name__)
class DisplayWidget(QtGui.QWidget):
"""
Customised version of QTableWidget which can respond to keyboard
events.
"""
- global log
- log = logging.getLogger(u'MainDisplay')
log.info(u'MainDisplay loaded')
def __init__(self, parent=None, name=None):
QtGui.QWidget.__init__(self, parent)
self.parent = parent
+ self.hotkey_map = {QtCore.Qt.Key_Return: 'servicemanager_next_item',
+ QtCore.Qt.Key_Space: 'live_slidecontroller_next_noloop',
+ QtCore.Qt.Key_Enter: 'live_slidecontroller_next_noloop',
+ QtCore.Qt.Key_0: 'servicemanager_next_item',
+ QtCore.Qt.Key_Backspace: 'live_slidecontroller_previous_noloop'}
def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent:
@@ -60,6 +64,9 @@ class DisplayWidget(QtGui.QWidget):
elif event.key() == QtCore.Qt.Key_PageDown:
Receiver.send_message(u'live_slidecontroller_last')
event.accept()
+ elif event.key() in self.hotkey_map:
+ Receiver.send_message(self.hotkey_map[event.key()])
+ event.accept()
elif event.key() == QtCore.Qt.Key_Escape:
self.resetDisplay()
event.accept()
@@ -71,8 +78,6 @@ class MainDisplay(DisplayWidget):
"""
This is the form that is used to display things on the projector.
"""
- global log
- log = logging.getLogger(u'MainDisplay')
log.info(u'MainDisplay Loaded')
def __init__(self, parent, screens):
@@ -90,31 +95,26 @@ class MainDisplay(DisplayWidget):
self.parent = parent
self.setWindowTitle(u'OpenLP Display')
self.screens = screens
- self.layout = QtGui.QVBoxLayout(self)
- self.layout.setSpacing(0)
- self.layout.setMargin(0)
- self.layout.setObjectName(u'layout')
self.mediaObject = Phonon.MediaObject(self)
self.video = Phonon.VideoWidget()
self.video.setVisible(False)
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
Phonon.createPath(self.mediaObject, self.video)
Phonon.createPath(self.mediaObject, self.audio)
- self.layout.insertWidget(0, self.video)
- self.display = QtGui.QLabel(self)
- self.display.setScaledContents(True)
- self.layout.insertWidget(0, self.display)
+ self.display_image = QtGui.QLabel(self)
+ self.display_image.setScaledContents(True)
+ self.display_text = QtGui.QLabel(self)
+ self.display_text.setScaledContents(True)
+ self.display_alert = QtGui.QLabel(self)
+ self.display_alert.setScaledContents(True)
self.primary = True
self.displayBlank = False
self.blankFrame = None
self.frame = None
- self.alertactive = False
- self.timer_id = 0
self.firstTime = True
self.mediaLoaded = False
self.hasTransition = False
- QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'alert_text'), self.displayAlert)
+ self.mediaBackground = False
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'live_slide_hide'), self.hideDisplay)
QtCore.QObject.connect(Receiver.get_receiver(),
@@ -126,11 +126,10 @@ class MainDisplay(DisplayWidget):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_play'), self.onMediaPlay)
QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'media_pause'), self.onMediaPaws)
+ QtCore.SIGNAL(u'media_pause'), self.onMediaPause)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'media_stop'), self.onMediaStop)
-
def setup(self, screenNumber):
"""
Sets up the screen on a particular screen.
@@ -138,54 +137,88 @@ class MainDisplay(DisplayWidget):
"""
log.debug(u'Setup %s for %s ' %(self.screens, screenNumber))
self.setVisible(False)
- screen = self.screens[screenNumber]
- if screen[u'number'] != screenNumber:
- # We will most probably never actually hit this bit, but just in
- # case the index in the list doesn't match the screen number, we
- # search for it.
- for scrn in self.screens:
- if scrn[u'number'] == screenNumber:
- screen = scrn
- break
- self.setGeometry(screen[u'size'])
+ self.screen = self.screens.current
+ #Sort out screen locations and sizes
+ self.setGeometry(self.screen[u'size'])
+ self.display_alert.setGeometry(self.screen[u'size'])
+ self.video.setGeometry(self.screen[u'size'])
+ self.display_image.resize(self.screen[u'size'].width(),
+ self.screen[u'size'].height())
+ self.display_text.resize(self.screen[u'size'].width(),
+ self.screen[u'size'].height())
#Build a custom splash screen
self.InitialFrame = QtGui.QImage(
- screen[u'size'].width(), screen[u'size'].height(),
+ self.screen[u'size'].width(),
+ self.screen[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
splash_image = QtGui.QImage(u':/graphics/openlp-splash-screen.png')
painter_image = QtGui.QPainter()
painter_image.begin(self.InitialFrame)
painter_image.fillRect(self.InitialFrame.rect(), QtCore.Qt.white)
painter_image.drawImage(
- (screen[u'size'].width() - splash_image.width()) / 2,
- (screen[u'size'].height() - splash_image.height()) / 2,
+ (self.screen[u'size'].width() - splash_image.width()) / 2,
+ (self.screen[u'size'].height() - splash_image.height()) / 2,
splash_image)
- self.frameView(self.InitialFrame)
+ self.display_image.setPixmap(QtGui.QPixmap.fromImage(self.InitialFrame))
+ self.repaint()
#Build a Black screen
painter = QtGui.QPainter()
self.blankFrame = QtGui.QImage(
- screen[u'size'].width(), screen[u'size'].height(),
+ self.screen[u'size'].width(),
+ self.screen[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
painter.begin(self.blankFrame)
- painter.fillRect(self.blankFrame.rect(), QtCore.Qt.black)
+ #TODO make black when testing finished
+ painter.fillRect(self.blankFrame.rect(), QtCore.Qt.red)
+ #build a blank transparent image
+ self.transparent = QtGui.QPixmap(self.screen[u'size'].width(),
+ self.screen[u'size'].height())
+ self.transparent.fill(QtCore.Qt.transparent)
+ self.display_alert.setPixmap(self.transparent)
+ self.frameView(self.transparent)
# To display or not to display?
- if not screen[u'primary']:
+ if not self.screen[u'primary']:
self.showFullScreen()
self.primary = False
else:
self.setVisible(False)
self.primary = True
+ Receiver.send_message(u'screen_changed')
def resetDisplay(self):
+ Receiver.send_message(u'stop_display_loop')
if self.primary:
self.setVisible(False)
+ else:
+ self.showFullScreen()
def hideDisplay(self):
+ self.mediaLoaded = True
self.setVisible(False)
def showDisplay(self):
+ self.mediaLoaded = False
if not self.primary:
self.setVisible(True)
+ self.showFullScreen()
+ Receiver.send_message(u'flush_alert')
+
+ def addImageWithText(self, frame):
+ frame = resize_image(frame,
+ self.screen[u'size'].width(),
+ self.screen[u'size'].height() )
+ self.display_image.setPixmap(QtGui.QPixmap.fromImage(frame))
+
+ def setAlertSize(self, top, height):
+ self.display_alert.setGeometry(
+ QtCore.QRect(0, top,
+ self.screen[u'size'].width(), height))
+
+ def addAlertImage(self, frame, blank=False):
+ if blank:
+ self.display_alert.setPixmap(self.transparent)
+ else:
+ self.display_alert.setPixmap(frame)
def frameView(self, frame, transition=False):
"""
@@ -194,87 +227,43 @@ class MainDisplay(DisplayWidget):
``frame``
Image frame to be rendered
"""
- if self.timer_id != 0 :
- self.displayAlert()
- elif not self.displayBlank:
+ if not self.displayBlank:
if transition:
- if self.hasTransition:
- if self.frame[u'trans'] is not None:
- self.display.setPixmap(QtGui.QPixmap.fromImage(self.frame[u'trans']))
- self.repaint()
- if frame[u'trans'] is not None:
- self.display.setPixmap(QtGui.QPixmap.fromImage(frame[u'trans']))
- self.repaint()
- self.hasTransition = True
- self.display.setPixmap(QtGui.QPixmap.fromImage(frame[u'main']))
+ if self.frame is not None:
+ self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.frame))
+ self.repaint()
+ self.frame = None
+ if frame[u'trans'] is not None:
+ self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame[u'trans']))
+ self.repaint()
+ self.frame = frame[u'trans']
+ self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame[u'main']))
+ self.display_frame = frame[u'main']
self.repaint()
else:
- self.display.setPixmap(QtGui.QPixmap.fromImage(frame))
+ if isinstance(frame, QtGui.QPixmap):
+ self.display_text.setPixmap(frame)
+ else:
+ self.display_text.setPixmap(QtGui.QPixmap.fromImage(frame))
+ self.display_frame = frame
if not self.isVisible():
self.setVisible(True)
self.showFullScreen()
- self.frame = frame
def blankDisplay(self, blanked=True):
if blanked:
self.displayBlank = True
- self.display.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame))
+ self.display_text.setPixmap(QtGui.QPixmap.fromImage(self.blankFrame))
else:
self.displayBlank = False
- if self.frame:
- self.frameView(self.frame)
- if blanked != self.parent.LiveController.blankButton.isChecked():
- self.parent.LiveController.blankButton.setChecked(self.displayBlank)
- self.parent.generalConfig.set_config(u'screen blank', self.displayBlank)
-
- def displayAlert(self, text=u''):
- """
- Called from the Alert Tab to display an alert
-
- ``text``
- display text
- """
- log.debug(u'display alert called %s' % text)
- alertTab = self.parent.settingsForm.AlertsTab
- if isinstance(self.frame, QtGui.QImage):
- alertframe = QtGui.QPixmap.fromImage(self.frame)
- else:
- alertframe = QtGui.QPixmap.fromImage(self.frame[u'main'])
- painter = QtGui.QPainter(alertframe)
- top = alertframe.rect().height() * 0.9
- painter.fillRect(
- QtCore.QRect(
- 0, top, alertframe.rect().width(),
- alertframe.rect().height() - top),
- QtGui.QColor(alertTab.bg_color))
- font = QtGui.QFont()
- font.setFamily(alertTab.font_face)
- font.setBold(True)
- font.setPointSize(40)
- painter.setFont(font)
- painter.setPen(QtGui.QColor(alertTab.font_color))
- x, y = (0, top)
- metrics = QtGui.QFontMetrics(font)
- painter.drawText(
- x, y + metrics.height() - metrics.descent() - 1, text)
- painter.end()
- self.display.setPixmap(alertframe)
- # check to see if we have a timer running
- if self.timer_id == 0:
- self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
-
- def timerEvent(self, event):
- if event.timerId() == self.timer_id:
- if isinstance(self.frame, QtGui.QImage):
- self.display.setPixmap(QtGui.QPixmap.fromImage(self.frame))
- else:
- self.display.setPixmap(QtGui.QPixmap.fromImage(self.frame[u'main']))
- self.killTimer(self.timer_id)
- self.timer_id = 0
+ if self.display_frame:
+ self.frameView(self.display_frame)
def onMediaQueue(self, message):
log.debug(u'Queue new media message %s' % message)
- self.display.close()
+ self.display_image.close()
+ self.display_text.close()
+ self.display_alert.close()
file = os.path.join(message[1], message[2])
if self.firstTime:
self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
@@ -287,29 +276,33 @@ class MainDisplay(DisplayWidget):
log.debug(u'Play the new media, Live ')
if not self.mediaLoaded and not self.displayBlank:
self.blankDisplay()
+ self.display_frame = self.blankFrame
self.firstTime = True
self.mediaLoaded = True
- self.display.hide()
+ self.display_image.hide()
+ self.display_text.hide()
+ self.display_alert.hide()
self.video.setFullScreen(True)
self.video.setVisible(True)
self.mediaObject.play()
- if self.primary:
- self.setVisible(True)
+ self.setVisible(True)
+ self.hide()
- def onMediaPaws(self):
+ def onMediaPause(self):
log.debug(u'Media paused by user')
self.mediaObject.pause()
def onMediaStop(self):
log.debug(u'Media stopped by user')
self.mediaObject.stop()
+ self.onMediaFinish()
def onMediaFinish(self):
log.debug(u'Reached end of media playlist')
- if self.primary:
- self.setVisible(False)
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.mediaLoaded = False
self.video.setVisible(False)
- self.display.show()
\ No newline at end of file
+ self.display_text.show()
+ self.display_image.show()
+ self.blankDisplay(False)
diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py
index 854811484..41b6d245f 100644
--- a/openlp/core/ui/mainwindow.py
+++ b/openlp/core/ui/mainwindow.py
@@ -25,31 +25,55 @@
import os
import logging
+import time
from PyQt4 import QtCore, QtGui
-from openlp.core.ui import AboutForm, SettingsForm, AlertForm, \
+from openlp.core.ui import AboutForm, SettingsForm, \
ServiceManager, ThemeManager, MainDisplay, SlideController, \
PluginForm, MediaDockManager
from openlp.core.lib import RenderManager, PluginConfig, build_icon, \
OpenLPDockWidget, SettingsManager, PluginManager, Receiver, str_to_bool
-from openlp.core.utils import check_latest_version
+from openlp.core.utils import check_latest_version, AppLocation
+
+log = logging.getLogger(__name__)
media_manager_style = """
QToolBox::tab {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 palette(midlight), stop: 1.0 palette(mid));
+ stop: 0 palette(button), stop: 1.0 palette(dark));
border-width: 1px;
border-style: outset;
- border-color: palette(midlight);
+ border-color: palette(dark);
border-radius: 5px;
}
QToolBox::tab:selected {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
- stop: 0 palette(light), stop: 1.0 palette(mid));
- border-color: palette(light);
+ stop: 0 palette(light), stop: 1.0 palette(button));
+ border-color: palette(button);
}
"""
+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, app_version, generalConfig):
+ QtCore.QThread.__init__(self, parent)
+ self.parent = parent
+ self.app_version = app_version
+ self.generalConfig = generalConfig
+
+ def run(self):
+ """
+ Run the thread.
+ """
+ time.sleep(2)
+ version = check_latest_version(self.generalConfig, self.app_version)
+ #new version has arrived
+ if version != self.app_version:
+ Receiver.send_message(u'version_check', u'%s' % version)
+
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
@@ -218,13 +242,8 @@ class Ui_MainWindow(object):
self.settingsmanager.showServiceManager)
self.ViewServiceManagerItem.setIcon(ServiceManagerIcon)
self.ViewServiceManagerItem.setObjectName(u'ViewServiceManagerItem')
- self.ToolsAlertItem = QtGui.QAction(MainWindow)
- AlertIcon = build_icon(u':/tools/tools_alert.png')
- self.ToolsAlertItem.setIcon(AlertIcon)
- self.ToolsAlertItem.setObjectName(u'ToolsAlertItem')
self.PluginItem = QtGui.QAction(MainWindow)
- #PluginIcon = build_icon(u':/tools/tools_alert.png')
- self.PluginItem.setIcon(AlertIcon)
+ #self.PluginItem.setIcon(AlertIcon)
self.PluginItem.setObjectName(u'PluginItem')
self.HelpDocumentationItem = QtGui.QAction(MainWindow)
ContentsIcon = build_icon(u':/system/system_help_contents.png')
@@ -283,7 +302,6 @@ class Ui_MainWindow(object):
self.OptionsMenu.addAction(self.OptionsViewMenu.menuAction())
self.OptionsMenu.addSeparator()
self.OptionsMenu.addAction(self.OptionsSettingsItem)
- self.ToolsMenu.addAction(self.ToolsAlertItem)
self.ToolsMenu.addAction(self.PluginItem)
self.ToolsMenu.addSeparator()
self.ToolsMenu.addAction(self.ToolsAddToolItem)
@@ -385,9 +403,6 @@ class Ui_MainWindow(object):
self.action_Preview_Panel.setStatusTip(
self.trUtf8('Toggle the visibility of the Preview Panel'))
self.action_Preview_Panel.setShortcut(self.trUtf8('F11'))
- self.ToolsAlertItem.setText(self.trUtf8('&Alert'))
- self.ToolsAlertItem.setStatusTip(self.trUtf8('Show an alert message'))
- self.ToolsAlertItem.setShortcut(self.trUtf8('F7'))
self.PluginItem.setText(self.trUtf8('&Plugin List'))
self.PluginItem.setStatusTip(self.trUtf8('List the Plugins'))
self.PluginItem.setShortcut(self.trUtf8('Alt+F7'))
@@ -415,8 +430,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
The main window.
"""
- global log
- log = logging.getLogger(u'MainWindow')
log.info(u'MainWindow loaded')
def __init__(self, screens, applicationVersion):
@@ -425,19 +438,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
plugins.
"""
QtGui.QMainWindow.__init__(self)
- self.screenList = screens
+ self.screens = screens
self.applicationVersion = applicationVersion
self.serviceNotSaved = False
self.settingsmanager = SettingsManager(screens)
self.generalConfig = PluginConfig(u'General')
self.mainDisplay = MainDisplay(self, screens)
- self.alertForm = AlertForm(self)
self.aboutForm = AboutForm(self, applicationVersion)
- self.settingsForm = SettingsForm(self.screenList, self, self)
+ self.settingsForm = SettingsForm(self.screens, self, self)
# Set up the path with plugins
- pluginpath = os.path.split(os.path.abspath(__file__))[0]
- pluginpath = os.path.abspath(
- os.path.join(pluginpath, u'..', u'..', u'plugins'))
+ pluginpath = AppLocation.get_directory(AppLocation.PluginsDir)
self.plugin_manager = PluginManager(pluginpath)
self.plugin_helpers = {}
# Set up the interface
@@ -476,14 +486,14 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.action_Preview_Panel.setChecked)
QtCore.QObject.connect(self.HelpAboutItem,
QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked)
- QtCore.QObject.connect(self.ToolsAlertItem,
- QtCore.SIGNAL(u'triggered()'), self.onToolsAlertItemClicked)
QtCore.QObject.connect(self.PluginItem,
QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked)
QtCore.QObject.connect(self.OptionsSettingsItem,
QtCore.SIGNAL(u'triggered()'), self.onOptionsSettingsItemClicked)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'update_global_theme'), self.defaultThemeChanged)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'version_check'), self.versionCheck)
QtCore.QObject.connect(self.FileNewItem,
QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.onNewService)
@@ -500,7 +510,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
#RenderManager needs to call ThemeManager and
#ThemeManager needs to call RenderManager
self.RenderManager = RenderManager(self.ThemeManagerContents,
- self.screenList, self.getMonitorNumber())
+ self.screens, self.getMonitorNumber())
#Define the media Dock Manager
self.mediaDockManager = MediaDockManager(self.MediaToolBox)
log.info(u'Load Plugins')
@@ -511,6 +521,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.plugin_helpers[u'service'] = self.ServiceManagerContents
self.plugin_helpers[u'settings'] = self.settingsForm
self.plugin_helpers[u'toolbox'] = self.mediaDockManager
+ self.plugin_helpers[u'maindisplay'] = self.mainDisplay
self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers)
# hook methods have to happen after find_plugins. Find plugins needs
# the controllers hence the hooks have moved from setupUI() to here
@@ -536,20 +547,18 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
log.info(u'Load data from Settings')
self.settingsForm.postSetUp()
- def versionCheck(self):
+ def versionCheck(self, version):
"""
Checks the version of the Application called from openlp.pyw
"""
app_version = self.applicationVersion[u'full']
- version = check_latest_version(self.generalConfig, app_version)
- if app_version != version:
- version_text = unicode(self.trUtf8('OpenLP version %s has been updated '
- 'to version %s\n\nYou can obtain the latest version from http://openlp.org'))
- QtGui.QMessageBox.question(None,
- self.trUtf8('OpenLP Version Updated'),
- version_text % (app_version, version),
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
- QtGui.QMessageBox.Ok)
+ version_text = unicode(self.trUtf8('OpenLP version %s has been updated '
+ 'to version %s\n\nYou can obtain the latest version from http://openlp.org'))
+ QtGui.QMessageBox.question(self,
+ self.trUtf8('OpenLP Version Updated'),
+ version_text % (app_version, version),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
+ QtGui.QMessageBox.Ok)
def getMonitorNumber(self):
"""
@@ -558,11 +567,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
monitor number does not exist.
"""
screen_number = int(self.generalConfig.get_config(u'monitor', 0))
- monitor_exists = False
- for screen in self.screenList:
- if screen[u'number'] == screen_number:
- monitor_exists = True
- if not monitor_exists:
+ if not self.screens.screen_exists(screen_number):
screen_number = 0
return screen_number
@@ -580,12 +585,17 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.ServiceManagerContents.onLoadService(True)
if str_to_bool(self.generalConfig.get_config(u'screen blank', False)) \
and str_to_bool(self.generalConfig.get_config(u'blank warning', False)):
- QtGui.QMessageBox.question(None,
+ self.LiveController.onBlankDisplay(True)
+ QtGui.QMessageBox.question(self,
self.trUtf8('OpenLP Main Display Blanked'),
self.trUtf8('The Main Display has been blanked out'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok)
- self.LiveController.blankButton.setChecked(True)
+
+ def versionThread(self):
+ app_version = self.applicationVersion[u'full']
+ vT = VersionThread(self, app_version, self.generalConfig)
+ vT.start()
def onHelpAboutItemClicked(self):
"""
@@ -594,12 +604,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.aboutForm.applicationVersion = self.applicationVersion
self.aboutForm.exec_()
- def onToolsAlertItemClicked(self):
- """
- Show the Alert form
- """
- self.alertForm.exec_()
-
def onPluginItemClicked(self):
"""
Show the Plugin form
@@ -613,7 +617,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
self.settingsForm.exec_()
updated_display = self.getMonitorNumber()
- if updated_display != self.RenderManager.current_display:
+ if updated_display != self.screens.current_display:
+ self.screens.set_current_display(updated_display)
self.RenderManager.update_display(updated_display)
self.mainDisplay.setup(updated_display)
self.activateWindow()
@@ -623,7 +628,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Hook to close the main window and display windows on exit
"""
if self.serviceNotSaved:
- ret = QtGui.QMessageBox.question(None,
+ ret = QtGui.QMessageBox.question(self,
self.trUtf8('Save Changes to Service?'),
self.trUtf8('Your service has changed, do you want to save those changes?'),
QtGui.QMessageBox.StandardButtons(
@@ -704,4 +709,4 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def togglePreviewPanel(self):
previewBool = self.PreviewController.Panel.isVisible()
self.PreviewController.Panel.setVisible(not previewBool)
- self.settingsmanager.togglePreviewPanel(not previewBool)
\ No newline at end of file
+ self.settingsmanager.togglePreviewPanel(not previewBool)
diff --git a/openlp/core/ui/mediadockmanager.py b/openlp/core/ui/mediadockmanager.py
index 4d76075df..0873133b2 100644
--- a/openlp/core/ui/mediadockmanager.py
+++ b/openlp/core/ui/mediadockmanager.py
@@ -25,7 +25,7 @@
import logging
-log = logging.getLogger(u'MediaDockManager')
+log = logging.getLogger(__name__)
class MediaDockManager(object):
@@ -58,4 +58,4 @@ class MediaDockManager(object):
if self.media_dock.widget(dock_index):
if self.media_dock.widget(dock_index).ConfigSection == name:
self.media_dock.widget(dock_index).hide()
- self.media_dock.removeItem(dock_index)
\ No newline at end of file
+ self.media_dock.removeItem(dock_index)
diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py
index fa48c0723..9af8b7ca3 100644
--- a/openlp/core/ui/pluginform.py
+++ b/openlp/core/ui/pluginform.py
@@ -30,9 +30,9 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib.plugin import PluginStatus
from plugindialog import Ui_PluginViewDialog
+log = logging.getLogger(__name__)
+
class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
- global log
- log = logging.getLogger(u'PluginForm')
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
@@ -126,4 +126,4 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
elif self.activePlugin.status == PluginStatus.Disabled:
status_text = 'Disabled'
self.PluginListWidget.currentItem().setText(
- u'%s (%s)' % (self.activePlugin.name, status_text))
\ No newline at end of file
+ u'%s (%s)' % (self.activePlugin.name, status_text))
diff --git a/openlp/core/ui/screen.py b/openlp/core/ui/screen.py
new file mode 100644
index 000000000..b85b3b003
--- /dev/null
+++ b/openlp/core/ui/screen.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+import logging
+
+log = logging.getLogger(__name__)
+
+class ScreenList(object):
+ """
+ Wrapper to handle the parameters of the display screen
+ """
+ log.info(u'Screen loaded')
+
+ def __init__(self):
+ self.preview = None
+ self.current = None
+ self.screen_list = []
+ self.count = 0
+ self.current_display = 0
+
+ def add_screen(self, screen):
+ if screen[u'primary']:
+ self.current = screen
+ self.screen_list.append(screen)
+ self.count += 1
+
+ def screen_exists(self, number):
+ for screen in self.screen_list:
+ if screen[u'number'] == number:
+ return True
+ return False
+
+ def set_current_display(self, number):
+ if number + 1 > self.count:
+ self.current = self.screen_list[0]
+ self.current_display = 0
+ else:
+ self.current = self.screen_list[number]
+ self.preview = self.current
+ self.current_display = number
+ if self.count == 1:
+ self.preview = self.screen_list[0]
+
+# if self.screen[u'number'] != screenNumber:
+# # We will most probably never actually hit this bit, but just in
+# # case the index in the list doesn't match the screen number, we
+# # search for it.
+# for scrn in self.screens:
+# if scrn[u'number'] == screenNumber:
+# self.screen = scrn
+# break
diff --git a/openlp/core/ui/serviceitemdialog.py b/openlp/core/ui/serviceitemdialog.py
new file mode 100644
index 000000000..1fe86a913
--- /dev/null
+++ b/openlp/core/ui/serviceitemdialog.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtCore, QtGui
+
+class Ui_ServiceNoteEdit(object):
+ def setupUi(self, ServiceNoteEdit):
+ ServiceNoteEdit.setObjectName(u'ServiceNoteEdit')
+ ServiceNoteEdit.resize(400, 243)
+ self.widget = QtGui.QWidget(ServiceNoteEdit)
+ self.widget.setGeometry(QtCore.QRect(20, 10, 361, 223))
+ self.widget.setObjectName(u'widget')
+ self.verticalLayout = QtGui.QVBoxLayout(self.widget)
+ self.verticalLayout.setObjectName(u'verticalLayout')
+ self.textEdit = QtGui.QTextEdit(self.widget)
+ self.textEdit.setObjectName(u'textEdit')
+ self.verticalLayout.addWidget(self.textEdit)
+ self.buttonBox = QtGui.QDialogButtonBox(self.widget)
+ self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Save)
+ self.buttonBox.setObjectName(u'buttonBox')
+ self.verticalLayout.addWidget(self.buttonBox)
+
+ self.retranslateUi(ServiceNoteEdit)
+ QtCore.QMetaObject.connectSlotsByName(ServiceNoteEdit)
+
+ def retranslateUi(self, ServiceNoteEdit):
+ ServiceNoteEdit.setWindowTitle(self.trUtf8('Service Item Notes'))
diff --git a/openlp/core/ui/serviceitemform.py b/openlp/core/ui/serviceitemform.py
new file mode 100644
index 000000000..43011ead8
--- /dev/null
+++ b/openlp/core/ui/serviceitemform.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtCore, QtGui
+from serviceitemdialog import Ui_ServiceNoteEdit
+
+class ServiceItemNoteForm(QtGui.QDialog, Ui_ServiceNoteEdit):
+ """
+ This is the form that is used to edit the verses of the song.
+ """
+ def __init__(self, parent=None):
+ """
+ Constructor
+ """
+ QtGui.QDialog.__init__(self, parent)
+ self.setupUi(self)
+ QtCore.QObject.connect(self.buttonBox,
+ QtCore.SIGNAL(u'accepted()'),
+ self.accept)
+ QtCore.QObject.connect(self.buttonBox,
+ QtCore.SIGNAL(u'rejected()'),
+ self.reject)
diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py
index 7e9fca933..a0a198f2d 100644
--- a/openlp/core/ui/servicemanager.py
+++ b/openlp/core/ui/servicemanager.py
@@ -28,10 +28,13 @@ import logging
import cPickle
import zipfile
+log = logging.getLogger(__name__)
+
from PyQt4 import QtCore, QtGui
+
from openlp.core.lib import PluginConfig, OpenLPToolbar, ServiceItem, \
- ServiceItemType, contextMenuAction, contextMenuSeparator, contextMenu, \
- Receiver, contextMenu, str_to_bool
+ contextMenuAction, Receiver, str_to_bool, build_icon
+from openlp.core.ui import ServiceItemNoteForm
class ServiceManagerList(QtGui.QTreeWidget):
@@ -39,23 +42,6 @@ class ServiceManagerList(QtGui.QTreeWidget):
QtGui.QTreeWidget.__init__(self,parent)
self.parent = parent
-# def mousePressEvent(self, event):
-# if event.button() == QtCore.Qt.RightButton:
-# item = self.itemAt(event.pos())
-# parentitem = item.parent()
-# if parentitem is None:
-# pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
-# else:
-# pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
-# serviceItem = self.parent.serviceItems[pos - 1]
-# if serviceItem[u'data'].edit_enabled:
-# self.parent.editAction.setVisible(True)
-# else:
-# self.parent.editAction.setVisible(False)
-# event.accept()
-# else:
-# event.ignore()
-
def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent:
#here accept the event and do something
@@ -91,6 +77,7 @@ class ServiceManagerList(QtGui.QTreeWidget):
just tell it what plugin to call
"""
if event.buttons() != QtCore.Qt.LeftButton:
+ event.ignore()
return
drag = QtGui.QDrag(self)
mimeData = QtCore.QMimeData()
@@ -105,9 +92,6 @@ class ServiceManager(QtGui.QWidget):
the resources used into one OSZ file for use on any OpenLP v2 installation.
Also handles the UI tasks of moving things up and down etc.
"""
- global log
- log = logging.getLogger(u'ServiceManager')
-
def __init__(self, parent):
"""
Sets up the service manager, toolbars, list view, et al.
@@ -121,6 +105,7 @@ class ServiceManager(QtGui.QWidget):
#Indicates if remoteTriggering is active. If it is the next addServiceItem call
#will replace the currently selected one.
self.remoteEditTriggered = False
+ self.serviceItemNoteForm = ServiceItemNoteForm()
#start with the layout
self.Layout = QtGui.QVBoxLayout(self)
self.Layout.setSpacing(0)
@@ -161,62 +146,38 @@ class ServiceManager(QtGui.QWidget):
self.ServiceManagerList.setAlternatingRowColors(True)
self.ServiceManagerList.setHeaderHidden(True)
self.ServiceManagerList.setExpandsOnDoubleClick(False)
+ self.ServiceManagerList.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
+ self.ServiceManagerList.customContextMenuRequested.connect(self.contextMenu)
self.ServiceManagerList.setObjectName(u'ServiceManagerList')
# enable drop
self.ServiceManagerList.__class__.dragEnterEvent = self.dragEnterEvent
self.ServiceManagerList.__class__.dragMoveEvent = self.dragEnterEvent
self.ServiceManagerList.__class__.dropEvent = self.dropEvent
- # Add a context menu to the service manager list
- self.ServiceManagerList.setContextMenuPolicy(
- QtCore.Qt.ActionsContextMenu)
- self.editAction = contextMenuAction(
- self.ServiceManagerList, ':/system/system_live.png',
- self.trUtf8('&Edit Item'), self.remoteEdit)
- self.ServiceManagerList.addAction(self.editAction)
- self.ServiceManagerList.addAction(contextMenuSeparator(
- self.ServiceManagerList))
- self.ServiceManagerList.addAction(contextMenuAction(
- self.ServiceManagerList, ':/system/system_preview.png',
- self.trUtf8('&Preview Verse'), self.makePreview))
- self.ServiceManagerList.addAction(contextMenuAction(
- self.ServiceManagerList, ':/system/system_live.png',
- self.trUtf8('&Show Live'), self.makeLive))
- self.ServiceManagerList.addAction(contextMenuSeparator(
- self.ServiceManagerList))
- self.ServiceManagerList.addAction(contextMenuAction(
- self.ServiceManagerList, ':/services/service_delete',
- self.trUtf8('&Remove from Service'), self.onDeleteFromService))
- self.ServiceManagerList.addAction(contextMenuSeparator(
- self.ServiceManagerList))
- self.ThemeMenu = contextMenu(
- self.ServiceManagerList, '',
- self.trUtf8('&Change Item Theme'))
- self.ServiceManagerList.addAction(self.ThemeMenu.menuAction())
self.Layout.addWidget(self.ServiceManagerList)
# Add the bottom toolbar
self.OrderToolbar = OpenLPToolbar(self)
self.OrderToolbar.addToolbarButton(
- self.trUtf8('Move to top'), u':/services/service_top.png',
+ self.trUtf8('Move to &top'), u':/services/service_top.png',
self.trUtf8('Move to top'), self.onServiceTop)
self.OrderToolbar.addToolbarButton(
- self.trUtf8('Move up'), u':/services/service_up.png',
+ self.trUtf8('Move &up'), u':/services/service_up.png',
self.trUtf8('Move up order'), self.onServiceUp)
self.OrderToolbar.addToolbarButton(
- self.trUtf8('Move down'), u':/services/service_down.png',
+ self.trUtf8('Move &down'), u':/services/service_down.png',
self.trUtf8('Move down order'), self.onServiceDown)
self.OrderToolbar.addToolbarButton(
- self.trUtf8('Move to bottom'), u':/services/service_bottom.png',
+ self.trUtf8('Move to &bottom'), u':/services/service_bottom.png',
self.trUtf8('Move to end'), self.onServiceEnd)
self.OrderToolbar.addSeparator()
self.OrderToolbar.addToolbarButton(
- self.trUtf8('Delete From Service'), u':/services/service_delete.png',
+ self.trUtf8('&Delete From Service'), u':/services/service_delete.png',
self.trUtf8('Delete From Service'), self.onDeleteFromService)
self.Layout.addWidget(self.OrderToolbar)
# Connect up our signals and slots
QtCore.QObject.connect(self.ThemeComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onThemeComboBoxSelected)
QtCore.QObject.connect(self.ServiceManagerList,
- QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.makeLive)
+ QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.makeLive)
QtCore.QObject.connect(self.ServiceManagerList,
QtCore.SIGNAL(u'itemCollapsed(QTreeWidgetItem*)'), self.collapsed)
QtCore.QObject.connect(self.ServiceManagerList,
@@ -225,18 +186,99 @@ class ServiceManager(QtGui.QWidget):
QtCore.SIGNAL(u'update_themes'), self.updateThemeList)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'remote_edit_clear'), self.onRemoteEditClear)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'presentation types'), self.onPresentationTypes)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'servicemanager_next_item'), self.nextItem)
# Last little bits of setting up
self.config = PluginConfig(u'ServiceManager')
self.servicePath = self.config.get_data_path()
self.service_theme = unicode(
self.config.get_config(u'service theme', u''))
+ #build the context menu
+ self.menu = QtGui.QMenu()
+ self.editAction = self.menu.addAction(self.trUtf8('&Edit Item'))
+ self.editAction.setIcon(build_icon(u':/services/service_edit.png'))
+ self.notesAction = self.menu.addAction(self.trUtf8('&Notes'))
+ self.notesAction.setIcon(build_icon(u':/services/service_notes.png'))
+ self.deleteAction = self.menu.addAction(self.trUtf8('&Delete From Service'))
+ self.deleteAction.setIcon(build_icon(u':/services/service_delete.png'))
+ self.sep1 = self.menu.addAction(u'')
+ self.sep1.setSeparator(True)
+ self.previewAction = self.menu.addAction(self.trUtf8('&Preview Verse'))
+ self.previewAction.setIcon(build_icon(u':/system/system_preview.png'))
+ self.liveAction = self.menu.addAction(self.trUtf8('&Live Verse'))
+ self.liveAction.setIcon(build_icon(u':/system/system_live.png'))
+ self.sep2 = self.menu.addAction(u'')
+ self.sep2.setSeparator(True)
+ self.themeMenu = QtGui.QMenu(self.trUtf8(u'&Change Item Theme'))
+ self.menu.addMenu(self.themeMenu)
+
+ def contextMenu(self, point):
+ item = self.ServiceManagerList.itemAt(point)
+ if item.parent() is None:
+ pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
+ else:
+ pos = item.parent().data(0, QtCore.Qt.UserRole).toInt()[0]
+ serviceItem = self.serviceItems[pos - 1]
+ self.editAction.setVisible(False)
+ self.notesAction.setVisible(False)
+ if serviceItem[u'service_item'].edit_enabled:
+ self.editAction.setVisible(True)
+ if item.parent() is None:
+ self.notesAction.setVisible(True)
+ self.themeMenu.menuAction().setVisible(False)
+ if serviceItem[u'service_item'].is_text():
+ self.themeMenu.menuAction().setVisible(True)
+ action = self.menu.exec_(self.ServiceManagerList.mapToGlobal(point))
+ if action == self.editAction:
+ self.remoteEdit()
+ if action == self.deleteAction:
+ self.onDeleteFromService()
+ if action == self.notesAction:
+ self.onServiceItemNoteForm()
+ if action == self.previewAction:
+ self.makePreview()
+ if action == self.liveAction:
+ self.makeLive()
+
+ def onPresentationTypes(self, presentation_types):
+ self.presentation_types = presentation_types
+
+ def onServiceItemNoteForm(self):
+ item, count = self.findServiceItem()
+ self.serviceItemNoteForm.textEdit.setPlainText(
+ self.serviceItems[item][u'service_item'].notes)
+ if self.serviceItemNoteForm.exec_():
+ self.serviceItems[item][u'service_item'].notes = \
+ self.serviceItemNoteForm.textEdit.toPlainText()
+ self.repaintServiceList(item, 0)
+
+ def nextItem(self):
+ """
+ Called by the SlideController to select the
+ next service item
+ """
+ if len(self.ServiceManagerList.selectedItems()) == 0:
+ return
+ selected = self.ServiceManagerList.selectedItems()[0]
+ lookFor = 0
+ serviceIterator = QtGui.QTreeWidgetItemIterator(self.ServiceManagerList)
+ while serviceIterator.value():
+ if lookFor == 1 and serviceIterator.value().parent() is None:
+ self.ServiceManagerList.setCurrentItem(serviceIterator.value())
+ self.makeLive()
+ return
+ if serviceIterator.value() == selected:
+ lookFor = 1
+ serviceIterator += 1
def onMoveSelectionUp(self):
"""
Moves the selection up the window
Called by the up arrow
"""
- serviceIterator = QTreeWidgetItemIterator(self.ServiceManagerList)
+ serviceIterator = QtGui.QTreeWidgetItemIterator(self.ServiceManagerList)
tempItem = None
setLastItem = False
while serviceIterator:
@@ -261,7 +303,7 @@ class ServiceManager(QtGui.QWidget):
Moves the selection down the window
Called by the down arrow
"""
- serviceIterator = QTreeWidgetItemIterator(self.ServiceManagerList)
+ serviceIterator = QtGui.QTreeWidgetItemIterator(self.ServiceManagerList)
firstItem = serviceIterator
setSelected = False
while serviceIterator:
@@ -348,7 +390,7 @@ class ServiceManager(QtGui.QWidget):
if self.parent.serviceNotSaved and \
str_to_bool(PluginConfig(u'General').
get_config(u'save prompt', u'False')):
- ret = QtGui.QMessageBox.question(None,
+ ret = QtGui.QMessageBox.question(self,
self.trUtf8('Save Changes to Service?'),
self.trUtf8('Your service is unsaved, do you want to save those '
'changes before creating a new one ?'),
@@ -390,19 +432,35 @@ class ServiceManager(QtGui.QWidget):
for itemcount, item in enumerate(self.serviceItems):
serviceitem = item[u'service_item']
treewidgetitem = QtGui.QTreeWidgetItem(self.ServiceManagerList)
- treewidgetitem.setText(0,serviceitem.title)
- treewidgetitem.setIcon(0,serviceitem.iconic_representation)
+ if serviceitem.notes:
+ icon = QtGui.QImage(serviceitem.icon)
+ icon = icon.scaled(80, 80, QtCore.Qt.KeepAspectRatio,
+ QtCore.Qt.SmoothTransformation)
+ overlay = QtGui.QImage(':/services/service_item_notes.png')
+ overlay = overlay.scaled(80, 80, QtCore.Qt.KeepAspectRatio,
+ QtCore.Qt.SmoothTransformation)
+ painter = QtGui.QPainter(icon)
+ painter.drawImage(0, 0, overlay)
+ painter.end()
+ treewidgetitem.setIcon(0, build_icon(icon))
+ else:
+ treewidgetitem.setIcon(0, serviceitem.iconic_representation)
+ treewidgetitem.setText(0, serviceitem.title)
+ treewidgetitem.setToolTip(0, serviceitem.notes)
treewidgetitem.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(item[u'order']))
- treewidgetitem.setExpanded(item[u'expanded'])
for count, frame in enumerate(serviceitem.get_frames()):
treewidgetitem1 = QtGui.QTreeWidgetItem(treewidgetitem)
text = frame[u'title']
- treewidgetitem1.setText(0,text[:40])
+ treewidgetitem1.setText(0, text[:40])
treewidgetitem1.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(count))
if serviceItem == itemcount and serviceItemCount == count:
- self.ServiceManagerList.setCurrentItem(treewidgetitem1)
+ #preserve expanding status as setCurrentItem sets it to True
+ temp = item[u'expanded']
+ self.ServiceManagerList.setCurrentItem(treewidgetitem1)
+ item[u'expanded'] = temp
+ treewidgetitem.setExpanded(item[u'expanded'])
def onSaveService(self, quick=False):
"""
@@ -433,10 +491,10 @@ class ServiceManager(QtGui.QWidget):
for item in self.serviceItems:
service.append({u'serviceitem':item[u'service_item'].get_service_repr()})
if item[u'service_item'].uses_file():
- for frame in item[u'service_item'].get_frames:
+ for frame in item[u'service_item'].get_frames():
path_from = unicode(os.path.join(
item[u'service_item'].service_item_path,
- frame.get_frame_title()))
+ frame[u'title']))
zip.write(path_from)
file = open(servicefile, u'wb')
cPickle.dump(service, file)
@@ -499,7 +557,8 @@ class ServiceManager(QtGui.QWidget):
serviceitem = ServiceItem()
serviceitem.RenderManager = self.parent.RenderManager
serviceitem.set_from_service(item, self.servicePath)
- self.addServiceItem(serviceitem)
+ if self.validateItem(serviceitem):
+ self.addServiceItem(serviceitem)
try:
if os.path.isfile(p_file):
os.remove(p_file)
@@ -516,6 +575,14 @@ class ServiceManager(QtGui.QWidget):
self.serviceName = name[len(name) - 1]
self.parent.serviceChanged(True, self.serviceName)
+ def validateItem(self, serviceItem):
+# print "---"
+# print serviceItem.name
+# print serviceItem.title
+# print serviceItem.service_item_path
+# print serviceItem.service_item_type
+ return True
+
def cleanUp(self):
"""
Empties the servicePath of temporary files
@@ -538,13 +605,20 @@ class ServiceManager(QtGui.QWidget):
self.regenerateServiceItems()
def regenerateServiceItems(self):
- if len(self.serviceItems) > 0:
+ #force reset of renderer as theme data has changed
+ self.parent.RenderManager.themedata = None
+ if self.serviceItems:
tempServiceItems = self.serviceItems
- self.onNewService()
+ self.ServiceManagerList.clear()
+ self.serviceItems = []
+ self.isNew = True
for item in tempServiceItems:
- self.addServiceItem(item[u'service_item'])
+ self.addServiceItem(item[u'service_item'], False, item[u'expanded'])
+ #Set to False as items may have changed rendering
+ #does not impact the saved song so True may aslo be valid
+ self.parent.serviceChanged(False, self.serviceName)
- def addServiceItem(self, item):
+ def addServiceItem(self, item, rebuild=False, expand=True):
"""
Add a Service item to the list
@@ -564,13 +638,16 @@ class ServiceManager(QtGui.QWidget):
if sitem == -1:
self.serviceItems.append({u'service_item': item,
u'order': len(self.serviceItems) + 1,
- u'expanded':True})
+ u'expanded':expand})
self.repaintServiceList(len(self.serviceItems) + 1, 0)
else:
self.serviceItems.insert(sitem + 1, {u'service_item': item,
u'order': len(self.serviceItems)+1,
- u'expanded':True})
+ u'expanded':expand})
self.repaintServiceList(sitem + 1, 0)
+ #if rebuilding list make sure live is fixed.
+ if rebuild:
+ self.parent.LiveController.replaceServiceManagerItem(item)
self.parent.serviceChanged(False, self.serviceName)
def makePreview(self):
@@ -581,6 +658,7 @@ class ServiceManager(QtGui.QWidget):
self.parent.PreviewController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], count)
+
def makeLive(self):
"""
Send the current item to the Live slide controller
@@ -588,6 +666,13 @@ class ServiceManager(QtGui.QWidget):
item, count = self.findServiceItem()
self.parent.LiveController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], count)
+ if str_to_bool(PluginConfig(u'General').
+ get_config(u'auto preview', u'False')):
+ item += 1
+ if self.serviceItems and item < len(self.serviceItems) and \
+ self.serviceItems[item][u'service_item'].autoPreviewAllowed:
+ self.parent.PreviewController.addServiceManagerItem(
+ self.serviceItems[item][u'service_item'], 0)
def remoteEdit(self):
"""
@@ -617,7 +702,7 @@ class ServiceManager(QtGui.QWidget):
else:
pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
count = item.data(0, QtCore.Qt.UserRole).toInt()[0]
- #adjuest for zero based arrays
+ #adjust for zero based arrays
pos = pos - 1
return pos, count
@@ -646,7 +731,7 @@ class ServiceManager(QtGui.QWidget):
if plugin == u'ServiceManager':
startpos, startCount = self.findServiceItem()
item = self.ServiceManagerList.itemAt(event.pos())
- if item == None:
+ if item is None:
endpos = len(self.serviceItems)
else:
parentitem = item.parent()
@@ -674,7 +759,7 @@ class ServiceManager(QtGui.QWidget):
A list of current themes to be displayed
"""
self.ThemeComboBox.clear()
- self.ThemeMenu.clear()
+ self.themeMenu.clear()
self.ThemeComboBox.addItem(u'')
for theme in theme_list:
self.ThemeComboBox.addItem(theme)
@@ -682,7 +767,7 @@ class ServiceManager(QtGui.QWidget):
self.ServiceManagerList,
None,
theme , self.onThemeChangeAction)
- self.ThemeMenu.addAction(action)
+ self.themeMenu.addAction(action)
id = self.ThemeComboBox.findText(self.service_theme,
QtCore.Qt.MatchExactly)
# Not Found
@@ -697,4 +782,4 @@ class ServiceManager(QtGui.QWidget):
theme = unicode(self.sender().text())
item, count = self.findServiceItem()
self.serviceItems[item][u'service_item'].theme = theme
- self.regenerateServiceItems()
\ No newline at end of file
+ self.regenerateServiceItems()
diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py
index ed5bd9d76..4a3902347 100644
--- a/openlp/core/ui/settingsform.py
+++ b/openlp/core/ui/settingsform.py
@@ -27,11 +27,11 @@ import logging
from PyQt4 import QtGui
-from openlp.core.ui import GeneralTab, ThemesTab, AlertsTab
+from openlp.core.ui import GeneralTab, ThemesTab
from openlp.core.lib import Receiver
from settingsdialog import Ui_SettingsDialog
-log = logging.getLogger(u'SettingsForm')
+log = logging.getLogger(__name__)
class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
@@ -44,9 +44,6 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
# Themes tab
self.ThemesTab = ThemesTab(mainWindow)
self.addTab(u'Themes', self.ThemesTab)
- # Alert tab
- self.AlertsTab = AlertsTab()
- self.addTab(u'Alerts', self.AlertsTab)
def addTab(self, name, tab):
log.info(u'Adding %s tab' % tab.tabTitle)
@@ -73,4 +70,4 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
def postSetUp(self):
for tab_index in range(0, self.SettingsTabWidget.count()):
- self.SettingsTabWidget.widget(tab_index).postSetUp()
\ No newline at end of file
+ self.SettingsTabWidget.widget(tab_index).postSetUp()
diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py
index 59dd857ac..e26df7a18 100644
--- a/openlp/core/ui/slidecontroller.py
+++ b/openlp/core/ui/slidecontroller.py
@@ -30,7 +30,10 @@ import os
from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
-from openlp.core.lib import OpenLPToolbar, Receiver, str_to_bool, PluginConfig
+from openlp.core.lib import OpenLPToolbar, Receiver, str_to_bool, \
+ PluginConfig, resize_image
+
+log = logging.getLogger(__name__)
class SlideList(QtGui.QTableWidget):
"""
@@ -40,6 +43,11 @@ class SlideList(QtGui.QTableWidget):
def __init__(self, parent=None, name=None):
QtGui.QTableWidget.__init__(self, parent.Controller)
self.parent = parent
+ self.hotkey_map = {QtCore.Qt.Key_Return: 'servicemanager_next_item',
+ QtCore.Qt.Key_Space: 'live_slidecontroller_next_noloop',
+ QtCore.Qt.Key_Enter: 'live_slidecontroller_next_noloop',
+ QtCore.Qt.Key_0: 'servicemanager_next_item',
+ QtCore.Qt.Key_Backspace: 'live_slidecontroller_previous_noloop'}
def keyPressEvent(self, event):
if type(event) == QtGui.QKeyEvent:
@@ -56,6 +64,9 @@ class SlideList(QtGui.QTableWidget):
elif event.key() == QtCore.Qt.Key_PageDown:
self.parent.onSlideSelectedLast()
event.accept()
+ elif event.key() in self.hotkey_map and self.parent.isLive:
+ Receiver.send_message(self.hotkey_map[event.key()])
+ event.accept()
event.ignore()
else:
event.ignore()
@@ -65,9 +76,6 @@ class SlideController(QtGui.QWidget):
SlideController is the slide controller widget. This widget is what the
user uses to control the displaying of verses/slides/etc on the screen.
"""
- global log
- log = logging.getLogger(u'SlideController')
-
def __init__(self, parent, settingsmanager, isLive=False):
"""
Set up the Slide Controller.
@@ -99,15 +107,14 @@ class SlideController(QtGui.QWidget):
# Type label for the top of the slide controller
self.TypeLabel = QtGui.QLabel(self.Panel)
if self.isLive:
- self.TypeLabel.setText(u'%s' %
- self.trUtf8('Live'))
+ self.TypeLabel.setText(self.trUtf8('Live'))
self.split = 1
prefix = u'live_slidecontroller'
else:
- self.TypeLabel.setText(u'%s' %
- self.trUtf8('Preview'))
+ self.TypeLabel.setText(self.trUtf8('Preview'))
self.split = 0
prefix = u'preview_slidecontroller'
+ self.TypeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;')
self.TypeLabel.setAlignment(QtCore.Qt.AlignCenter)
self.PanelLayout.addWidget(self.TypeLabel)
# Splitter
@@ -135,6 +142,7 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.setEditTriggers(
QtGui.QAbstractItemView.NoEditTriggers)
self.PreviewListWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+ self.PreviewListWidget.setAlternatingRowColors(True)
self.ControllerLayout.addWidget(self.PreviewListWidget)
# Build the full toolbar
self.Toolbar = OpenLPToolbar(self)
@@ -163,9 +171,9 @@ class SlideController(QtGui.QWidget):
self.Toolbar.addToolbarSeparator(u'Close Separator')
self.blankButton = self.Toolbar.addToolbarButton(
u'Blank Screen', u':/slides/slide_close.png',
- self.trUtf8('Blank Screen'), self.onBlankScreen, True)
+ self.trUtf8('Blank Screen'), self.onBlankDisplay, True)
QtCore.QObject.connect(Receiver.get_receiver(),
- QtCore.SIGNAL(u'live_slide_blank'), self.onBlankDisplay)
+ QtCore.SIGNAL(u'live_slide_blank'), self.blankScreen)
if not self.isLive:
self.Toolbar.addToolbarSeparator(u'Close Separator')
self.Toolbar.addToolbarButton(
@@ -173,7 +181,7 @@ class SlideController(QtGui.QWidget):
self.trUtf8('Move to live'), self.onGoLive)
self.Toolbar.addToolbarSeparator(u'Close Separator')
self.Toolbar.addToolbarButton(
- u'Edit Song', u':/songs/song_edit.png',
+ u'Edit Song', u':/services/service_edit.png',
self.trUtf8('Edit and re-preview Song'), self.onEditSong)
if isLive:
self.Toolbar.addToolbarSeparator(u'Loop Separator')
@@ -184,6 +192,8 @@ class SlideController(QtGui.QWidget):
u'Stop Loop', u':/media/media_stop.png',
self.trUtf8('Stop continuous loop'), self.onStopLoop)
self.DelaySpinBox = QtGui.QSpinBox()
+ self.DelaySpinBox.setMinimum(1)
+ self.DelaySpinBox.setMaximum(180)
self.Toolbar.addToolbarWidget(
u'Image SpinBox', self.DelaySpinBox)
self.DelaySpinBox.setSuffix(self.trUtf8('s'))
@@ -235,6 +245,9 @@ class SlideController(QtGui.QWidget):
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
Phonon.createPath(self.mediaObject, self.video)
Phonon.createPath(self.mediaObject, self.audio)
+ if not self.isLive:
+ self.video.setGeometry(QtCore.QRect(0, 0, 300, 225))
+ self.video.setVisible(False)
self.SlideLayout.insertWidget(0, self.video)
# Actual preview screen
self.SlidePreview = QtGui.QLabel(self)
@@ -246,7 +259,8 @@ class SlideController(QtGui.QWidget):
self.SlidePreview.sizePolicy().hasHeightForWidth())
self.SlidePreview.setSizePolicy(sizePolicy)
self.SlidePreview.setFixedSize(
- QtCore.QSize(self.settingsmanager.slidecontroller_image,self.settingsmanager.slidecontroller_image / 1.3 ))
+ QtCore.QSize(self.settingsmanager.slidecontroller_image,
+ self.settingsmanager.slidecontroller_image / 1.3 ))
self.SlidePreview.setFrameShape(QtGui.QFrame.Box)
self.SlidePreview.setFrameShadow(QtGui.QFrame.Plain)
self.SlidePreview.setLineWidth(1)
@@ -257,8 +271,6 @@ class SlideController(QtGui.QWidget):
# Signals
QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
- QtCore.QObject.connect(self.PreviewListWidget,
- QtCore.SIGNAL(u'activated(QModelIndex)'), self.onSlideSelected)
if isLive:
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'update_spin_delay'), self.receiveSpinDelay)
@@ -268,12 +280,19 @@ class SlideController(QtGui.QWidget):
else:
self.Toolbar.makeWidgetsInvisible(self.song_edit_list)
self.Mediabar.setVisible(False)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'stop_display_loop'), self.onStopLoop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_first' % prefix), self.onSlideSelectedFirst)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_next' % prefix), self.onSlideSelectedNext)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_previous' % prefix), self.onSlideSelectedPrevious)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'%s_next_noloop' % prefix), self.onSlideSelectedNextNoloop)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'%s_previous_noloop' % prefix),
+ self.onSlideSelectedPreviousNoloop)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_last' % prefix), self.onSlideSelectedLast)
QtCore.QObject.connect(Receiver.get_receiver(),
@@ -393,9 +412,13 @@ class SlideController(QtGui.QWidget):
if item.is_media():
self.onMediaStart(item)
elif item.is_command():
+ if self.isLive:
+ blanked = self.blankButton.isChecked()
+ else:
+ blanked = False
Receiver.send_message(u'%s_start' % item.name.lower(), \
[item.title, item.service_item_path,
- item.get_frame_title(), slideno, self.isLive])
+ item.get_frame_title(), slideno, self.isLive, blanked])
self.displayServiceManagerItems(item, slideno)
def displayServiceManagerItems(self, serviceItem, slideno):
@@ -428,9 +451,11 @@ class SlideController(QtGui.QWidget):
tag = None
#If verse handle verse number else tag only
if bits[0] == self.trUtf8('Verse'):
- tag = u'%s%s' % (bits[0][0], bits[1][0] )
+ tag = u'%s%s' % (bits[0][0], bits[1][0:] )
+ row = bits[1][0:]
else:
tag = bits[0]
+ row = bits[0][0:1]
try:
test = self.slideList[tag]
except:
@@ -441,7 +466,9 @@ class SlideController(QtGui.QWidget):
else:
label = QtGui.QLabel()
label.setMargin(4)
- pixmap = self.parent.RenderManager.resize_image(frame[u'image'])
+ pixmap = resize_image(frame[u'image'],
+ self.parent.RenderManager.width,
+ self.parent.RenderManager.height)
label.setScaledContents(True)
label.setPixmap(QtGui.QPixmap.fromImage(pixmap))
self.PreviewListWidget.setCellWidget(framenumber, 0, label)
@@ -480,18 +507,26 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.selectRow(0)
self.onSlideSelected()
- def onBlankDisplay(self):
- self.blankButton.setChecked(self.parent.mainDisplay.displayBlank)
+ def onBlankDisplay(self, force=False):
+ """
+ Handle the blank screen button
+ """
+ if force:
+ self.blankButton.setChecked(True)
+ self.blankScreen(self.blankButton.isChecked())
+ self.parent.generalConfig.set_config(u'screen blank',
+ self.blankButton.isChecked())
- def onBlankScreen(self, blanked):
+ def blankScreen(self, blanked=False):
"""
- Blank the screen.
+ Blank the display screen.
"""
- if not self.serviceItem and self.serviceItem.is_command():
- if blanked:
- Receiver.send_message(u'%s_blank'% self.serviceItem.name.lower())
- else:
- Receiver.send_message(u'%s_unblank'% self.serviceItem.name.lower())
+ if self.serviceItem is not None:
+ if self.serviceItem.is_command():
+ if blanked:
+ Receiver.send_message(u'%s_blank'% self.serviceItem.name.lower())
+ else:
+ Receiver.send_message(u'%s_unblank'% self.serviceItem.name.lower())
else:
self.parent.mainDisplay.blankDisplay(blanked)
@@ -531,7 +566,7 @@ class SlideController(QtGui.QWidget):
def updatePreview(self):
rm = self.parent.RenderManager
- if not rm.screen_list[rm.current_display][u'primary']:
+ if not rm.screens.current[u'primary']:
# Grab now, but try again in a couple of seconds if slide change is slow
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
@@ -543,12 +578,15 @@ class SlideController(QtGui.QWidget):
def grabMainDisplay(self):
rm = self.parent.RenderManager
winid = QtGui.QApplication.desktop().winId()
- rect = rm.screen_list[rm.current_display][u'size']
+ rect = rm.screens.current[u'size']
winimg = QtGui.QPixmap.grabWindow(winid, rect.x(),
rect.y(), rect.width(), rect.height())
self.SlidePreview.setPixmap(winimg)
- def onSlideSelectedNext(self):
+ def onSlideSelectedNextNoloop(self):
+ self.onSlideSelectedNext(False)
+
+ def onSlideSelectedNext(self, loop=True):
"""
Go to the next slide.
"""
@@ -561,11 +599,18 @@ class SlideController(QtGui.QWidget):
else:
row = self.PreviewListWidget.currentRow() + 1
if row == self.PreviewListWidget.rowCount():
- row = 0
+ if loop:
+ row = 0
+ else:
+ Receiver.send_message('servicemanager_next_item')
+ return
self.PreviewListWidget.selectRow(row)
self.onSlideSelected()
- def onSlideSelectedPrevious(self):
+ def onSlideSelectedPreviousNoloop(self):
+ self.onSlideSelectedPrevious(False)
+
+ def onSlideSelectedPrevious(self, loop=True):
"""
Go to the previous slide.
"""
@@ -578,7 +623,10 @@ class SlideController(QtGui.QWidget):
else:
row = self.PreviewListWidget.currentRow() - 1
if row == -1:
- row = self.PreviewListWidget.rowCount() - 1
+ if loop:
+ row = self.PreviewListWidget.rowCount() - 1
+ else:
+ row = 0
self.PreviewListWidget.selectRow(row)
self.onSlideSelected()
@@ -635,7 +683,7 @@ class SlideController(QtGui.QWidget):
if self.isLive:
Receiver.send_message(u'%s_start' % item.name.lower(), \
[item.title, item.service_item_path,
- item.get_frame_title(), slideno, self.isLive])
+ item.get_frame_title(), self.isLive, self.blankButton.isChecked()])
else:
self.mediaObject.stop()
self.mediaObject.clearQueue()
@@ -659,9 +707,9 @@ class SlideController(QtGui.QWidget):
def onMediaStop(self):
if self.isLive:
- Receiver.send_message(u'%s_stop'% self.serviceItem.name.lower())
+ Receiver.send_message(u'%s_stop'% self.serviceItem.name.lower(), self.isLive)
else:
self.mediaObject.stop()
self.video.hide()
- self.SlidePreview.clear()
- self.SlidePreview.show()
\ No newline at end of file
+ self.SlidePreview.clear()
+ self.SlidePreview.show()
diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py
index fd0284412..5cad41f58 100644
--- a/openlp/core/ui/thememanager.py
+++ b/openlp/core/ui/thememanager.py
@@ -34,17 +34,16 @@ from PyQt4 import QtCore, QtGui
from openlp.core.ui import AmendThemeForm
from openlp.core.theme import Theme
from openlp.core.lib import PluginConfig, OpenLPToolbar, contextMenuAction, \
- ThemeXML, ThemeLevel, str_to_bool, get_text_file_string, build_icon, \
- Receiver, contextMenuSeparator
+ ThemeXML, str_to_bool, get_text_file_string, build_icon, Receiver, \
+ contextMenuSeparator
from openlp.core.utils import ConfigHelper
+log = logging.getLogger(__name__)
+
class ThemeManager(QtGui.QWidget):
"""
Manages the orders of Theme.
"""
- global log
- log = logging.getLogger(u'ThemeManager')
-
def __init__(self, parent):
QtGui.QWidget.__init__(self, parent)
self.parent = parent
@@ -108,6 +107,8 @@ class ThemeManager(QtGui.QWidget):
self.themelist = []
self.path = os.path.join(ConfigHelper.get_data_path(), u'themes')
self.checkThemesExists(self.path)
+ self.thumbPath = os.path.join(self.path, u'.thumbnails')
+ self.checkThemesExists(self.thumbPath)
self.amendThemeForm.path = self.path
# Last little bits of setting up
self.config = PluginConfig(u'themes')
@@ -179,12 +180,26 @@ class ThemeManager(QtGui.QWidget):
self.trUtf8('You are unable to delete the default theme!'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
else:
+ for plugin in self.parent.plugin_manager.plugins:
+ if not plugin.can_delete_theme(theme):
+ QtGui.QMessageBox.critical(
+ self, self.trUtf8('Error'),
+ self.trUtf8('theme %s is use in %s plugin' % (theme, plugin.name)),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
+ return
+ if unicode(self.parent.ServiceManagerContents.ThemeComboBox.currentText()) == theme:
+ QtGui.QMessageBox.critical(
+ self, self.trUtf8('Error'),
+ self.trUtf8('theme %s is use Service Manager' % theme),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
+ return
self.themelist.remove(theme)
th = theme + u'.png'
row = self.ThemeListWidget.row(item)
self.ThemeListWidget.takeItem(row)
try:
os.remove(os.path.join(self.path, th))
+ os.remove(os.path.join(self.thumbPath, th))
shutil.rmtree(os.path.join(self.path, theme))
except:
#if not present do not worry
@@ -231,9 +246,9 @@ class ThemeManager(QtGui.QWidget):
self, self.trUtf8('Select Theme Import File'),
self.config.get_last_dir(), u'Theme (*.*)')
log.info(u'New Themes %s', unicode(files))
- if len(files) > 0:
+ if files:
for file in files:
- self.config.set_last_dir(filename)
+ self.config.set_last_dir(unicode(file))
self.unzipTheme(file, self.path)
self.loadThemes()
@@ -246,25 +261,33 @@ class ThemeManager(QtGui.QWidget):
log.debug(u'Load themes from dir')
self.themelist = []
self.ThemeListWidget.clear()
- for root, dirs, files in os.walk(self.path):
- for name in files:
- if name.endswith(u'.png'):
- #check to see file is in theme root directory
- theme = os.path.join(self.path, name)
- if os.path.exists(theme):
- (path, filename) = os.path.split(unicode(file))
- textName = os.path.splitext(name)[0]
- if textName == self.global_theme:
- name = u'%s (%s)' % (textName,
- self.trUtf8('default'))
- else:
- name = textName
- item_name = QtGui.QListWidgetItem(name)
- item_name.setIcon(build_icon(theme))
- item_name.setData(QtCore.Qt.UserRole,
- QtCore.QVariant(textName))
- self.ThemeListWidget.addItem(item_name)
- self.themelist.append(textName)
+ #root, dirs, files = os.walk(self.path)
+ dirList = os.listdir(self.path)
+ for name in dirList:
+ if name.endswith(u'.png'):
+ #check to see file is in theme root directory
+ theme = os.path.join(self.path, name)
+ if os.path.exists(theme):
+ (path, filename) = os.path.split(unicode(file))
+ textName = os.path.splitext(name)[0]
+ if textName == self.global_theme:
+ name = u'%s (%s)' % (textName,
+ self.trUtf8('default'))
+ else:
+ name = textName
+ thumb = os.path.join(self.thumbPath, u'%s.png' % textName)
+ item_name = QtGui.QListWidgetItem(name)
+ if os.path.exists(thumb):
+ icon = build_icon(thumb)
+ else:
+ icon = build_icon(theme)
+ pixmap = icon.pixmap(QtCore.QSize(88,50))
+ pixmap.save(thumb, u'png')
+ item_name.setIcon(icon)
+ item_name.setData(QtCore.Qt.UserRole,
+ QtCore.QVariant(textName))
+ self.ThemeListWidget.addItem(item_name)
+ self.themelist.append(textName)
self.pushThemes()
def pushThemes(self):
@@ -302,17 +325,23 @@ class ThemeManager(QtGui.QWidget):
filexml = None
themename = None
for file in zip.namelist():
- if file.endswith(os.path.sep):
- theme_dir = os.path.join(dir, file)
+ osfile = unicode(QtCore.QDir.toNativeSeparators(file))
+ theme_dir = None
+ if osfile.endswith(os.path.sep):
+ theme_dir = os.path.join(dir, osfile)
if not os.path.exists(theme_dir):
- os.mkdir(os.path.join(dir, file))
+ os.mkdir(os.path.join(dir, osfile))
else:
- fullpath = os.path.join(dir, file)
- names = file.split(os.path.sep)
+ fullpath = os.path.join(dir, osfile)
+ names = osfile.split(os.path.sep)
if len(names) > 1:
# not preview file
if themename is None:
themename = names[0]
+ if theme_dir is None:
+ theme_dir = os.path.join(dir, names[0])
+ if not os.path.exists(theme_dir):
+ os.mkdir(os.path.join(dir, names[0]))
xml_data = zip.read(file)
if os.path.splitext(file)[1].lower() in [u'.xml']:
if self.checkVersion1(xml_data):
@@ -324,7 +353,7 @@ class ThemeManager(QtGui.QWidget):
outfile = open(fullpath, u'w')
outfile.write(filexml)
else:
- outfile = open(fullpath, u'w')
+ outfile = open(fullpath, u'wb')
outfile.write(zip.read(file))
self.generateAndSaveImage(dir, themename, filexml)
except:
@@ -332,7 +361,7 @@ class ThemeManager(QtGui.QWidget):
self, self.trUtf8('Error'),
self.trUtf8('File is not a valid theme!'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
- log.exception(u'Importing theme from zip file failed')
+ log.exception(u'Importing theme from zip file failed %s' % filename)
finally:
if zip:
zip.close()
@@ -373,7 +402,6 @@ class ThemeManager(QtGui.QWidget):
unicode(theme.BackgroundParameter2.name()), direction)
else:
newtheme.add_background_image(unicode(theme.BackgroundParameter1))
-
newtheme.add_font(unicode(theme.FontName),
unicode(theme.FontColor.name()),
unicode(theme.FontProportion * 3), u'False')
@@ -386,10 +414,15 @@ class ThemeManager(QtGui.QWidget):
shadow = True
if theme.Outline == 1:
outline = True
+ vAlignCorrection = 0
+ if theme.VerticalAlign == 2:
+ vAlignCorrection = 1
+ elif theme.VerticalAlign == 1:
+ vAlignCorrection = 2
newtheme.add_display(unicode(shadow), unicode(theme.ShadowColor.name()),
unicode(outline), unicode(theme.OutlineColor.name()),
- unicode(theme.HorizontalAlign), unicode(theme.VerticalAlign),
- unicode(theme.WrapStyle), 0)
+ unicode(theme.HorizontalAlign), unicode(vAlignCorrection),
+ unicode(theme.WrapStyle), unicode(0))
return newtheme.extract_xml()
def saveTheme(self, name, theme_xml, theme_pretty_xml, image_from,
@@ -427,8 +460,6 @@ class ThemeManager(QtGui.QWidget):
if outfile:
outfile.close()
if image_from and image_from != image_to:
- print "if", image_from
- print "it", image_to
try:
shutil.copyfile(image_from, image_to)
except:
@@ -448,6 +479,10 @@ class ThemeManager(QtGui.QWidget):
if os.path.exists(samplepathname):
os.unlink(samplepathname)
frame.save(samplepathname, u'png')
+ thumb = os.path.join(self.thumbPath, u'%s.png' % name)
+ icon = build_icon(frame)
+ pixmap = icon.pixmap(QtCore.QSize(88,50))
+ pixmap.save(thumb, u'png')
log.debug(u'Theme image written to %s', samplepathname)
def generateImage(self, themedata):
@@ -529,4 +564,4 @@ class ThemeManager(QtGui.QWidget):
theme.font_main_y = int(theme.font_main_y.strip())
#theme.theme_mode
theme.theme_name = theme.theme_name.strip()
- #theme.theme_version
\ No newline at end of file
+ #theme.theme_version
diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py
index 962aa69bd..4083300a6 100644
--- a/openlp/core/utils/__init__.py
+++ b/openlp/core/utils/__init__.py
@@ -22,21 +22,65 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+
+import os
+import sys
import logging
import urllib2
from datetime import datetime
-from registry import Registry
-from confighelper import ConfigHelper
-
log = logging.getLogger(__name__)
-__all__ = ['Registry', 'ConfigHelper']
+class AppLocation(object):
+ """
+ Retrieve a directory based on the directory type.
+ """
+ AppDir = 1
+ ConfigDir = 2
+ DataDir = 3
+ PluginsDir = 4
+
+ @staticmethod
+ def get_directory(dir_type):
+ if dir_type == AppLocation.AppDir:
+ return os.path.abspath(os.path.split(sys.argv[0])[0])
+ elif dir_type == AppLocation.ConfigDir:
+ if os.name == u'nt':
+ path = os.path.join(os.getenv(u'APPDATA'), u'openlp')
+ elif os.name == u'mac':
+ path = os.path.join(os.getenv(u'HOME'), u'Library',
+ u'Application Support', u'openlp')
+ else:
+ try:
+ from xdg import BaseDirectory
+ path = os.path.join(BaseDirectory.xdg_config_home, u'openlp')
+ except ImportError:
+ path = os.path.join(os.getenv(u'HOME'), u'.openlp')
+ return path
+ elif dir_type == AppLocation.DataDir:
+ if os.name == u'nt':
+ path = os.path.join(os.getenv(u'APPDATA'), u'openlp', u'data')
+ elif os.name == u'mac':
+ path = os.path.join(os.getenv(u'HOME'), u'Library',
+ u'Application Support', u'openlp', u'Data')
+ else:
+ try:
+ from xdg import BaseDirectory
+ path = os.path.join(BaseDirectory.xdg_data_home, u'openlp')
+ except ImportError:
+ path = os.path.join(os.getenv(u'HOME'), u'.openlp', u'data')
+ return path
+ elif dir_type == AppLocation.PluginsDir:
+ app_path = os.path.abspath(os.path.split(sys.argv[0])[0])
+ if hasattr(sys, u'frozen') and sys.frozen == 1:
+ return os.path.join(app_path, u'plugins')
+ else:
+ return os.path.join(app_path, u'openlp', u'plugins')
-log = logging.getLogger(__name__)
def check_latest_version(config, current_version):
version_string = current_version
+ #set to prod in the distribution confif file.
last_test = config.get_config(u'last version test', datetime.now().date())
this_test = unicode(datetime.now().date())
config.set_config(u'last version test', this_test)
@@ -52,3 +96,8 @@ def check_latest_version(config, current_version):
if hasattr(e, u'reason'):
log.exception(u'Reason for failure: %s', e.reason)
return version_string
+
+from registry import Registry
+from confighelper import ConfigHelper
+
+__all__ = [u'Registry', u'ConfigHelper', u'AppLocations', u'check_latest_version']
diff --git a/openlp/core/utils/confighelper.py b/openlp/core/utils/confighelper.py
index 112712675..7920013f2 100644
--- a/openlp/core/utils/confighelper.py
+++ b/openlp/core/utils/confighelper.py
@@ -24,6 +24,8 @@
###############################################################################
import os
+
+from openlp.core.utils import AppLocation
from openlp.core.utils.registry import Registry
class ConfigHelper(object):
@@ -34,20 +36,7 @@ class ConfigHelper(object):
@staticmethod
def get_data_path():
- if os.name == u'nt':
- # ask OS for path to application data, set on Windows XP and Vista
- path = os.path.join(os.getenv(u'APPDATA'), u'openlp', u'data')
- elif os.name == u'mac':
- path = os.path.join(os.getenv(u'HOME'), u'Library',
- u'Application Support', u'openlp', u'Data')
- else:
- try:
- from xdg import BaseDirectory
- path = os.path.join(BaseDirectory.xdg_data_home, u'openlp')
- except ImportError:
- path = os.path.join(os.getenv(u'HOME'), u'.openlp', u'data')
- #reg = ConfigHelper.get_registry()
- #path = ConfigHelper.get_config(u'main', 'data path', path)
+ path = AppLocation.get_directory(AppLocation.DataDir)
if not os.path.exists(path):
os.makedirs(path)
return path
@@ -81,17 +70,7 @@ class ConfigHelper(object):
current operating system, and returns an instantiation of that class.
"""
if ConfigHelper.__registry__ is None:
- config_path = u''
- if os.name == u'nt':
- config_path = os.path.join(os.getenv(u'APPDATA'), u'openlp')
- elif os.name == u'mac':
- config_path = os.path.join(os.getenv(u'HOME'), u'Library',
- u'Application Support', u'openlp')
- else:
- try:
- from xdg import BaseDirectory
- config_path = os.path.join(BaseDirectory.xdg_config_home, u'openlp')
- except ImportError:
- config_path = os.path.join(os.getenv(u'HOME'), u'.openlp')
+ config_path = AppLocation.get_directory(AppLocation.ConfigDir)
ConfigHelper.__registry__ = Registry(config_path)
- return ConfigHelper.__registry__
\ No newline at end of file
+ return ConfigHelper.__registry__
+
diff --git a/openlp/migration/display.py b/openlp/migration/display.py
index 9a3f6e44e..52951d31f 100644
--- a/openlp/migration/display.py
+++ b/openlp/migration/display.py
@@ -25,18 +25,18 @@
import logging
+log = logging.getLogger(__name__)
+
class Display():
- global log
- log = logging.getLogger(u'Display Logger')
log.info(u'Display Class loaded')
@staticmethod
def output(string):
- log.debug(string);
- print (string)
+ log.debug(string)
+ #print (string)
@staticmethod
def sub_output(string):
if not string is None:
- log.debug(u' '+string);
- print (u' '+string)
\ No newline at end of file
+ log.debug(u' '+string)
+ #print (u' '+string)
diff --git a/openlp/migration/migratebibles.py b/openlp/migration/migratebibles.py
index 92504e907..f9e10b756 100644
--- a/openlp/migration/migratebibles.py
+++ b/openlp/migration/migratebibles.py
@@ -28,5 +28,5 @@ class MigrateBibles():
self.display = display
def process(self):
- self.display.output(u'Bible process started');
- self.display.output(u'Bible process finished');
\ No newline at end of file
+ self.display.output(u'Bible process started')
+ self.display.output(u'Bible process finished')
\ No newline at end of file
diff --git a/openlp/migration/migratefiles.py b/openlp/migration/migratefiles.py
index 9c38fbb88..f1c9435ab 100644
--- a/openlp/migration/migratefiles.py
+++ b/openlp/migration/migratefiles.py
@@ -30,20 +30,20 @@ class MigrateFiles():
self.display = display
def process(self):
- self.display.output(u'Files process started');
+ self.display.output(u'Files process started')
self._initial_setup()
- self.display.output(u'Files process finished');
+ self.display.output(u'Files process finished')
def _initial_setup(self):
- self.display.output(u'Initial Setup started');
+ self.display.output(u'Initial Setup started')
ConfigHelper.get_data_path()
- self.display.sub_output(u'Config created');
+ self.display.sub_output(u'Config created')
ConfigHelper.get_config(u'bible', u'data path')
- self.display.sub_output(u'Config created');
+ self.display.sub_output(u'Config created')
ConfigHelper.get_config(u'videos', u'data path')
- self.display.sub_output(u'videos created');
+ self.display.sub_output(u'videos created')
ConfigHelper.get_config(u'images', u'data path')
- self.display.sub_output(u'images created');
+ self.display.sub_output(u'images created')
ConfigHelper.get_config(u'presentations', u'data path')
- self.display.sub_output(u'presentations created');
- self.display.output(u'Initial Setup finished');
\ No newline at end of file
+ self.display.sub_output(u'presentations created')
+ self.display.output(u'Initial Setup finished')
\ No newline at end of file
diff --git a/openlp/plugins/alerts/__init__.py b/openlp/plugins/alerts/__init__.py
new file mode 100644
index 000000000..bc50edda3
--- /dev/null
+++ b/openlp/plugins/alerts/__init__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
\ No newline at end of file
diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py
new file mode 100644
index 000000000..90e7946c7
--- /dev/null
+++ b/openlp/plugins/alerts/alertsplugin.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+
+import logging
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import Plugin, build_icon, PluginStatus
+from openlp.plugins.alerts.lib import AlertsManager, DBManager
+from openlp.plugins.alerts.forms import AlertsTab, AlertForm, AlertEditForm
+
+log = logging.getLogger(__name__)
+
+class alertsPlugin(Plugin):
+ log.info(u'Alerts Plugin loaded')
+
+ def __init__(self, plugin_helpers):
+ Plugin.__init__(self, u'Alerts', u'1.9.1', plugin_helpers)
+ self.weight = -3
+ self.icon = build_icon(u':/media/media_image.png')
+ self.alertsmanager = AlertsManager(self)
+ self.manager = DBManager(self.config)
+ self.alertForm = AlertForm(self.manager, self)
+ self.alertEditForm = AlertEditForm(self.manager, self)
+ self.status = PluginStatus.Active
+
+ def get_settings_tab(self):
+ self.alertsTab = AlertsTab(self)
+ return self.alertsTab
+
+ def add_tools_menu_item(self, tools_menu):
+ """
+ Give the alerts plugin the opportunity to add items to the
+ **Tools** menu.
+
+ ``tools_menu``
+ The actual **Tools** menu item, so that your actions can
+ use it as their parent.
+ """
+ log.info(u'add tools menu')
+ self.toolsAlertItem = QtGui.QAction(tools_menu)
+ AlertIcon = build_icon(u':/tools/tools_alert.png')
+ self.toolsAlertItem.setIcon(AlertIcon)
+ self.toolsAlertItem.setObjectName(u'toolsAlertItem')
+ self.toolsAlertItem.setText(self.trUtf8('&Alert'))
+ self.toolsAlertItem.setStatusTip(self.trUtf8('Show an alert message'))
+ self.toolsAlertItem.setShortcut(u'F7')
+ self.service_manager.parent.ToolsMenu.addAction(self.toolsAlertItem)
+ QtCore.QObject.connect(self.toolsAlertItem,
+ QtCore.SIGNAL(u'triggered()'), self.onAlertsTrigger)
+ self.toolsAlertItem.setVisible(False)
+
+ def initialise(self):
+ log.info(u'Alerts Initialising')
+ Plugin.initialise(self)
+ self.toolsAlertItem.setVisible(True)
+
+ def finalise(self):
+ log.info(u'Plugin Finalise')
+ self.toolsAlertItem.setVisible(False)
+ #stop any events being processed
+
+ def togglealertsState(self):
+ self.alertsActive = not self.alertsActive
+ self.config.set_config(u'active', self.alertsActive)
+
+ def onAlertsTrigger(self):
+ self.alertForm.loadList()
+ self.alertForm.exec_()
+
+ def onAlertsEdit(self):
+ self.alertEditForm.loadList()
+ self.alertEditForm.exec_()
+
+ def about(self):
+ about_text = self.trUtf8('Alerts Plugin
This plugin '
+ 'controls the displaying of alerts on the presentations screen')
+ return about_text
diff --git a/openlp/plugins/alerts/forms/__init__.py b/openlp/plugins/alerts/forms/__init__.py
new file mode 100644
index 000000000..14c30d73b
--- /dev/null
+++ b/openlp/plugins/alerts/forms/__init__.py
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from alertstab import AlertsTab
+from alertform import AlertForm
+from alerteditform import AlertEditForm
diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py
new file mode 100644
index 000000000..53fc1fff5
--- /dev/null
+++ b/openlp/plugins/alerts/forms/alertdialog.py
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'alertform.ui'
+#
+# Created: Sat Feb 13 08:19:51 2010
+# by: PyQt4 UI code generator 4.6.2
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore, QtGui
+
+class Ui_AlertDialog(object):
+ def setupUi(self, AlertForm):
+ AlertForm.setObjectName(u'AlertDialog')
+ AlertForm.resize(430, 320)
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(u':/icon/openlp.org-icon-32.bmp'), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ AlertForm.setWindowIcon(icon)
+ self.AlertFormLayout = QtGui.QVBoxLayout(AlertForm)
+ self.AlertFormLayout.setSpacing(8)
+ self.AlertFormLayout.setMargin(8)
+ self.AlertFormLayout.setObjectName(u'AlertFormLayout')
+ self.AlertEntryWidget = QtGui.QWidget(AlertForm)
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.AlertEntryWidget.sizePolicy().hasHeightForWidth())
+ self.AlertEntryWidget.setSizePolicy(sizePolicy)
+ self.AlertEntryWidget.setObjectName(u'AlertEntryWidget')
+ self.verticalLayout_2 = QtGui.QVBoxLayout(self.AlertEntryWidget)
+ self.verticalLayout_2.setObjectName(u'verticalLayout_2')
+ self.verticalLayout = QtGui.QVBoxLayout()
+ self.verticalLayout.setObjectName(u'verticalLayout')
+ self.AlertEntryLabel = QtGui.QLabel(self.AlertEntryWidget)
+ sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.AlertEntryLabel.sizePolicy().hasHeightForWidth())
+ self.AlertEntryLabel.setSizePolicy(sizePolicy)
+ self.AlertEntryLabel.setObjectName(u'AlertEntryLabel')
+ self.verticalLayout.addWidget(self.AlertEntryLabel)
+ self.AlertEntryEditItem = QtGui.QLineEdit(self.AlertEntryWidget)
+ self.AlertEntryEditItem.setObjectName(u'AlertEntryEditItem')
+ self.verticalLayout.addWidget(self.AlertEntryEditItem)
+ self.AlertListWidget = QtGui.QListWidget(self.AlertEntryWidget)
+ self.AlertListWidget.setAlternatingRowColors(True)
+ self.AlertListWidget.setObjectName(u'AlertListWidget')
+ self.verticalLayout.addWidget(self.AlertListWidget)
+ self.verticalLayout_2.addLayout(self.verticalLayout)
+ self.horizontalLayout = QtGui.QHBoxLayout()
+ self.horizontalLayout.setObjectName(u'horizontalLayout')
+ spacerItem = QtGui.QSpacerItem(181, 38, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.DisplayButton = QtGui.QPushButton(self.AlertEntryWidget)
+ self.DisplayButton.setObjectName(u'DisplayButton')
+ self.horizontalLayout.addWidget(self.DisplayButton)
+ self.CancelButton = QtGui.QPushButton(self.AlertEntryWidget)
+ self.CancelButton.setObjectName(u'CancelButton')
+ self.horizontalLayout.addWidget(self.CancelButton)
+ self.verticalLayout_2.addLayout(self.horizontalLayout)
+ self.AlertFormLayout.addWidget(self.AlertEntryWidget)
+
+ self.retranslateUi(AlertForm)
+ QtCore.QObject.connect(self.CancelButton, QtCore.SIGNAL(u'clicked()'), self.close)
+ QtCore.QMetaObject.connectSlotsByName(AlertForm)
+
+ def retranslateUi(self, AlertForm):
+ AlertForm.setWindowTitle(self.trUtf8('Alert Message'))
+ self.AlertEntryLabel.setText(self.trUtf8('Alert Text:'))
+ self.DisplayButton.setText(self.trUtf8('Display'))
+ self.CancelButton.setText(self.trUtf8('Cancel'))
diff --git a/openlp/plugins/alerts/forms/alerteditdialog.py b/openlp/plugins/alerts/forms/alerteditdialog.py
new file mode 100644
index 000000000..6cf4769ef
--- /dev/null
+++ b/openlp/plugins/alerts/forms/alerteditdialog.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'alerteditdialog.ui'
+#
+# Created: Sun Feb 14 16:45:10 2010
+# by: PyQt4 UI code generator 4.6.2
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt4 import QtCore, QtGui
+
+class Ui_AlertEditDialog(object):
+ def setupUi(self, AlertEditDialog):
+ AlertEditDialog.setObjectName(u'AlertEditDialog')
+ AlertEditDialog.resize(400, 300)
+ self.buttonBox = QtGui.QDialogButtonBox(AlertEditDialog)
+ self.buttonBox.setGeometry(QtCore.QRect(220, 270, 173, 27))
+ self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel)
+ self.buttonBox.setObjectName(u'buttonBox')
+ self.layoutWidget = QtGui.QWidget(AlertEditDialog)
+ self.layoutWidget.setGeometry(QtCore.QRect(20, 10, 361, 251))
+ self.layoutWidget.setObjectName(u'layoutWidget')
+ self.verticalLayout_2 = QtGui.QVBoxLayout(self.layoutWidget)
+ self.verticalLayout_2.setObjectName(u'verticalLayout_2')
+ self.horizontalLayout_2 = QtGui.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName(u'horizontalLayout_2')
+ self.AlertLineEdit = QtGui.QLineEdit(self.layoutWidget)
+ self.AlertLineEdit.setObjectName(u'AlertLineEdit')
+ self.horizontalLayout_2.addWidget(self.AlertLineEdit)
+ self.verticalLayout_2.addLayout(self.horizontalLayout_2)
+ self.horizontalLayout = QtGui.QHBoxLayout()
+ self.horizontalLayout.setObjectName(u'horizontalLayout')
+ self.AlertListWidget = QtGui.QListWidget(self.layoutWidget)
+ self.AlertListWidget.setAlternatingRowColors(True)
+ self.AlertListWidget.setObjectName(u'AlertListWidget')
+ self.horizontalLayout.addWidget(self.AlertListWidget)
+ self.verticalLayout = QtGui.QVBoxLayout()
+ self.verticalLayout.setObjectName(u'verticalLayout')
+ self.SaveButton = QtGui.QPushButton(self.layoutWidget)
+ self.SaveButton.setObjectName(u'SaveButton')
+ self.verticalLayout.addWidget(self.SaveButton)
+ self.ClearButton = QtGui.QPushButton(self.layoutWidget)
+ self.ClearButton.setObjectName(u'ClearButton')
+ self.verticalLayout.addWidget(self.ClearButton)
+ self.AddButton = QtGui.QPushButton(self.layoutWidget)
+ self.AddButton.setObjectName(u'AddButton')
+ self.verticalLayout.addWidget(self.AddButton)
+ self.EditButton = QtGui.QPushButton(self.layoutWidget)
+ self.EditButton.setObjectName(u'EditButton')
+ self.verticalLayout.addWidget(self.EditButton)
+ self.DeleteButton = QtGui.QPushButton(self.layoutWidget)
+ self.DeleteButton.setObjectName(u'DeleteButton')
+ self.verticalLayout.addWidget(self.DeleteButton)
+ self.horizontalLayout.addLayout(self.verticalLayout)
+ self.verticalLayout_2.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(AlertEditDialog)
+ QtCore.QMetaObject.connectSlotsByName(AlertEditDialog)
+
+ def retranslateUi(self, AlertEditDialog):
+ AlertEditDialog.setWindowTitle(self.trUtf8('Maintain Alerts'))
+ self.SaveButton.setText(self.trUtf8('Save'))
+ self.ClearButton.setText(self.trUtf8('Clear'))
+ self.AddButton.setText(self.trUtf8('Add'))
+ self.EditButton.setText(self.trUtf8('Edit'))
+ self.DeleteButton.setText(self.trUtf8('Delete'))
+
diff --git a/openlp/plugins/alerts/forms/alerteditform.py b/openlp/plugins/alerts/forms/alerteditform.py
new file mode 100644
index 000000000..62c129508
--- /dev/null
+++ b/openlp/plugins/alerts/forms/alerteditform.py
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtGui, QtCore
+from openlp.plugins.alerts.lib.models import AlertItem
+
+from alerteditdialog import Ui_AlertEditDialog
+
+class AlertEditForm(QtGui.QDialog, Ui_AlertEditDialog):
+ """
+ Class documentation goes here.
+ """
+ def __init__(self, manager, parent):
+ """
+ Constructor
+ """
+ self.manager = manager
+ self.parent = parent
+ QtGui.QDialog.__init__(self, None)
+ self.setupUi(self)
+ QtCore.QObject.connect(self.DeleteButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onDeleteClick)
+ QtCore.QObject.connect(self.ClearButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onClearClick)
+ QtCore.QObject.connect(self.EditButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onEditClick)
+ QtCore.QObject.connect(self.AddButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onAddClick)
+ QtCore.QObject.connect(self.SaveButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onSaveClick)
+ QtCore.QObject.connect(self.buttonBox,
+ QtCore.SIGNAL(u'rejected()'), self.close)
+ QtCore.QObject.connect(self.AlertLineEdit,
+ QtCore.SIGNAL(u'textChanged(const QString&)'),
+ self.onTextChanged)
+ QtCore.QObject.connect(self.AlertListWidget,
+ QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
+ self.onItemSelected)
+ QtCore.QObject.connect(self.AlertListWidget,
+ QtCore.SIGNAL(u'clicked(QModelIndex)'),
+ self.onItemSelected)
+
+ def loadList(self):
+ self.AlertListWidget.clear()
+ alerts = self.manager.get_all_alerts()
+ for alert in alerts:
+ item_name = QtGui.QListWidgetItem(alert.text)
+ item_name.setData(
+ QtCore.Qt.UserRole, QtCore.QVariant(alert.id))
+ self.AlertListWidget.addItem(item_name)
+ self.AddButton.setEnabled(True)
+ self.ClearButton.setEnabled(False)
+ self.SaveButton.setEnabled(False)
+ self.EditButton.setEnabled(False)
+ self.DeleteButton.setEnabled(False)
+
+ def onItemSelected(self):
+ if self.AlertLineEdit.text():
+ QtGui.QMessageBox.information(self,
+ self.trUtf8('Item selected to Edit'),
+ self.trUtf8('Please Save or Clear seletced item'))
+ else:
+ self.EditButton.setEnabled(True)
+ self.DeleteButton.setEnabled(True)
+
+ def onDeleteClick(self):
+ item = self.AlertListWidget.currentItem()
+ if item:
+ item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
+ self.parent.manager.delete_alert(item_id)
+ row = self.AlertListWidget.row(item)
+ self.AlertListWidget.takeItem(row)
+ self.AddButton.setEnabled(True)
+ self.SaveButton.setEnabled(False)
+ self.DeleteButton.setEnabled(False)
+ self.EditButton.setEnabled(False)
+
+ def onEditClick(self):
+ item = self.AlertListWidget.currentItem()
+ if item:
+ self.item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
+ self.AlertLineEdit.setText(unicode(item.text()))
+ self.AddButton.setEnabled(True)
+ self.ClearButton.setEnabled(True)
+ self.SaveButton.setEnabled(True)
+ self.DeleteButton.setEnabled(True)
+ self.EditButton.setEnabled(False)
+
+ def onClearClick(self):
+ self.AlertLineEdit.setText(u'')
+ self.AddButton.setEnabled(False)
+ self.ClearButton.setEnabled(True)
+ self.SaveButton.setEnabled(False)
+ self.DeleteButton.setEnabled(False)
+ self.EditButton.setEnabled(False)
+
+ def onAddClick(self):
+ if len(self.AlertLineEdit.text()) == 0:
+ QtGui.QMessageBox.information(self,
+ self.trUtf8('Item selected to Add'),
+ self.trUtf8('Missing data'))
+ else:
+ alert = AlertItem()
+ alert.text = unicode(self.AlertLineEdit.text())
+ self.manager.save_alert(alert)
+ self.onClearClick()
+ self.loadList()
+
+ def onSaveClick(self):
+ alert = self.manager.get_alert(self.item_id)
+ alert.text = unicode(self.AlertLineEdit.text())
+ self.manager.save_alert(alert)
+ self.onClearClick()
+ self.loadList()
+
+ def onTextChanged(self):
+ self.AddButton.setEnabled(True)
+
+ def onDoubleClick(self):
+ """
+ List item has been double clicked to display it
+ """
+ items = self.AlertListWidget.selectedIndexes()
+ for item in items:
+ bitem = self.AlertListWidget.item(item.row())
+ self.triggerAlert(bitem.text())
+
+ def onSingleClick(self):
+ """
+ List item has been single clicked to add it to
+ the edit field so it can be changed.
+ """
+ items = self.AlertListWidget.selectedIndexes()
+ for item in items:
+ bitem = self.AlertListWidget.item(item.row())
+ self.AlertEntryEditItem.setText(bitem.text())
+
+ def triggerAlert(self, text):
+ self.parent.alertsmanager.displayAlert(text)
diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py
new file mode 100644
index 000000000..2d7dd1c21
--- /dev/null
+++ b/openlp/plugins/alerts/forms/alertform.py
@@ -0,0 +1,100 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from PyQt4 import QtGui, QtCore
+
+from openlp.plugins.alerts.lib.models import AlertItem
+
+from alertdialog import Ui_AlertDialog
+
+class AlertForm(QtGui.QDialog, Ui_AlertDialog):
+ """
+ Class documentation goes here.
+ """
+ def __init__(self, manager, parent):
+ """
+ Constructor
+ """
+ self.manager = manager
+ self.parent = parent
+ self.history_required = True
+ QtGui.QDialog.__init__(self, None)
+ self.setupUi(self)
+ QtCore.QObject.connect(self.DisplayButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onDisplayClicked)
+ QtCore.QObject.connect(self.AlertEntryEditItem,
+ QtCore.SIGNAL(u'textChanged(const QString&)'),
+ self.onTextChanged)
+ QtCore.QObject.connect(self.AlertListWidget,
+ QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
+ self.onDoubleClick)
+ QtCore.QObject.connect(self.AlertListWidget,
+ QtCore.SIGNAL(u'clicked(QModelIndex)'),
+ self.onSingleClick)
+
+ def loadList(self):
+ self.AlertListWidget.clear()
+ alerts = self.manager.get_all_alerts()
+ for alert in alerts:
+ item_name = QtGui.QListWidgetItem(alert.text)
+ self.AlertListWidget.addItem(item_name)
+
+ def onDisplayClicked(self):
+ self.triggerAlert(unicode(self.AlertEntryEditItem.text()))
+ if self.parent.alertsTab.save_history and self.history_required:
+ alert = AlertItem()
+ alert.text = unicode(self.AlertEntryEditItem.text())
+ self.manager.save_alert(alert)
+ self.history_required = False
+ self.loadList()
+
+ def onTextChanged(self):
+ #Data has changed by editing it so potential storage
+ self.history_required = True
+
+ def onDoubleClick(self):
+ """
+ List item has been double clicked to display it
+ """
+ items = self.AlertListWidget.selectedIndexes()
+ for item in items:
+ bitem = self.AlertListWidget.item(item.row())
+ self.triggerAlert(bitem.text())
+ self.history_required = False
+
+ def onSingleClick(self):
+ """
+ List item has been single clicked to add it to
+ the edit field so it can be changed.
+ """
+ items = self.AlertListWidget.selectedIndexes()
+ for item in items:
+ bitem = self.AlertListWidget.item(item.row())
+ self.AlertEntryEditItem.setText(bitem.text())
+ self.history_required = False
+
+ def triggerAlert(self, text):
+ self.parent.alertsmanager.displayAlert(text)
diff --git a/openlp/core/ui/alertstab.py b/openlp/plugins/alerts/forms/alertstab.py
similarity index 62%
rename from openlp/core/ui/alertstab.py
rename to openlp/plugins/alerts/forms/alertstab.py
index d2e38e048..c842c2e20 100644
--- a/openlp/core/ui/alertstab.py
+++ b/openlp/plugins/alerts/forms/alertstab.py
@@ -25,16 +25,15 @@
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import SettingsTab
+from openlp.core.lib import SettingsTab, str_to_bool
class AlertsTab(SettingsTab):
"""
AlertsTab is the alerts settings tab in the settings dialog.
"""
- def __init__(self):
- SettingsTab.__init__(self, u'Alerts')
- self.font_color = '#ffffff'
- self.bg_color = '#660000'
+ def __init__(self, parent, section=None):
+ self.parent = parent
+ SettingsTab.__init__(self, parent.name, section)
def setupUi(self):
self.setObjectName(u'AlertsTab')
@@ -83,6 +82,22 @@ class AlertsTab(SettingsTab):
self.BackgroundColorButton.setObjectName(u'BackgroundColorButton')
self.ColorLayout.addWidget(self.BackgroundColorButton)
self.FontLayout.addWidget(self.ColorWidget)
+ self.FontSizeWidget = QtGui.QWidget(self.FontGroupBox)
+ self.FontSizeWidget.setObjectName(u'FontSizeWidget')
+ self.FontSizeLayout = QtGui.QHBoxLayout(self.FontSizeWidget)
+ self.FontSizeLayout.setSpacing(8)
+ self.FontSizeLayout.setMargin(0)
+ self.FontSizeLayout.setObjectName(u'FontSizeLayout')
+ self.FontSizeLabel = QtGui.QLabel(self.FontSizeWidget)
+ self.FontSizeLabel.setObjectName(u'FontSizeLabel')
+ self.FontSizeLayout.addWidget(self.FontSizeLabel)
+ self.FontSizeSpinBox = QtGui.QSpinBox(self.FontSizeWidget)
+ self.FontSizeSpinBox.setObjectName(u'FontSizeSpinBox')
+ self.FontSizeLayout.addWidget(self.FontSizeSpinBox)
+ self.FontSizeSpacer = QtGui.QSpacerItem(147, 20,
+ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.FontSizeLayout.addItem(self.FontSizeSpacer)
+ self.FontLayout.addWidget(self.FontSizeWidget)
self.TimeoutWidget = QtGui.QWidget(self.FontGroupBox)
self.TimeoutWidget.setObjectName(u'TimeoutWidget')
self.TimeoutLayout = QtGui.QHBoxLayout(self.TimeoutWidget)
@@ -100,6 +115,56 @@ class AlertsTab(SettingsTab):
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.TimeoutLayout.addItem(self.TimeoutSpacer)
self.FontLayout.addWidget(self.TimeoutWidget)
+ self.LocationWidget = QtGui.QWidget(self.FontGroupBox)
+ self.LocationWidget.setObjectName(u'LocationWidget')
+ self.LocationLayout = QtGui.QHBoxLayout(self.LocationWidget)
+ self.LocationLayout.setSpacing(8)
+ self.LocationLayout.setMargin(0)
+ self.LocationLayout.setObjectName(u'LocationLayout')
+ self.LocationLabel = QtGui.QLabel(self.LocationWidget)
+ self.LocationLabel.setObjectName(u'LocationLabel')
+ self.LocationLayout.addWidget(self.LocationLabel)
+ self.LocationComboBox = QtGui.QComboBox(self.LocationWidget)
+ self.LocationComboBox.addItem(QtCore.QString())
+ self.LocationComboBox.addItem(QtCore.QString())
+ self.LocationComboBox.setObjectName(u'LocationComboBox')
+ self.LocationLayout.addWidget(self.LocationComboBox)
+ self.LocationSpacer = QtGui.QSpacerItem(147, 20,
+ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.LocationLayout.addItem(self.LocationSpacer)
+ self.FontLayout.addWidget(self.LocationWidget)
+ self.HistoryWidget = QtGui.QWidget(self.FontGroupBox)
+ self.HistoryWidget.setObjectName(u'HistoryWidget')
+ self.HistoryLayout = QtGui.QHBoxLayout(self.HistoryWidget)
+ self.HistoryLayout.setSpacing(8)
+ self.HistoryLayout.setMargin(0)
+ self.HistoryLayout.setObjectName(u'HistoryLayout')
+ self.HistoryLabel = QtGui.QLabel(self.HistoryWidget)
+ self.HistoryLabel.setObjectName(u'HistoryLabel')
+ self.HistoryLayout.addWidget(self.HistoryLabel)
+ self.HistoryCheckBox = QtGui.QCheckBox(self.HistoryWidget)
+ self.HistoryCheckBox.setObjectName(u'HistoryCheckBox')
+ self.HistoryLayout.addWidget(self.HistoryCheckBox)
+ self.HistorySpacer = QtGui.QSpacerItem(147, 20,
+ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.HistoryLayout.addItem(self.HistorySpacer)
+ self.FontLayout.addWidget(self.HistoryWidget)
+ self.HistoryEditWidget = QtGui.QWidget(self.FontGroupBox)
+ self.HistoryEditWidget.setObjectName(u'HistoryEditWidget')
+ self.HistoryEditLayout = QtGui.QHBoxLayout(self.HistoryEditWidget)
+ self.HistoryEditLayout.setSpacing(8)
+ self.HistoryEditLayout.setMargin(0)
+ self.HistoryEditLayout.setObjectName(u'HistoryEditLayout')
+ self.HistoryEditLabel = QtGui.QLabel(self.HistoryEditWidget)
+ self.HistoryEditLabel.setObjectName(u'HistoryEditLabel')
+ self.HistoryEditLayout.addWidget(self.HistoryEditLabel)
+ self.HistoryEditPushButton = QtGui.QPushButton(self.HistoryEditWidget)
+ self.HistoryEditPushButton.setObjectName(u'HistoryEditPushButton')
+ self.HistoryEditLayout.addWidget(self.HistoryEditPushButton)
+ self.HistoryEditSpacer = QtGui.QSpacerItem(147, 20,
+ QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+ self.HistoryEditLayout.addItem(self.HistoryEditSpacer)
+ self.FontLayout.addWidget(self.HistoryEditWidget)
self.SlideLeftLayout.addWidget(self.FontGroupBox)
self.SlideLeftSpacer = QtGui.QSpacerItem(20, 94,
QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
@@ -125,7 +190,7 @@ class AlertsTab(SettingsTab):
self.PreviewLayout.setMargin(8)
self.PreviewLayout.setObjectName(u'PreviewLayout')
self.FontPreview = QtGui.QLineEdit(self.PreviewGroupBox)
- self.FontPreview.setMinimumSize(QtCore.QSize(280, 100))
+ self.FontPreview.setFixedSize(QtCore.QSize(350, 100))
self.FontPreview.setReadOnly(True)
self.FontPreview.setFocusPolicy(QtCore.Qt.NoFocus)
self.FontPreview.setAlignment(
@@ -138,24 +203,40 @@ class AlertsTab(SettingsTab):
self.SlideRightLayout.addItem(self.SlideRightSpacer)
self.AlertsLayout.addWidget(self.AlertRightColumn)
# Signals and slots
+ QtCore.QObject.connect(self.HistoryCheckBox,
+ QtCore.SIGNAL(u'stateChanged(int)'),
+ self.onHistoryCheckBoxChanged)
QtCore.QObject.connect(self.BackgroundColorButton,
QtCore.SIGNAL(u'pressed()'), self.onBackgroundColorButtonClicked)
QtCore.QObject.connect(self.FontColorButton,
QtCore.SIGNAL(u'pressed()'), self.onFontColorButtonClicked)
+ QtCore.QObject.connect(self.HistoryEditPushButton,
+ QtCore.SIGNAL(u'pressed()'), self.onHistoryEditButtonClicked)
QtCore.QObject.connect(self.FontComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onFontComboBoxClicked)
+ QtCore.QObject.connect(self.LocationComboBox,
+ QtCore.SIGNAL(u'activated(int)'), self.onLocationComboBoxClicked)
QtCore.QObject.connect(self.TimeoutSpinBox,
QtCore.SIGNAL(u'valueChanged(int)'), self.onTimeoutSpinBoxChanged)
+ QtCore.QObject.connect(self.FontSizeSpinBox,
+ QtCore.SIGNAL(u'valueChanged(int)'), self.onFontSizeSpinBoxChanged)
def retranslateUi(self):
self.FontGroupBox.setTitle(self.trUtf8('Font'))
self.FontLabel.setText(self.trUtf8('Font Name:'))
self.FontColorLabel.setText(self.trUtf8('Font Color:'))
self.BackgroundColorLabel.setText(self.trUtf8('Background Color:'))
+ self.FontSizeLabel.setText(self.trUtf8('Font Size:'))
+ self.FontSizeSpinBox.setSuffix(self.trUtf8('pt'))
self.TimeoutLabel.setText(self.trUtf8('Alert timeout:'))
self.TimeoutSpinBox.setSuffix(self.trUtf8('s'))
+ self.LocationLabel.setText(self.trUtf8('Location:'))
+ self.HistoryLabel.setText(self.trUtf8('Keep History:'))
+ self.HistoryEditLabel.setText(self.trUtf8('Edit History:'))
self.PreviewGroupBox.setTitle(self.trUtf8('Preview'))
- self.FontPreview.setText(self.trUtf8('openlp.org 2.0 rocks!'))
+ self.FontPreview.setText(self.trUtf8('openlp.org'))
+ self.LocationComboBox.setItemText(0, self.trUtf8('Top'))
+ self.LocationComboBox.setItemText(1, self.trUtf8('Bottom'))
def onBackgroundColorButtonClicked(self):
self.bg_color = QtGui.QColorDialog.getColor(
@@ -167,6 +248,15 @@ class AlertsTab(SettingsTab):
def onFontComboBoxClicked(self):
self.updateDisplay()
+ def onLocationComboBoxClicked(self, location):
+ self.location = location
+
+ def onHistoryCheckBoxChanged(self, check_state):
+ self.save_history = False
+ # we have a set value convert to True/False
+ if check_state == QtCore.Qt.Checked:
+ self.save_history = True
+
def onFontColorButtonClicked(self):
self.font_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.font_color), self).name()
@@ -177,19 +267,33 @@ class AlertsTab(SettingsTab):
def onTimeoutSpinBoxChanged(self):
self.timeout = self.TimeoutSpinBox.value()
+ def onFontSizeSpinBoxChanged(self):
+ self.font_size = self.FontSizeSpinBox.value()
+ self.updateDisplay()
+
+ def onHistoryEditButtonClicked(self):
+ self.parent.onAlertsEdit()
+
def load(self):
self.timeout = int(self.config.get_config(u'timeout', 5))
self.font_color = unicode(
self.config.get_config(u'font color', u'#ffffff'))
+ self.font_size = int(self.config.get_config(u'font size', 40))
self.bg_color = unicode(
self.config.get_config(u'background color', u'#660000'))
self.font_face = unicode(
self.config.get_config(u'font face', QtGui.QFont().family()))
+ self.location = int(self.config.get_config(u'location', 0))
+ self.save_history = str_to_bool(
+ self.config.get_config(u'save history', u'False'))
+ self.FontSizeSpinBox.setValue(self.font_size)
self.TimeoutSpinBox.setValue(self.timeout)
self.FontColorButton.setStyleSheet(
u'background-color: %s' % self.font_color)
self.BackgroundColorButton.setStyleSheet(
u'background-color: %s' % self.bg_color)
+ self.LocationComboBox.setCurrentIndex(self.location)
+ self.HistoryCheckBox.setChecked(self.save_history)
font = QtGui.QFont()
font.setFamily(self.font_face)
self.FontComboBox.setCurrentFont(font)
@@ -199,14 +303,18 @@ class AlertsTab(SettingsTab):
self.font_face = self.FontComboBox.currentFont().family()
self.config.set_config(u'background color', unicode(self.bg_color))
self.config.set_config(u'font color', unicode(self.font_color))
+ self.config.set_config(u'font size', unicode(self.font_size))
self.config.set_config(u'font face', unicode(self.font_face))
self.config.set_config(u'timeout', unicode(self.timeout))
+ self.config.set_config(u'location',
+ unicode(self.LocationComboBox.currentIndex()))
+ self.config.set_config(u'save history', unicode(self.save_history))
def updateDisplay(self):
font = QtGui.QFont()
font.setFamily(self.FontComboBox.currentFont().family())
font.setBold(True)
- font.setPointSize(16)
+ font.setPointSize(self.font_size)
self.FontPreview.setFont(font)
self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' % \
- (self.bg_color, self.font_color))
\ No newline at end of file
+ (self.bg_color, self.font_color))
diff --git a/openlp/plugins/alerts/lib/__init__.py b/openlp/plugins/alerts/lib/__init__.py
new file mode 100644
index 000000000..c39574719
--- /dev/null
+++ b/openlp/plugins/alerts/lib/__init__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+from alertsmanager import AlertsManager
+from manager import DBManager
diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py
new file mode 100644
index 000000000..41fc25562
--- /dev/null
+++ b/openlp/plugins/alerts/lib/alertsmanager.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+
+import logging
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import Receiver
+
+log = logging.getLogger(__name__)
+
+class AlertsManager(QtCore.QObject):
+ """
+ AlertsTab is the Alerts settings tab in the settings dialog.
+ """
+ log.info(u'Alert Manager loaded')
+
+ def __init__(self, parent):
+ QtCore.QObject.__init__(self)
+ self.parent = parent
+ self.timer_id = 0
+ self.alertList = []
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'flush_alert'), self.generateAlert)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'alert_text'), self.displayAlert)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'screen_changed'), self.screenChanged)
+ QtCore.QObject.connect(Receiver.get_receiver(),
+ QtCore.SIGNAL(u'config_updated'), self.screenChanged)
+
+ def screenChanged(self):
+ log.debug(u'screen changed')
+ self.screen = self.parent.maindisplay.screen
+ self.alertTab = self.parent.alertsTab
+ self.font = QtGui.QFont()
+ self.font.setFamily(self.alertTab.font_face)
+ self.font.setBold(True)
+ self.font.setPointSize(self.alertTab.font_size)
+ self.metrics = QtGui.QFontMetrics(self.font)
+ self.alertHeight = self.metrics.height() + 4
+ if self.alertTab.location == 0:
+ self.alertScreenPosition = 0
+ else:
+ self.alertScreenPosition = self.screen[u'size'].height() - self.alertHeight
+ self.alertHeight = self.screen[u'size'].height() - self.alertScreenPosition
+ self.parent.maindisplay.setAlertSize(self.alertScreenPosition, self.alertHeight)
+
+ def displayAlert(self, text=u''):
+ """
+ Called from the Alert Tab to display an alert
+
+ ``text``
+ display text
+ """
+ log.debug(u'display alert called %s' % text)
+ self.parent.maindisplay.parent.StatusBar.showMessage(u'')
+ self.alertList.append(text)
+ if self.timer_id != 0 or self.parent.maindisplay.mediaLoaded:
+ self.parent.maindisplay.parent.StatusBar.showMessage(\
+ self.trUtf8(u'Alert message created and delayed'))
+ return
+ self.generateAlert()
+
+ def generateAlert(self):
+ log.debug(u'Generate Alert called')
+ if len(self.alertList) == 0:
+ return
+ text = self.alertList.pop(0)
+ alertTab = self.parent.alertsTab
+ alertframe = \
+ QtGui.QPixmap(self.screen[u'size'].width(), self.alertHeight)
+ alertframe.fill(QtCore.Qt.transparent)
+ painter = QtGui.QPainter(alertframe)
+ painter.fillRect(alertframe.rect(), QtCore.Qt.transparent)
+ painter.setRenderHint(QtGui.QPainter.Antialiasing)
+ painter.fillRect(
+ QtCore.QRect(
+ 0, 0, alertframe.rect().width(),
+ alertframe.rect().height()),
+ QtGui.QColor(self.alertTab.bg_color))
+ painter.setFont(self.font)
+ painter.setPen(QtGui.QColor(self.alertTab.font_color))
+ x, y = (0, 2)
+ painter.drawText(
+ x, y + self.metrics.height() - self.metrics.descent() - 1, text)
+ painter.end()
+ self.parent.maindisplay.addAlertImage(alertframe)
+ # check to see if we have a timer running
+ if self.timer_id == 0:
+ self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
+
+ def timerEvent(self, event):
+ if event.timerId() == self.timer_id:
+ self.parent.maindisplay.addAlertImage(None, True)
+ self.killTimer(self.timer_id)
+ self.timer_id = 0
+ self.generateAlert()
diff --git a/openlp/plugins/alerts/lib/classes.py b/openlp/plugins/alerts/lib/classes.py
new file mode 100644
index 000000000..eec21300c
--- /dev/null
+++ b/openlp/plugins/alerts/lib/classes.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+class BaseModel(object):
+ """
+ BaseModel provides a base object with a set of generic functions
+ """
+
+ @classmethod
+ def populate(cls, **kwargs):
+ """
+ Creates an instance of a class and populates it, returning the instance
+ """
+ me = cls()
+ keys = kwargs.keys()
+ for key in keys:
+ me.__setattr__(key, kwargs[key])
+ return me
+
+class AlertItem(BaseModel):
+ """
+ Custom Slide model
+ """
+ pass
diff --git a/openlp/plugins/alerts/lib/manager.py b/openlp/plugins/alerts/lib/manager.py
new file mode 100644
index 000000000..a3ed1ee7e
--- /dev/null
+++ b/openlp/plugins/alerts/lib/manager.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+
+import logging
+
+from openlp.plugins.alerts.lib.models import init_models, metadata, AlertItem
+
+log = logging.getLogger(__name__)
+
+class DBManager():
+ """
+ The Song Manager provides a central location for all database code. This
+ class takes care of connecting to the database and running all the queries.
+ """
+ log.info(u'Alerts DB loaded')
+
+ def __init__(self, config):
+ """
+ Creates the connection to the database, and creates the tables if they
+ don't exist.
+ """
+ self.config = config
+ log.debug(u'Alerts Initialising')
+ self.db_url = u''
+ db_type = self.config.get_config(u'db type', u'sqlite')
+ if db_type == u'sqlite':
+ self.db_url = u'sqlite:///%s/alerts.sqlite' % \
+ self.config.get_data_path()
+ else:
+ self.db_url = u'%s://%s:%s@%s/%s' % \
+ (db_type, self.config.get_config(u'db username'),
+ self.config.get_config(u'db password'),
+ self.config.get_config(u'db hostname'),
+ self.config.get_config(u'db database'))
+ self.session = init_models(self.db_url)
+ metadata.create_all(checkfirst=True)
+
+ log.debug(u'Alerts Initialised')
+
+ def get_all_alerts(self):
+ """
+ Returns the details of a Alert Show
+ """
+ return self.session.query(AlertItem).order_by(AlertItem.text).all()
+
+ def save_alert(self, AlertItem):
+ """
+ Saves a Alert show to the database
+ """
+ log.debug(u'Alert added')
+ try:
+ self.session.add(AlertItem)
+ self.session.commit()
+ log.debug(u'Alert saved')
+ return True
+ except:
+ self.session.rollback()
+ log.exception(u'Alert save failed')
+ return False
+
+ def get_alert(self, id=None):
+ """
+ Returns the details of a Alert
+ """
+ if id is None:
+ return AlertItem()
+ else:
+ return self.session.query(AlertItem).get(id)
+
+ def delete_alert(self, id):
+ """
+ Delete a Alert show
+ """
+ if id != 0:
+ AlertItem = self.get_alert(id)
+ try:
+ self.session.delete(AlertItem)
+ self.session.commit()
+ return True
+ except:
+ self.session.rollback()
+ log.exception(u'Alert deleton failed')
+ return False
+ else:
+ return True
diff --git a/openlp/plugins/alerts/lib/meta.py b/openlp/plugins/alerts/lib/meta.py
new file mode 100644
index 000000000..38b0f7206
--- /dev/null
+++ b/openlp/plugins/alerts/lib/meta.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from sqlalchemy import MetaData
+
+__all__ = ['session', 'metadata', 'engine']
+
+# SQLAlchemy database engine. Updated by model.init_model()
+engine = None
+
+# SQLAlchemy session manager. Updated by model.init_model()
+session = None
+
+# Global metadata. If you have multiple databases with overlapping table
+# names, you'll need a metadata for each database
+metadata = MetaData()
\ No newline at end of file
diff --git a/openlp/plugins/alerts/lib/models.py b/openlp/plugins/alerts/lib/models.py
new file mode 100644
index 000000000..4f556cd23
--- /dev/null
+++ b/openlp/plugins/alerts/lib/models.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from sqlalchemy import create_engine
+from sqlalchemy.orm import scoped_session, sessionmaker, mapper
+
+from openlp.plugins.alerts.lib.meta import metadata
+from openlp.plugins.alerts.lib.tables import *
+from openlp.plugins.alerts.lib.classes import *
+
+def init_models(url):
+ engine = create_engine(url)
+ metadata.bind = engine
+ session = scoped_session(sessionmaker(autoflush=True, autocommit=False,
+ bind=engine))
+ mapper(AlertItem, alerts_table)
+ return session
diff --git a/openlp/plugins/alerts/lib/tables.py b/openlp/plugins/alerts/lib/tables.py
new file mode 100644
index 000000000..0a731fb13
--- /dev/null
+++ b/openlp/plugins/alerts/lib/tables.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
+# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
+# Carsten Tinggaard #
+# --------------------------------------------------------------------------- #
+# 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 #
+###############################################################################
+
+from sqlalchemy import Column, Table, types
+
+from openlp.plugins.alerts.lib.meta import metadata
+
+# Definition of the "alerts" table
+alerts_table = Table(u'alerts', metadata,
+ Column(u'id', types.Integer(), primary_key=True),
+ Column(u'text', types.UnicodeText, nullable=False))
diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py
index 912a02212..bd65b6622 100644
--- a/openlp/plugins/bibles/bibleplugin.py
+++ b/openlp/plugins/bibles/bibleplugin.py
@@ -27,25 +27,26 @@ import logging
from PyQt4 import QtCore, QtGui
-from openlp.core.lib import Plugin, build_icon
+from openlp.core.lib import Plugin, build_icon, PluginStatus
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
+log = logging.getLogger(__name__)
+
class BiblePlugin(Plugin):
- global log
- log = logging.getLogger(u'BiblePlugin')
log.info(u'Bible Plugin loaded')
def __init__(self, plugin_helpers):
- Plugin.__init__(self, u'Bibles', u'1.9.0', plugin_helpers)
+ Plugin.__init__(self, u'Bibles', u'1.9.1', plugin_helpers)
self.weight = -9
self.icon = build_icon(u':/media/media_bible.png')
#Register the bible Manager
- self.biblemanager = None
+ self.status = PluginStatus.Active
+ self.manager = None
def initialise(self):
log.info(u'bibles Initialising')
- if self.biblemanager is None:
- self.biblemanager = BibleManager(self.config)
+ if self.manager is None:
+ self.manager = BibleManager(self, self.config)
Plugin.initialise(self)
self.insert_toolbox_item()
self.ImportBibleItem.setVisible(True)
@@ -90,4 +91,10 @@ class BiblePlugin(Plugin):
about_text = self.trUtf8('Bible Plugin
This '
'plugin allows bible verses from different sources to be '
'displayed on the screen during the service.')
- return about_text
\ No newline at end of file
+ return about_text
+
+
+ def can_delete_theme(self, theme):
+ if self.settings_tab.bible_theme == theme:
+ return False
+ return True
diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py
index 1f655a52d..59e38e39a 100644
--- a/openlp/plugins/bibles/forms/bibleimportwizard.py
+++ b/openlp/plugins/bibles/forms/bibleimportwizard.py
@@ -91,15 +91,6 @@ class Ui_BibleImportWizard(object):
self.OsisLayout.setMargin(0)
self.OsisLayout.setSpacing(8)
self.OsisLayout.setObjectName(u'OsisLayout')
- self.OsisBibleNameLabel = QtGui.QLabel(self.OsisPage)
- self.OsisBibleNameLabel.setIndent(0)
- self.OsisBibleNameLabel.setObjectName(u'OsisBibleNameLabel')
- self.OsisLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
- self.OsisBibleNameLabel)
- self.OsisBibleNameEdit = QtGui.QLineEdit(self.OsisPage)
- self.OsisBibleNameEdit.setObjectName(u'OsisBibleNameEdit')
- self.OsisLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
- self.OsisBibleNameEdit)
self.OsisLocationLabel = QtGui.QLabel(self.OsisPage)
self.OsisLocationLabel.setObjectName(u'OsisLocationLabel')
self.OsisLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
@@ -302,13 +293,11 @@ class Ui_BibleImportWizard(object):
self.ImportProgressLabel.setObjectName(u'ImportProgressLabel')
self.ImportLayout.addWidget(self.ImportProgressLabel)
self.ImportProgressBar = QtGui.QProgressBar(self.ImportPage)
- self.ImportProgressBar.setProperty(u'value', 0)
- self.ImportProgressBar.setInvertedAppearance(False)
+ self.ImportProgressBar.setValue(0)
self.ImportProgressBar.setObjectName(u'ImportProgressBar')
self.ImportLayout.addWidget(self.ImportProgressBar)
BibleImportWizard.addPage(self.ImportPage)
-
self.retranslateUi(BibleImportWizard)
self.FormatWidget.setCurrentIndex(0)
self.WebDownloadTabWidget.setCurrentIndex(0)
@@ -334,7 +323,6 @@ class Ui_BibleImportWizard(object):
self.FormatComboBox.setItemText(1, self.trUtf8('CSV'))
self.FormatComboBox.setItemText(2, self.trUtf8('OpenSong'))
self.FormatComboBox.setItemText(3, self.trUtf8('Web Download'))
- self.OsisBibleNameLabel.setText(self.trUtf8('Bible Name:'))
self.OsisLocationLabel.setText(self.trUtf8('File Location:'))
self.BooksLocationLabel.setText(self.trUtf8('Books Location:'))
self.VerseLocationLabel.setText(self.trUtf8('Verse Location:'))
@@ -362,4 +350,4 @@ class Ui_BibleImportWizard(object):
self.ImportPage.setSubTitle(
self.trUtf8('Please wait while your Bible is imported.'))
self.ImportProgressLabel.setText(self.trUtf8('Ready.'))
- #self.ImportProgressBar.setFormat(u'%p')
+ self.ImportProgressBar.setFormat(u'%p%')
diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py
index 7e82b6b7f..742598fdb 100644
--- a/openlp/plugins/bibles/forms/importwizardform.py
+++ b/openlp/plugins/bibles/forms/importwizardform.py
@@ -23,10 +23,10 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
+import csv
import logging
import os
import os.path
-from time import sleep
from PyQt4 import QtCore, QtGui
@@ -34,6 +34,8 @@ from bibleimportwizard import Ui_BibleImportWizard
from openlp.core.lib import Receiver
from openlp.plugins.bibles.lib.manager import BibleFormat
+log = logging.getLogger(__name__)
+
class DownloadLocation(object):
Unknown = -1
Crosswalk = 0
@@ -45,8 +47,8 @@ class DownloadLocation(object):
}
@classmethod
- def get_name(class_, id):
- return class_.Names[id]
+ def get_name(cls, id):
+ return cls.Names[id]
class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
@@ -54,12 +56,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
This is the Bible Import Wizard, which allows easy importing of Bibles
into OpenLP from other formats like OSIS, CSV and OpenSong.
"""
-
- global log
- log = logging.getLogger(u'BibleImportForm')
log.info(u'BibleImportForm loaded')
- def __init__(self, parent, config, biblemanager, bibleplugin):
+ def __init__(self, parent, config, manager, bibleplugin):
'''
Constructor
'''
@@ -68,10 +67,10 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
self.registerFields()
self.finishButton = self.button(QtGui.QWizard.FinishButton)
self.cancelButton = self.button(QtGui.QWizard.CancelButton)
- self.biblemanager = biblemanager
+ self.manager = manager
self.config = config
self.bibleplugin = bibleplugin
- self.biblemanager.set_process_dialog(self)
+ self.manager.set_process_dialog(self)
self.web_bible_list = {}
self.loadWebBibles()
QtCore.QObject.connect(self.LocationComboBox,
@@ -96,9 +95,9 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtCore.SIGNAL(u'currentIdChanged(int)'),
self.onCurrentIdChanged)
- def show(self):
+ def exec_(self):
self.setDefaults()
- return QtGui.QWizard.show()
+ return QtGui.QWizard.exec_(self)
def validateCurrentPage(self):
if self.currentId() == 0:
@@ -107,14 +106,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif self.currentId() == 1:
# Select page
if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS:
- if self.field(u'osis_biblename').toString() == u'':
- QtGui.QMessageBox.critical(self,
- self.trUtf8('Invalid Bible Name'),
- self.trUtf8('You need to specify a name for your '
- 'Bible!'),
- QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
- self.OsisBibleNameEdit.setFocus()
- return False
if self.field(u'osis_location').toString() == u'':
QtGui.QMessageBox.critical(self,
self.trUtf8('Invalid Bible Location'),
@@ -169,6 +160,15 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.CopyrightEdit.setFocus()
return False
+ elif self.manager.exists(
+ self.field(u'license_version').toString()):
+ QtGui.QMessageBox.critical(self,
+ self.trUtf8('Bible Exists'),
+ self.trUtf8('This Bible already exists! Please import '
+ 'a different Bible or first delete the existing one.'),
+ QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
+ self.VersionNameEdit.setFocus()
+ return False
return True
if self.currentId() == 3:
# Progress page
@@ -209,8 +209,6 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
def registerFields(self):
self.SelectPage.registerField(
u'source_format', self.FormatComboBox)
- self.SelectPage.registerField(
- u'osis_biblename', self.OsisBibleNameEdit)
self.SelectPage.registerField(
u'osis_location', self.OSISLocationEdit)
self.SelectPage.registerField(
@@ -237,24 +235,23 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
u'license_permission', self.PermissionEdit)
def setDefaults(self):
- self.setField(u'source_format', 0)
- self.setField(u'osis_biblename', u'')
- self.setField(u'osis_location', u'')
- self.setField(u'csv_booksfile', u'')
- self.setField(u'csv_versefile', u'')
- self.setField(u'opensong_file', u'')
- self.setField(u'web_location', 0)
- self.setField(u'web_biblename', self.BibleComboBox)
+ self.setField(u'source_format', QtCore.QVariant(0))
+ self.setField(u'osis_location', QtCore.QVariant(''))
+ self.setField(u'csv_booksfile', QtCore.QVariant(''))
+ self.setField(u'csv_versefile', QtCore.QVariant(''))
+ self.setField(u'opensong_file', QtCore.QVariant(''))
+ self.setField(u'web_location', QtCore.QVariant(DownloadLocation.Crosswalk))
+ self.setField(u'web_biblename', QtCore.QVariant(self.BibleComboBox))
self.setField(u'proxy_server',
- self.config.get_config(u'proxy address', u''))
+ QtCore.QVariant(self.config.get_config(u'proxy address', '')))
self.setField(u'proxy_username',
- self.config.get_config(u'proxy username',u''))
+ QtCore.QVariant(self.config.get_config(u'proxy username','')))
self.setField(u'proxy_password',
- self.config.get_config(u'proxy password',u''))
- self.setField(u'license_version', self.VersionNameEdit)
- self.setField(u'license_copyright', self.CopyrightEdit)
- self.setField(u'license_permission', self.PermissionEdit)
- self.onLocationComboBoxChanged(0)
+ QtCore.QVariant(self.config.get_config(u'proxy password','')))
+ self.setField(u'license_version', QtCore.QVariant(self.VersionNameEdit))
+ self.setField(u'license_copyright', QtCore.QVariant(self.CopyrightEdit))
+ self.setField(u'license_permission', QtCore.QVariant(self.PermissionEdit))
+ self.onLocationComboBoxChanged(DownloadLocation.Crosswalk)
def loadWebBibles(self):
"""
@@ -267,29 +264,33 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
fbibles = None
try:
self.web_bible_list[DownloadLocation.Crosswalk] = {}
- fbibles = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r')
- for line in fbibles:
- parts = line.split(u',')
- self.web_bible_list[DownloadLocation.Crosswalk][parts[0]] = \
- parts[1].rstrip()
+ books_file = open(os.path.join(filepath, u'crosswalkbooks.csv'), 'r')
+ dialect = csv.Sniffer().sniff(books_file.read(1024))
+ books_file.seek(0)
+ books_reader = csv.reader(books_file, dialect)
+ for line in books_reader:
+ self.web_bible_list[DownloadLocation.Crosswalk][line[0]] = \
+ unicode(line[1], u'utf-8').strip()
except:
log.exception(u'Crosswalk resources missing')
finally:
- if fbibles:
- fbibles.close()
+ if books_file:
+ books_file.close()
#Load and store BibleGateway Bibles
try:
self.web_bible_list[DownloadLocation.BibleGateway] = {}
- fbibles = open(os.path.join(filepath, u'biblegateway.csv'), 'r')
- for line in fbibles:
- parts = line.split(u',')
- self.web_bible_list[DownloadLocation.BibleGateway][parts[0]] = \
- parts[1].rstrip()
+ books_file = open(os.path.join(filepath, u'biblegateway.csv'), 'r')
+ dialect = csv.Sniffer().sniff(books_file.read(1024))
+ books_file.seek(0)
+ books_reader = csv.reader(books_file, dialect)
+ for line in books_reader:
+ self.web_bible_list[DownloadLocation.BibleGateway][line[0]] = \
+ unicode(line[1], u'utf-8').strip()
except:
log.exception(u'Biblegateway resources missing')
finally:
- if fbibles:
- fbibles.close()
+ if books_file:
+ books_file.close()
def getFileName(self, title, editbox):
filename = QtGui.QFileDialog.getOpenFileName(self, title,
@@ -317,22 +318,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
success = False
if bible_type == BibleFormat.OSIS:
# Import an OSIS bible
- success = self.biblemanager.register_osis_file_bible(
- unicode(self.field(u'license_version').toString()),
- unicode(self.field(u'osis_location').toString())
+ success = self.manager.import_bible(BibleFormat.OSIS,
+ name=unicode(self.field(u'license_version').toString()),
+ filename=unicode(self.field(u'osis_location').toString())
)
elif bible_type == BibleFormat.CSV:
# Import a CSV bible
- success = self.biblemanager.register_csv_file_bible(
- unicode(self.field(u'license_version').toString()),
- self.field(u'csv_booksfile').toString(),
- self.field(u'csv_versefile').toString()
+ success = self.manager.import_bible(BibleFormat.CSV,
+ name=unicode(self.field(u'license_version').toString()),
+ booksfile=self.field(u'csv_booksfile').toString(),
+ versefile=self.field(u'csv_versefile').toString()
)
elif bible_type == BibleFormat.OpenSong:
# Import an OpenSong bible
- success = self.biblemanager.register_opensong_bible(
- unicode(self.field(u'license_version').toString()),
- self.field(u'opensong_file').toString()
+ success = self.manager.import_bible(BibleFormat.OpenSong,
+ name=unicode(self.field(u'license_version').toString()),
+ filename=self.field(u'opensong_file').toString()
)
elif bible_type == BibleFormat.WebDownload:
# Import a bible from the web
@@ -344,21 +345,22 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
elif download_location == DownloadLocation.BibleGateway:
bible = self.web_bible_list[DownloadLocation.BibleGateway][
unicode(self.BibleComboBox.currentText())]
- success = self.biblemanager.register_http_bible(
- unicode(self.field(u'license_version').toString()),
- unicode(DownloadLocation.get_name(download_location)),
- unicode(bible),
- unicode(self.field(u'proxy_server').toString()),
- unicode(self.field(u'proxy_username').toString()),
- unicode(self.field(u'proxy_password').toString())
+ success = self.manager.import_bible(BibleFormat.WebDownload,
+ name=unicode(self.field(u'license_version').toString()),
+ download_source=unicode(DownloadLocation.get_name(download_location)),
+ download_name=unicode(bible),
+ proxy_server=unicode(self.field(u'proxy_server').toString()),
+ proxy_username=unicode(self.field(u'proxy_username').toString()),
+ proxy_password=unicode(self.field(u'proxy_password').toString())
)
if success:
- self.biblemanager.save_meta_data(
+ self.manager.save_meta_data(
unicode(self.field(u'license_version').toString()),
unicode(self.field(u'license_version').toString()),
unicode(self.field(u'license_copyright').toString()),
unicode(self.field(u'license_permission').toString())
)
+ self.manager.reload_bibles()
self.ImportProgressLabel.setText(self.trUtf8('Finished import.'))
else:
self.ImportProgressLabel.setText(
diff --git a/openlp/plugins/bibles/lib/bibleDBimpl.py b/openlp/plugins/bibles/lib/bibleDBimpl.py
deleted file mode 100644
index 9c65a7eaa..000000000
--- a/openlp/plugins/bibles/lib/bibleDBimpl.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman #
-# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
-# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
-# Carsten Tinggaard #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-
-import os
-import logging
-
-from common import BibleCommon
-from openlp.plugins.bibles.lib.models import *
-
-class BibleDBImpl(BibleCommon):
- global log
- log = logging.getLogger(u'BibleDBImpl')
- log.info(u'BibleDBimpl loaded')
-
- def __init__(self, biblepath, biblename, config):
- # Connect to database
- self.config = config
- self.biblefile = os.path.join(biblepath, biblename + u'.sqlite')
- log.debug(u'Load bible %s on path %s', biblename, self.biblefile)
- db_type = self.config.get_config(u'db type', u'sqlite')
- db_url = u''
- if db_type == u'sqlite':
- db_url = u'sqlite:///' + self.biblefile
- else:
- db_url = u'%s://%s:%s@%s/%s' % \
- (db_type, self.config.get_config(u'db username'),
- self.config.get_config(u'db password'),
- self.config.get_config(u'db hostname'),
- self.config.get_config(u'db database'))
- self.metadata, self.session = init_models(db_url)
- self.metadata.create_all(checkfirst=True)
-
- def create_tables(self):
- log.debug(u'createTables')
- self.save_meta(u'dbversion', u'2')
- self._load_testament(u'Old Testament')
- self._load_testament(u'New Testament')
- self._load_testament(u'Apocrypha')
-
- def add_verse(self, bookid, chap, vse, text):
- verse = Verse()
- verse.book_id = bookid
- verse.chapter = chap
- verse.verse = vse
- verse.text = text
- self.session.add(verse)
- return verse
-
- def save_verses(self):
- log.debug('Saving verses...')
- self.session.commit()
-
- def create_chapter(self, bookid, chap, textlist):
- log.debug(u'create_chapter %s,%s', bookid, chap)
- #text list has book and chapter as first to elements of the array
- for verse_number, verse_text in textlist.iteritems():
- verse = Verse()
- verse.book_id = bookid
- verse.chapter = chap
- verse.verse = verse_number
- verse.text = verse_text
- self.session.add(verse)
- self.session.commit()
-
- def create_book(self, bookname, bookabbrev, testament=1):
- log.debug(u'create_book %s,%s', bookname, bookabbrev)
- book = Book()
- book.testament_id = testament
- book.name = bookname
- book.abbreviation = bookabbrev
- self.session.add(book)
- self.session.commit()
- return book
-
- def save_meta(self, key, value):
- log.debug(u'save_meta %s/%s', key, value)
- bmeta = BibleMeta()
- bmeta.key = key
- bmeta.value = value
- self.session.add(bmeta)
- self.session.commit()
-
- def get_meta(self, metakey):
- log.debug(u'get meta %s', metakey)
- return self.session.query(BibleMeta).filter_by(key=metakey).first()
-
- def delete_meta(self, metakey):
- biblemeta = self.get_meta(metakey)
- try:
- self.session.delete(biblemeta)
- self.session.commit()
- return True
- except:
- return False
-
- def _load_testament(self, testament):
- log.debug(u'load_testaments %s', testament)
- test = ONTestament()
- test.name = testament
- self.session.add(test)
- self.session.commit()
-
- def get_bible_books(self):
- log.debug(u'get_bible_books')
- return self.session.query(Book).order_by(Book.id).all()
-
- def get_max_bible_book_verses(self, bookname, chapter):
- log.debug(u'get_max_bible_book_verses %s, %s', bookname, chapter)
- verse = self.session.query(Verse).join(Book).filter(
- Book.name == bookname).filter(
- Verse.chapter == chapter).order_by(Verse.verse.desc()).first()
- if verse == None:
- return 0
- else:
- return verse.verse
-
- def get_max_bible_book_chapter(self, bookname):
- log.debug(u'get_max_bible_book_chapter %s', bookname)
- verse = self.session.query(Verse).join(Book).filter(
- Book.name == bookname).order_by(Verse.chapter.desc()).first()
- if verse == None:
- return 0
- else:
- return verse.chapter
-
- def get_bible_book(self, bookname):
- log.debug(u'get_bible_book %s', bookname)
- book = self.session.query(Book).filter(
- Book.name.like(bookname + u'%')).first()
- if book is None:
- book = self.session.query(Book).filter(
- Book.abbreviation.like(bookname + u'%')).first()
- return book
-
- def get_bible_chapter(self, id, chapter):
- log.debug(u'get_bible_chapter %s, %s', id, chapter)
- return self.session.query(Verse).filter_by(chapter=chapter).filter_by(
- book_id=id).first()
-
- def get_bible_text(self, bookname, chapter, sverse, everse):
- log.debug(u'get_bible_text %s, %s, %s, %s', bookname, chapter, sverse,
- everse)
- #Look up book name or abbreviation
- book = self.get_bible_book(bookname)
- if book:
- bookname = book.name
- log.debug(u'bookname corrected to %s' % bookname)
- verses = self.session.query(Verse).join(Book).filter(
- Book.name == bookname).filter(Verse.chapter == chapter).filter(
- Verse.verse>=sverse).filter(Verse.verse<=everse).order_by(
- Verse.verse).all()
- return verses
-
- def get_verses_from_text(self, versetext):
- log.debug(u'get_verses_from_text %s',versetext)
- versetext = u'%%%s%%' % versetext
- verses = self.session.query(Verse).filter(
- Verse.text.like(versetext)).all()
- return verses
-
- def dump_bible(self):
- log.debug( u'.........Dumping Bible Database')
- log.debug( '...............................Books ')
- books = self.session.query(Book).all()
- log.debug(books)
- log.debug( u'...............................Verses ')
- verses = self.session.query(Verse).all()
- log.debug(verses)
\ No newline at end of file
diff --git a/openlp/plugins/bibles/lib/bibleHTTPimpl.py b/openlp/plugins/bibles/lib/bibleHTTPimpl.py
deleted file mode 100644
index f8cad5c18..000000000
--- a/openlp/plugins/bibles/lib/bibleHTTPimpl.py
+++ /dev/null
@@ -1,228 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman #
-# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
-# Gorven, Scott Guerrieri, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
-# Carsten Tinggaard #
-# --------------------------------------------------------------------------- #
-# This program is free software; you can redistribute it and/or modify it #
-# under the terms of the GNU General Public License as published by the Free #
-# Software Foundation; version 2 of the License. #
-# #
-# This program is distributed in the hope that it will be useful, but WITHOUT #
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
-# more details. #
-# #
-# You should have received a copy of the GNU General Public License along #
-# with this program; if not, write to the Free Software Foundation, Inc., 59 #
-# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
-###############################################################################
-
-import logging
-
-from common import BibleCommon, SearchResults
-
-class BGExtract(BibleCommon):
- global log
- log = logging.getLogger(u'BibleHTTPMgr(BG_extract)')
- log.info(u'BG_extract loaded')
-
- def __init__(self, proxyurl= None):
- log.debug(u'init %s', proxyurl)
- self.proxyurl = proxyurl
-
- def get_bible_chapter(self, version, bookname, chapter) :
- """
- Access and decode bibles via the BibleGateway website
-
- ``Version``
- The version of the bible like 31 for New International version
-
- ``bookname``
- Name of the Book
-
- ``chapter``
- Chapter number
- """
- log.debug(u'get_bible_chapter %s,%s,%s',
- version, bookname, chapter)
- urlstring = \
- u'http://www.biblegateway.com/passage/?search=%s+%d&version=%s' % \
- (bookname, chapter, version)
- log.debug(u'BibleGateway urm = %s' % urlstring)
- xml_string = self._get_web_text(urlstring, self.proxyurl)
- verseSearch = u' -1:
- # clear out string
- verseText = u''
- versePos = xml_string.find(u'', versePos) + 6
- i = xml_string.find(verseSearch, versePos + 1)
- # Not sure if this is needed now
- if i == -1:
- i = xml_string.find(u' 0 and j < i:
- i = j
- verseText = xml_string[versePos + 7 : i ]
- # store the verse
- bible[verse] = self._clean_text(verseText)
- versePos = -1
- else:
- verseText = xml_string[versePos: i]
- start_tag = verseText.find(verseFootnote)
- while start_tag > -1:
- end_tag = verseText.find(u'')
- verseText = verseText[:start_tag] + verseText[end_tag + 6:len(verseText)]
- start_tag = verseText.find(verseFootnote)
- # Chop off verse and start again
- xml_string = xml_string[i:]
- #look for the next verse
- versePos = xml_string.find(verseSearch)
- # store the verse
- bible[verse] = self._clean_text(verseText)
- verse += 1
- return SearchResults(bookname, chapter, bible)
-
-class CWExtract(BibleCommon):
- global log
- log = logging.getLogger(u'BibleHTTPMgr(CWExtract)')
- log.info(u'CWExtract loaded')
-
- def __init__(self, proxyurl=None):
- log.debug(u'init %s', proxyurl)
- self.proxyurl = proxyurl
-
- def get_bible_chapter(self, version, bookname, chapter) :
- log.debug(u'getBibleChapter %s,%s,%s',
- version,bookname, chapter)
- """
- Access and decode bibles via the Crosswalk website
-
- ``version``
- The version of the bible like niv for New International Version
-
- ``bookname``
- Text name of in english e.g. 'gen' for Genesis
-
- ``chapter``
- Chapter number
- """
- log.debug(u'get_bible_chapter %s,%s,%s',
- version, bookname, chapter)
- bookname = bookname.replace(u' ', u'')
- urlstring = u'http://bible.crosswalk.com/OnlineStudyBible/bible.cgi?word=%s+%d&version=%s'\
- % (bookname, chapter, version)
- xml_string = self._get_web_text(urlstring, self.proxyurl)
- ## Strip Book Title from Heading to return it to system
- ##
- i = xml_string.find(u'