This commit is contained in:
Tim Bentley 2010-10-24 19:20:23 +01:00
commit 39f7b3b4d8
37 changed files with 482 additions and 170 deletions

View File

@ -3,9 +3,13 @@
:mod:`core` Module :mod:`core` Module
================== ==================
.. automodule:: openlp.core
:members:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
lib lib
theme theme
ui
utils

View File

@ -1,7 +1,7 @@
.. _core-lib: .. _core-lib:
:mod:`lib` Module Object Library
================= ==============
.. automodule:: openlp.core.lib .. automodule:: openlp.core.lib
:members: :members:

View File

@ -0,0 +1,27 @@
.. _core-ui:
User Interface
==============
.. automodule:: openlp.core.ui
Main Windows
------------
.. autoclass:: openlp.core.ui.mainwindow.MainWindow
:members:
.. autoclass:: openlp.core.ui.maindisplay.MainDisplay
:members:
Managers
--------
.. autoclass:: openlp.core.ui.servicemanager.ServiceManager
:members:
.. autoclass:: openlp.core.ui.mediadockmanager.MediaDockManager
:members:
.. autoclass:: openlp.core.ui.thememanager.ThemeManager
:members:

View File

@ -0,0 +1,7 @@
.. _core-utils:
Utilities
=========
.. automodule:: openlp.core.utils
:members:

View File

@ -15,7 +15,6 @@ Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
openlp
core/index core/index
plugins/index plugins/index

View File

@ -0,0 +1,31 @@
.. _plugins-alerts:
Alerts Plugin
=============
.. automodule:: openlp.plugins.alerts
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.alerts.alertsplugin.AlertsPlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.alerts.forms
:members:
.. autoclass:: openlp.plugins.alerts.forms.alertform.AlertForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.alerts.lib
:members:
.. automodule:: openlp.plugins.alerts.lib.db
:members:

View File

@ -0,0 +1,34 @@
.. _plugins-custom:
Custom Slides Plugin
====================
.. automodule:: openlp.plugins.custom
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.custom.customplugin.CustomPlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.custom.forms
:members:
.. autoclass:: openlp.plugins.custom.forms.editcustomform.EditCustomForm
:members:
.. autoclass:: openlp.plugins.custom.forms.editcustomslideform.EditCustomSlideForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.custom.lib
:members:
.. automodule:: openlp.plugins.custom.lib.mediaitem
:members:

View File

@ -1,7 +1,7 @@
.. _plugins-index: .. _plugins-index:
:mod:`plugins` Module Plugins
===================== =======
.. automodule:: openlp.plugins .. automodule:: openlp.plugins
:members: :members:
@ -14,15 +14,7 @@
presentations presentations
media media
images images
custom
:mod:`custom` Plugin remotes
-------------------- songusage
alerts
.. automodule:: openlp.plugins.custom
:members:
:mod:`songusage` Plugin
-----------------------
.. automodule:: openlp.plugins.songusage
:members:

View File

@ -0,0 +1,19 @@
.. _plugins-remotes:
Remotes Plugin
==============
.. automodule:: openlp.plugins.remotes
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.remotes.remoteplugin.RemotesPlugin
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.remotes.lib
:members:

View File

@ -0,0 +1,34 @@
.. _plugins-songusage:
Song Usage Plugin
=================
.. automodule:: openlp.plugins.songusage
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.songusage.songusageplugin.SongUsagePlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.songusage.forms
:members:
.. autoclass:: openlp.plugins.songusage.forms.songusagedeleteform.SongUsageDeleteForm
:members:
.. autoclass:: openlp.plugins.songusage.forms.songusagedetailform.SongUsageDetailForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.songusage.lib
:members:
.. automodule:: openlp.plugins.songusage.lib.db
:members:

View File

@ -3,7 +3,7 @@ Dual Monitor Setup
================== ==================
The first step in getting OpenLP working on your system is to setup your The first step in getting OpenLP working on your system is to setup your
computer properly for dual monitors. This is not very difficult, but the steps computer properly for dual monitors. This is not very difficult, but the steps
do vary depending on operating system. do vary depending on operating system.
Most modern computers do have the ability for dual monitors. To be certain Most modern computers do have the ability for dual monitors. To be certain
@ -19,11 +19,13 @@ monitors will have two of, or a combination of the two connectors below.
.. image:: pics/dvi.png .. image:: pics/dvi.png
A laptop computer setup only varies slightly, generally you will need only one A laptop computer setup only varies slightly, generally you will need only one
of outputs pictured above since your laptops screen serves as one of the of outputs pictured above since your laptops screen serves as one of the
monitors. Sometimes with older laptops a key stroke generally involving the FN monitors. Sometimes with older laptops a key stroke generally involving the
key and another key is required to enable the second monitor on laptops. :kbd:`Fn` key and another key is required to enable the second monitor on
laptops.
Some computers also incorporate the use of S-Video or HDMI connections. Some computers also incorporate the use of :abbr:`S-Video (Separate Video)` or
:abbr:`HDMI (High-Definition Multimedia Interface)` connections.
A typical OpenLP set up consist of your normal single monitor setup, with your A typical OpenLP set up consist of your normal single monitor setup, with your
projector setup as the second monitor. With the option of extending your projector setup as the second monitor. With the option of extending your
@ -39,49 +41,47 @@ next.
Windows 7 Windows 7
^^^^^^^^^ ^^^^^^^^^
Windows 7 has using a projector in mind. Simply connect your projector and Windows 7 has using a projector in mind. Simply connect your projector and
press the **Windows key and tap P**. press :kbd:`Windows+P`.
The more traditional way is also fairly straight forward. Go to the control The more traditional way is also fairly straight forward. Go to
panel and click on display. This will open up the Display options. You can :guilabel:`Control Panel` and click on :guilabel:`Display`. This will open up
also bypass this step by right click on a blank area on your desktop and the :guilabel:`Display` dialog. You can also bypass this step by right click on
selecting **resolution**. a blank area on your desktop and selecting :guilabel:`Resolution`.
.. image:: pics/winsevendisplay.png .. image:: pics/winsevendisplay.png
Then click on the Screen Resolution from the left pane. Then click on the :guilabel:`Adjust resolution` link in the left pane. Enable
your projector and make sure that the selected value for :guilabel:`Multiple
displays` is :guilabel:`Extend these displays`.
.. image:: pics/winsevenresolution.png .. image:: pics/winsevenresolution.png
Then enable your projector and ensure your desktop is extended.
Windows Vista Windows Vista
^^^^^^^^^^^^^ ^^^^^^^^^^^^^
From the control panel click on personalize, or right click a blank place on From :guilabel:`Control Panel` click on :guilabel:`Personalize`, or right click
the desktop and click personalization. a blank place on the desktop and click :guilabel:`Personalization`.
.. image:: pics/vistapersonalize.png .. image:: pics/vistapersonalize.png
From the **Personalization** window click on Display Settings. From the :guilabel:`Personalization` window click on :guilabel:`Display
Settings`. Then enable the montior that represents your projector and make sure
you have checked :guilabel:`Extend the desktop onto this monitor`.
.. image:: pics/vistadisplaysettings.png .. image:: pics/vistadisplaysettings.png
Then enable the montior that represents your projector an make sure your
you have checked Extend the desktop.
Windows XP Windows XP
^^^^^^^^^^ ^^^^^^^^^^
From the control panel select Display, or right click on a blank area of the From :guilabel:`Control Panel` select :guilabel:`Display`, or right click on a
desktop and select properties. From the properties window click on the settings blank area of the desktop and select :guilabel:`Properties`. From the
tab. :guilabel:`Display Properties` window click on the :guilabel:`Settings` tab.
Then click on the monitor that represents your projector and make sure you have
checked :guilabel:`Extend my Windows desktop onto this monitor`.
.. image:: pics/xpdisplaysettings.png .. image:: pics/xpdisplaysettings.png
Then enable the monitor that represents your projector an make sure your
you have checked Extend the desktop.
Linux Linux
----- -----
@ -91,22 +91,22 @@ assumes that you have properly set up any proprietary drivers if needed. You
should seek out your distributions documentation if this general guide does not should seek out your distributions documentation if this general guide does not
work. work.
GNOME GNOME
^^^^^ ^^^^^
This guide is for users of the GNOME desktop who do not use proprietary drivers. This guide is for users of the GNOME desktop who do not use proprietary drivers.
From most distros go to System --> Preferences --> Display Settings (Monitors) From most distros go to :menuselection:`System --> Preferences --> Display
Settings (Monitors)`. Set up your projector with the correct resolution and make
sure that :guilabel:`Same image on all monitors` is **unchecked**.
.. image:: pics/gnome.png .. image:: pics/gnome.png
Setup your projector with the correct resolution and make sure you do **not**
have mirrored desktop enabled (same image on all monitors).
KDE KDE
^^^ ^^^
This guide is for users of the KDE desktop who do not use proprietary drivers. This guide is for users of the KDE desktop who do not use proprietary drivers.
From most distros click the Kick Off menu and navigate to **system settings** From most distros click the Kick Off menu and navigate to
:guilabel:`System Settings`
.. image:: pics/kdesystemsettings.png .. image:: pics/kdesystemsettings.png
@ -118,10 +118,63 @@ From here you will need to set up your projector with the appropriate
resolution, and position. OpenLP works best projecting to the monitor on the resolution, and position. OpenLP works best projecting to the monitor on the
right. right.
Linux Systems Using nVidia Drivers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This guide is for users of the proprietary nVidia driver on Linux Distributions.
It is assumed that you have properly setup your drivers according to your
distribution's documentation, and you have a working ``xorg.conf`` file in place.
If you wish to make the changes permanent in setting up your system for dual
monitors it will be necessary to modify your ``xorg.conf`` file. It is always a
good idea to make a backup of any critical file before making changes::
user@linux:~ $ sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.old
Or for those using systems that use the root user instead of sudo, change to
root and enter::
root@linux: # cp /etc/X11/xorg.conf /etc/X11/xorg.conf.old
The exact location of the ``xorg.conf`` file can vary so check your
distribution's documentation.
If you want to make your changes permanent run nVidia settings from the
terminal::
user@linux:~ $ sudo nvidia-settings
Or, as root::
root@linux: # nividia-settings
If you do not want to write the changes to your ``xorg.conf`` file simply run
the nVidia Settings program (``nvidia-settings``) from your desktop's menu,
usually in an administration or system menu, or from the terminal as a normal
user run::
user@linux:~ $ nvidia-settings
Once you have opened nVidia Settings, click on
:guilabel:`X Server Display Configuration`. Then select the monitor you are
wanting to use as your second monitor and click :guilabel:`Configure`.
.. image:: pics/nvlinux1.png
After clicking :guilabel:`Configure`, select :guilabel:`TwinView`. Then click
:guilabel:`OK`.
.. image:: pics/twinview.png
Then click :guilabel:`Apply` and if you are happy with the way things look click
:guilabel:`Keep` to keep your new settings. Don't worry if all goes wrong the
settings will return back to the previous settings in 15 seconds without any
action. nVidia Settings should take care of selecting your optimum resolution
etc, but that can be changed as needed. When you are happy with everything click
on :guilabel:`Save to X Configuration File`.
.. image:: pics/xorgwrite.png
Then click :guilabel:`Save` and you should be set. You may want to restart X or
your machine just to make sure all the settings carry over the next time you log
in.

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -316,6 +316,7 @@ from theme import ThemeLevel, ThemeXML, BackgroundGradientType, BackgroundType,
HorizontalType, VerticalType HorizontalType, VerticalType
from spelltextedit import SpellTextEdit from spelltextedit import SpellTextEdit
from eventreceiver import Receiver from eventreceiver import Receiver
from imagemanager import ImageManager
from settingsmanager import SettingsManager from settingsmanager import SettingsManager
from plugin import PluginStatus, StringContent, Plugin from plugin import PluginStatus, StringContent, Plugin
from pluginmanager import PluginManager from pluginmanager import PluginManager

View File

@ -331,6 +331,7 @@ def build_html(item, screen, alert, islive):
height = screen[u'size'].height() height = screen[u'size'].height()
theme = item.themedata theme = item.themedata
webkitvers = webkit_version() webkitvers = webkit_version()
# Image generated and poked in
if item.bg_image_bytes: if item.bg_image_bytes:
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
else: else:

View File

@ -0,0 +1,158 @@
# -*- 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, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Provides the store and management for Images automatically caching them and
resizing them when needed. Only one copy of each image is needed in the system.
A Thread is used to convert the image to a byte array so the user does not need
to wait for the conversion to happen.
"""
import logging
import os
import time
from PyQt4 import QtCore
from openlp.core.lib import resize_image, image_to_byte
log = logging.getLogger(__name__)
class ImageThread(QtCore.QThread):
"""
A special Qt thread class to speed up the display of text based frames.
This is threaded so it loads the frames in background
"""
def __init__(self, manager):
QtCore.QThread.__init__(self, None)
self.image_mamager = manager
def run(self):
"""
Run the thread.
"""
self.image_mamager.process()
class Image(object):
name = ''
path = ''
dirty = True
image = None
image_bytes = None
class ImageManager(QtCore.QObject):
"""
Image Manager handles the conversion and sizing of images.
"""
log.info(u'Image Manager loaded')
def __init__(self):
self._cache = {}
self._thread_running = False
self._cache_dirty = False
self.image_thread = ImageThread(self)
def update_display(self, width, height):
"""
Screen has changed size so rebuild the cache to new size
"""
log.debug(u'update_display')
self.width = width
self.height = height
# mark the images as dirty for a rebuild
for key in self._cache.keys():
image = self._cache[key]
image.dirty = True
fullpath = os.path.join(image.path, image.name)
image.image = resize_image(fullpath,
self.width, self.height)
self._cache_dirty = True
# only one thread please
if not self._thread_running:
self.image_thread.start()
def get_image(self, name):
"""
Return the Qimage from the cache
"""
log.debug(u'get_image %s' % name)
return self._cache[name].image
def get_image_bytes(self, name):
"""
Returns the byte string for an image
If not present wait for the background thread to process it.
"""
log.debug(u'get_image_bytes %s' % name)
if not self._cache[name].image_bytes:
while self._cache[name].dirty:
log.debug(u'get_image_bytes - waiting')
time.sleep(0.1)
return self._cache[name].image_bytes
def add_image(self, name, path):
"""
Add image to cache if it is not already there
"""
log.debug(u'add_image %s:%s' % (name, path))
if not name in self._cache:
image = Image()
image.name = name
image.path = path
image.image = resize_image(path,
self.width, self.height)
self._cache[name] = image
self._cache_dirty = True
# only one thread please
if not self._thread_running:
self.image_thread.start()
def process(self):
"""
Controls the processing called from a QThread
"""
log.debug(u'process - started')
self._thread_running = True
self.clean_cache()
# data loaded since we started ?
while self._cache_dirty:
log.debug(u'process - recycle')
self.clean_cache()
self._thread_running = False
log.debug(u'process - ended')
def clean_cache(self):
"""
Actually does the work.
"""
log.debug(u'clean_cache')
# we will clean the cache now
self._cache_dirty = False
for key in self._cache.keys():
image = self._cache[key]
if image.dirty:
image.image_bytes = image_to_byte(image.image)
image.dirty = False

View File

@ -51,11 +51,6 @@ class Renderer(object):
self._rect = None self._rect = None
self.theme_name = None self.theme_name = None
self._theme = None self._theme = None
self._bg_image_filename = None
self.frame = None
self.bg_frame = None
self.bg_image = None
self.bg_image_bytes = None
def set_theme(self, theme): def set_theme(self, theme):
""" """
@ -66,14 +61,7 @@ class Renderer(object):
""" """
log.debug(u'set theme') log.debug(u'set theme')
self._theme = theme self._theme = theme
self.bg_frame = None
self.bg_image = None
self.bg_image_bytes = None
self._bg_image_filename = None
self.theme_name = theme.theme_name self.theme_name = theme.theme_name
if theme.background_type == u'image':
if theme.background_filename:
self._bg_image_filename = unicode(theme.background_filename)
def set_text_rectangle(self, rect_main, rect_footer): def set_text_rectangle(self, rect_main, rect_footer):
""" """
@ -105,39 +93,6 @@ class Renderer(object):
(build_lyrics_format_css(self._theme, self.page_width, (build_lyrics_format_css(self._theme, self.page_width,
self.page_height), build_lyrics_outline_css(self._theme)) self.page_height), build_lyrics_outline_css(self._theme))
def set_frame_dest(self, frame_width, frame_height):
"""
Set the size of the slide.
``frame_width``
The width of the slide.
``frame_height``
The height of the slide.
"""
log.debug(u'set frame dest (frame) w %d h %d', frame_width,
frame_height)
self.frame = QtGui.QImage(frame_width, frame_height,
QtGui.QImage.Format_ARGB32_Premultiplied)
if self._bg_image_filename and not self.bg_image:
self.bg_image = resize_image(self._bg_image_filename,
self.frame.width(), self.frame.height())
if self._theme.background_type == u'image':
self.bg_frame = QtGui.QImage(self.frame.width(),
self.frame.height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
painter = QtGui.QPainter()
painter.begin(self.bg_frame)
painter.fillRect(self.frame.rect(), QtCore.Qt.black)
if self.bg_image:
painter.drawImage(0, 0, self.bg_image)
painter.end()
self.bg_image_bytes = image_to_byte(self.bg_frame)
else:
self.bg_frame = None
self.bg_image_bytes = None
def format_slide(self, words, line_break): def format_slide(self, words, line_break):
""" """
Figure out how much text can appear on a slide, using the current Figure out how much text can appear on a slide, using the current

View File

@ -28,7 +28,7 @@ import logging
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Renderer, ThemeLevel, ServiceItem from openlp.core.lib import Renderer, ThemeLevel, ServiceItem, ImageManager
from openlp.core.ui import MainDisplay from openlp.core.ui import MainDisplay
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -56,7 +56,9 @@ class RenderManager(object):
""" """
log.debug(u'Initilisation started') log.debug(u'Initilisation started')
self.screens = screens self.screens = screens
self.image_manager = ImageManager()
self.display = MainDisplay(self, screens, False) self.display = MainDisplay(self, screens, False)
self.display.imageManager = self.image_manager
self.display.setup() self.display.setup()
self.theme_manager = theme_manager self.theme_manager = theme_manager
self.renderer = Renderer() self.renderer = Renderer()
@ -75,9 +77,11 @@ class RenderManager(object):
log.debug(u'Update Display') log.debug(u'Update Display')
self.calculate_default(self.screens.current[u'size']) self.calculate_default(self.screens.current[u'size'])
self.display = MainDisplay(self, self.screens, False) self.display = MainDisplay(self, self.screens, False)
self.display.imageManager = self.image_manager
self.display.setup() self.display.setup()
self.renderer.bg_frame = None self.renderer.bg_frame = None
self.themedata = None self.themedata = None
self.image_manager.update_display(self.width, self.height)
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global): def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
""" """
@ -153,7 +157,8 @@ class RenderManager(object):
self.calculate_default(self.screens.current[u'size']) self.calculate_default(self.screens.current[u'size'])
self.renderer.set_theme(self.themedata) self.renderer.set_theme(self.themedata)
self.build_text_rectangle(self.themedata) self.build_text_rectangle(self.themedata)
self.renderer.set_frame_dest(self.width, self.height) self.image_manager.add_image(self.themedata.theme_name,
self.themedata.background_filename)
return self.renderer._rect, self.renderer._rect_footer return self.renderer._rect, self.renderer._rect_footer
def build_text_rectangle(self, theme): def build_text_rectangle(self, theme):
@ -211,7 +216,7 @@ class RenderManager(object):
serviceItem.raw_footer = footer serviceItem.raw_footer = footer
serviceItem.render(True) serviceItem.render(True)
self.display.buildHtml(serviceItem) self.display.buildHtml(serviceItem)
raw_html = serviceItem.get_rendered_frame(0)[1] raw_html = serviceItem.get_rendered_frame(0)
preview = self.display.text(raw_html) preview = self.display.text(raw_html)
# Reset the real screen size for subsequent render requests # Reset the real screen size for subsequent render requests
self.calculate_default(self.screens.current[u'size']) self.calculate_default(self.screens.current[u'size'])

View File

@ -30,7 +30,6 @@ type and capability of an item.
import logging import logging
import os import os
import time
import uuid import uuid
from PyQt4 import QtGui from PyQt4 import QtGui
@ -160,12 +159,10 @@ class ServiceItem(object):
theme = self.theme theme = self.theme
self.main, self.footer = \ self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride) self.render_manager.set_override_theme(theme, useOverride)
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
self.themedata = self.render_manager.renderer._theme self.themedata = self.render_manager.renderer._theme
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides') log.debug(u'Formatting slides')
for slide in self._raw_frames: for slide in self._raw_frames:
before = time.time()
formatted = self.render_manager \ formatted = self.render_manager \
.format_slide(slide[u'raw_slide'], line_break) .format_slide(slide[u'raw_slide'], line_break)
for page in formatted: for page in formatted:
@ -174,12 +171,8 @@ class ServiceItem(object):
u'text': clean_tags(page.rstrip()), u'text': clean_tags(page.rstrip()),
u'html': expand_tags(page.rstrip()), u'html': expand_tags(page.rstrip()),
u'verseTag': slide[u'verseTag'] }) u'verseTag': slide[u'verseTag'] })
log.log(15, u'Formatting took %4s' % (time.time() - before)) elif self.service_item_type == ServiceItemType.Image or \
elif self.service_item_type == ServiceItemType.Image: self.service_item_type == ServiceItemType.Command:
for slide in self._raw_frames:
slide[u'image'] = resize_image(slide[u'image'],
self.render_manager.width, self.render_manager.height)
elif self.service_item_type == ServiceItemType.Command:
pass pass
else: else:
log.error(u'Invalid value renderer :%s' % self.service_item_type) log.error(u'Invalid value renderer :%s' % self.service_item_type)
@ -192,7 +185,7 @@ class ServiceItem(object):
else: else:
self.foot_text = u'%s<br>%s' % (self.foot_text, foot) self.foot_text = u'%s<br>%s' % (self.foot_text, foot)
def add_from_image(self, path, title, image): def add_from_image(self, path, title):
""" """
Add an image slide to the service item. Add an image slide to the service item.
@ -201,13 +194,11 @@ class ServiceItem(object):
``title`` ``title``
A title for the slide in the service item. A title for the slide in the service item.
``image``
The actual image file name.
""" """
self.service_item_type = ServiceItemType.Image self.service_item_type = ServiceItemType.Image
self._raw_frames.append( self._raw_frames.append(
{u'title': title, u'image': image, u'path': path}) {u'title': title, u'path': path})
self.render_manager.image_manager.add_image(title, path)
self._new_item() self._new_item()
def add_from_text(self, title, raw_slide, verse_tag=None): def add_from_text(self, title, raw_slide, verse_tag=None):
@ -241,7 +232,7 @@ class ServiceItem(object):
""" """
self.service_item_type = ServiceItemType.Command self.service_item_type = ServiceItemType.Command
self._raw_frames.append( self._raw_frames.append(
{u'title': file_name, u'image': image, u'path': path}) {u'title': file_name, u'image':image, u'path': path})
self._new_item() self._new_item()
def get_service_repr(self): def get_service_repr(self):
@ -310,8 +301,7 @@ class ServiceItem(object):
elif self.service_item_type == ServiceItemType.Image: elif self.service_item_type == ServiceItemType.Image:
for text_image in serviceitem[u'serviceitem'][u'data']: for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image) filename = os.path.join(path, text_image)
real_image = QtGui.QImage(unicode(filename)) self.add_from_image(filename, text_image)
self.add_from_image(path, text_image, real_image)
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for text_image in serviceitem[u'serviceitem'][u'data']: for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image[u'title']) filename = os.path.join(path, text_image[u'title'])
@ -387,9 +377,11 @@ class ServiceItem(object):
renders it if required. renders it if required.
""" """
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
return None, self._display_frames[row][u'html'].split(u'\n')[0] return self._display_frames[row][u'html'].split(u'\n')[0]
elif self.service_item_type == ServiceItemType.Image:
return self._raw_frames[row][u'title']
else: else:
return self._raw_frames[row][u'image'], u'' return self._raw_frames[row][u'image']
def get_frame_title(self, row=0): def get_frame_title(self, row=0):
""" """

View File

@ -25,7 +25,6 @@
############################################################################### ###############################################################################
import re import re
import sys
try: try:
import enchant import enchant
from enchant import DictNotFoundError from enchant import DictNotFoundError
@ -37,7 +36,7 @@ except ImportError:
# http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/ # http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import html_expands, translate, context_menu_action from openlp.core.lib import html_expands, translate
class SpellTextEdit(QtGui.QPlainTextEdit): class SpellTextEdit(QtGui.QPlainTextEdit):
def __init__(self, *args): def __init__(self, *args):

View File

@ -157,12 +157,12 @@ class VerticalType(object):
Middle = 1 Middle = 1
Bottom = 2 Bottom = 2
boolean_list = [u'bold', u'italics', u'override', u'outline', u'shadow', \ boolean_list = [u'italics', u'override', u'outline', u'shadow',
u'slide_transition'] u'slide_transition']
integer_list =[u'size', u'line_adjustment', u'x', u'height', u'y', \ integer_list = [u'proportion', u'line_adjustment', u'x', u'height', u'y',
u'width', u'shadow_size', u'outline_size', u'horizontal_align', \ u'width', u'shadow_size', u'outline_size', u'horizontal_align',
u'vertical_align'] u'vertical_align', u'wrap_style']
class ThemeXML(object): class ThemeXML(object):
""" """

View File

@ -40,7 +40,6 @@ class HideMode(object):
from themeform import ThemeForm from themeform import ThemeForm
from filerenameform import FileRenameForm from filerenameform import FileRenameForm
from maindisplay import MainDisplay from maindisplay import MainDisplay
from slidecontroller import HideMode
from servicenoteform import ServiceNoteForm from servicenoteform import ServiceNoteForm
from serviceitemeditform import ServiceItemEditForm from serviceitemeditform import ServiceItemEditForm
from screen import ScreenList from screen import ScreenList

View File

@ -24,7 +24,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from exceptiondialog import Ui_ExceptionDialog from exceptiondialog import Ui_ExceptionDialog

View File

@ -27,7 +27,6 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from filerenamedialog import Ui_FileRenameDialog from filerenamedialog import Ui_FileRenameDialog
from openlp.core.lib import translate
class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog):
""" """

View File

@ -90,6 +90,9 @@ class DisplayWidget(QtGui.QGraphicsView):
event.ignore() event.ignore()
class MainDisplay(DisplayWidget): class MainDisplay(DisplayWidget):
"""
This is the display screen.
"""
def __init__(self, parent, screens, live): def __init__(self, parent, screens, live):
DisplayWidget.__init__(self, live, parent=None) DisplayWidget.__init__(self, live, parent=None)
@ -222,7 +225,14 @@ class MainDisplay(DisplayWidget):
shrinkItem.resize(self.screen[u'size'].width(), shrinkItem.resize(self.screen[u'size'].width(),
self.screen[u'size'].height()) self.screen[u'size'].height())
def image(self, image): def directImage(self, name, path):
"""
API for replacement backgrounds so Images are added directly to cache
"""
image = self.imageManager.add_image(name, path)
self.image(name)
def image(self, name):
""" """
Add an image as the background. The image is converted to a Add an image as the background. The image is converted to a
bytestream on route. bytestream on route.
@ -231,25 +241,20 @@ class MainDisplay(DisplayWidget):
The Image to be displayed can be QImage or QPixmap The Image to be displayed can be QImage or QPixmap
""" """
log.debug(u'image to display') log.debug(u'image to display')
if not isinstance(image, QtGui.QImage): image = self.imageManager.get_image_bytes(name)
image = resize_image(image, self.screen[u'size'].width(),
self.screen[u'size'].height())
self.resetVideo() self.resetVideo()
self.displayImage(image) self.displayImage(image)
# show screen # show screen
if self.isLive: if self.isLive:
self.setVisible(True) self.setVisible(True)
return self.preview()
def displayImage(self, image): def displayImage(self, image):
""" """
Display an image, as is. Display an image, as is.
""" """
if image: if image:
if isinstance(image, QtGui.QImage): js = u'show_image("data:image/png;base64,%s");' % image
js = u'show_image("data:image/png;base64,%s");' % \
image_to_byte(image)
else:
js = u'show_image("data:image/png;base64,%s");' % image
else: else:
js = u'show_image("");' js = u'show_image("");'
self.frame.evaluateJavaScript(js) self.frame.evaluateJavaScript(js)
@ -396,6 +401,9 @@ class MainDisplay(DisplayWidget):
self.loaded = False self.loaded = False
self.initialFrame = False self.initialFrame = False
self.serviceItem = serviceItem self.serviceItem = serviceItem
if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.imageManager. \
get_image_bytes(self.serviceItem.themedata.theme_name)
html = build_html(self.serviceItem, self.screen, self.parent.alertTab, html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
self.isLive) self.isLive)
log.debug(u'buildHtml - pre setHtml') log.debug(u'buildHtml - pre setHtml')

View File

@ -26,6 +26,7 @@
import logging import logging
import os import os
import time
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
@ -400,6 +401,7 @@ class SlideController(QtGui.QWidget):
log.debug(u'screenSizeChanged live = %s' % self.isLive) log.debug(u'screenSizeChanged live = %s' % self.isLive)
# rebuild display as screen size changed # rebuild display as screen size changed
self.display = MainDisplay(self, self.screens, self.isLive) self.display = MainDisplay(self, self.screens, self.isLive)
self.display.imageManager = self.parent.RenderManager.image_manager
self.display.alertTab = self.alertTab self.display.alertTab = self.alertTab
self.ratio = float(self.screens.current[u'size'].width()) / \ self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height()) float(self.screens.current[u'size'].height())
@ -585,13 +587,14 @@ class SlideController(QtGui.QWidget):
label = QtGui.QLabel() label = QtGui.QLabel()
label.setMargin(4) label.setMargin(4)
label.setScaledContents(True) label.setScaledContents(True)
if isinstance(frame[u'image'], QtGui.QImage): if self.serviceItem.is_command():
label.setPixmap(QtGui.QPixmap.fromImage(frame[u'image'])) image = resize_image(frame[u'image'],
else:
pixmap = resize_image(frame[u'image'],
self.parent.RenderManager.width, self.parent.RenderManager.width,
self.parent.RenderManager.height) self.parent.RenderManager.height)
label.setPixmap(QtGui.QPixmap.fromImage(pixmap)) else:
image = self.parent.RenderManager.image_manager. \
get_image(frame[u'title'])
label.setPixmap(QtGui.QPixmap.fromImage(image))
self.PreviewListWidget.setCellWidget(framenumber, 0, label) self.PreviewListWidget.setCellWidget(framenumber, 0, label)
slideHeight = width * self.parent.RenderManager.screen_ratio slideHeight = width * self.parent.RenderManager.screen_ratio
row += 1 row += 1
@ -782,15 +785,12 @@ class SlideController(QtGui.QWidget):
[self.serviceItem, self.isLive, row]) [self.serviceItem, self.isLive, row])
self.updatePreview() self.updatePreview()
else: else:
frame, raw_html = self.serviceItem.get_rendered_frame(row) toDisplay = self.serviceItem.get_rendered_frame(row)
if self.serviceItem.is_text(): if self.serviceItem.is_text():
frame = self.display.text(raw_html) frame = self.display.text(toDisplay)
else: else:
self.display.image(frame) frame = self.display.image(toDisplay)
if isinstance(frame, QtGui.QImage): self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
else:
self.SlidePreview.setPixmap(QtGui.QPixmap(frame))
self.selectedRow = row self.selectedRow = row
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
row) row)

View File

@ -34,9 +34,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.ui import FileRenameForm, ThemeForm
from openlp.core.theme import Theme from openlp.core.theme import Theme
from openlp.core.lib import OpenLPToolbar, context_menu_action, \ from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \
ThemeXML, str_to_bool, get_text_file_string, build_icon, Receiver, \ build_icon, Receiver, SettingsManager, translate, check_item_selected
context_menu_separator, SettingsManager, translate, check_item_selected
from openlp.core.utils import AppLocation, get_filesystem_encoding from openlp.core.utils import AppLocation, get_filesystem_encoding
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -261,7 +260,7 @@ class ThemeManager(QtGui.QWidget):
os.path.split(unicode(themeData.background_filename))[1]) os.path.split(unicode(themeData.background_filename))[1])
save_from = themeData.background_filename save_from = themeData.background_filename
theme = themeData.extract_xml() theme = themeData.extract_xml()
pretty_theme =themeData.extract_formatted_xml() pretty_theme = themeData.extract_formatted_xml()
self.saveTheme(newThemeName, theme, pretty_theme, save_from, save_to) self.saveTheme(newThemeName, theme, pretty_theme, save_from, save_to)
def onEditTheme(self): def onEditTheme(self):

View File

@ -28,7 +28,6 @@ The :mod:`languagemanager` module provides all the translation settings and
language file loading for OpenLP. language file loading for OpenLP.
""" """
import logging import logging
import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui

View File

@ -32,7 +32,6 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
ItemCapabilities, translate ItemCapabilities, translate
from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.forms import BibleImportForm
from openlp.plugins.bibles.lib.db import BibleDB
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -6,8 +6,8 @@ Deut,Deuteronomy,Deut
Josh,Joshua,Josh Josh,Joshua,Josh
Judg,Judges,Judg Judg,Judges,Judg
Ruth,Ruth,Ruth Ruth,Ruth,Ruth
1Sam,1 Samual,1Sam 1Sam,1 Samuel,1Sam
2Sam,2 Samual,2Sam 2Sam,2 Samuel,2Sam
1Kgs,1 Kings,1Kgs 1Kgs,1 Kings,1Kgs
2Kgs,2 Kings,2Kgs 2Kgs,2 Kings,2Kgs
1Chr,1 Chronicles,1Chr 1Chr,1 Chronicles,1Chr

1 Gen Genesis Gen
6 Josh Joshua Josh
7 Judg Judges Judg
8 Ruth Ruth Ruth
9 1Sam 1 Samual 1 Samuel 1Sam
10 2Sam 2 Samual 2 Samuel 2Sam
11 1Kgs 1 Kings 1Kgs
12 2Kgs 2 Kings 2Kgs
13 1Chr 1 Chronicles 1Chr

View File

@ -28,7 +28,6 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate
from editcustomslidedialog import Ui_CustomSlideEditDialog from editcustomslidedialog import Ui_CustomSlideEditDialog
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -166,9 +166,8 @@ class ImageMediaItem(MediaManagerItem):
for item in items: for item in items:
bitem = self.listView.item(item.row()) bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
frame = QtGui.QImage(unicode(filename))
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
service_item.add_from_image(path, name, frame) service_item.add_from_image(filename, name)
return True return True
else: else:
return False return False
@ -185,7 +184,8 @@ class ImageMediaItem(MediaManagerItem):
for item in items: for item in items:
bitem = self.listView.item(item.row()) bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
self.parent.liveController.display.image(filename) (path, name) = os.path.split(filename)
self.parent.liveController.display.directImage(name, filename)
self.resetButton.setVisible(True) self.resetButton.setVisible(True)
def onPreviewClick(self): def onPreviewClick(self):

View File

@ -28,7 +28,6 @@ The :mod:`ewimport` module provides the functionality for importing
EasyWorship song databases into the current installation database. EasyWorship song databases into the current installation database.
""" """
import sys
import os import os
import struct import struct
@ -192,8 +191,9 @@ class EasyWorshipSongImport(SongImport):
num_fields) num_fields)
field_names.pop() field_names.pop()
field_descs = [] field_descs = []
for i,field_name in enumerate(field_names): for i, field_name in enumerate(field_names):
field_type, field_size = struct.unpack_from('BB', field_info, i * 2) field_type, field_size = struct.unpack_from('BB',
field_info, i * 2)
field_descs.append(FieldDescEntry(field_name, field_type, field_descs.append(FieldDescEntry(field_name, field_type,
field_size)) field_size))
self.set_record_struct(field_descs) self.set_record_struct(field_descs)
@ -272,7 +272,7 @@ class EasyWorshipSongImport(SongImport):
return success return success
def find_field(self, field_name): def find_field(self, field_name):
return [i for i,x in enumerate(self.field_descs) \ return [i for i, x in enumerate(self.field_descs) \
if x.name == field_name][0] if x.name == field_name][0]
def set_record_struct(self, field_descs): def set_record_struct(self, field_descs):
@ -331,7 +331,7 @@ class EasyWorshipSongImport(SongImport):
# Memo or Blob # Memo or Blob
block_start, blob_size = \ block_start, blob_size = \
struct.unpack_from('<II', field, len(field)-10) struct.unpack_from('<II', field, len(field)-10)
sub_block = block_start & 0xff; sub_block = block_start & 0xff
block_start &= ~0xff block_start &= ~0xff
self.memo_file.seek(block_start) self.memo_file.seek(block_start)
memo_block_type, = struct.unpack('b', self.memo_file.read(1)) memo_block_type, = struct.unpack('b', self.memo_file.read(1))
@ -339,12 +339,12 @@ class EasyWorshipSongImport(SongImport):
self.memo_file.seek(8, os.SEEK_CUR) self.memo_file.seek(8, os.SEEK_CUR)
elif memo_block_type == 3: elif memo_block_type == 3:
if sub_block > 63: if sub_block > 63:
return u''; return u''
self.memo_file.seek(11 + (5 * sub_block), os.SEEK_CUR) self.memo_file.seek(11 + (5 * sub_block), os.SEEK_CUR)
sub_block_start, = struct.unpack('B', self.memo_file.read(1)) sub_block_start, = struct.unpack('B', self.memo_file.read(1))
self.memo_file.seek(block_start + (sub_block_start * 16)) self.memo_file.seek(block_start + (sub_block_start * 16))
else: else:
return u''; return u''
return self.memo_file.read(blob_size) return self.memo_file.read(blob_size)
else: else:
return 0 return 0

View File

@ -29,7 +29,6 @@ The :mod:`songbeamerimport` module provides the functionality for importing
""" """
import logging import logging
import os import os
import re
import chardet import chardet
import codecs import codecs

View File

@ -6,8 +6,8 @@ Deut,Deuteronomy,Deut
Josh,Joshua,Josh Josh,Joshua,Josh
Judg,Judges,Judg Judg,Judges,Judg
Ruth,Ruth,Ruth Ruth,Ruth,Ruth
1Sam,1 Samual,1Sam 1Sam,1 Samuel,1Sam
2Sam,2 Samual,2Sam 2Sam,2 Samuel,2Sam
1Kgs,1 Kings,1Kgs 1Kgs,1 Kings,1Kgs
2Kgs,2 Kings,2Kgs 2Kgs,2 Kings,2Kgs
1Chr,1 Chronicles,1Chr 1Chr,1 Chronicles,1Chr