diff --git a/documentation/api/source/core/index.rst b/documentation/api/source/core/index.rst index 38a98ab97..8555e1ebe 100644 --- a/documentation/api/source/core/index.rst +++ b/documentation/api/source/core/index.rst @@ -3,9 +3,13 @@ :mod:`core` Module ================== +.. automodule:: openlp.core + :members: + .. toctree:: :maxdepth: 2 lib theme - + ui + utils \ No newline at end of file diff --git a/documentation/api/source/core/lib.rst b/documentation/api/source/core/lib.rst index 5fc66200d..6ca952d7d 100644 --- a/documentation/api/source/core/lib.rst +++ b/documentation/api/source/core/lib.rst @@ -1,7 +1,7 @@ .. _core-lib: -:mod:`lib` Module -================= +Object Library +============== .. automodule:: openlp.core.lib :members: diff --git a/documentation/api/source/core/ui.rst b/documentation/api/source/core/ui.rst new file mode 100644 index 000000000..63db7478e --- /dev/null +++ b/documentation/api/source/core/ui.rst @@ -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: diff --git a/documentation/api/source/core/utils.rst b/documentation/api/source/core/utils.rst new file mode 100644 index 000000000..d0c6a672b --- /dev/null +++ b/documentation/api/source/core/utils.rst @@ -0,0 +1,7 @@ +.. _core-utils: + +Utilities +========= + +.. automodule:: openlp.core.utils + :members: diff --git a/documentation/api/source/index.rst b/documentation/api/source/index.rst index cd64b13a1..e1aeebbab 100644 --- a/documentation/api/source/index.rst +++ b/documentation/api/source/index.rst @@ -15,7 +15,6 @@ Contents: .. toctree:: :maxdepth: 2 - openlp core/index plugins/index diff --git a/documentation/api/source/plugins/alerts.rst b/documentation/api/source/plugins/alerts.rst new file mode 100644 index 000000000..e7cf33d63 --- /dev/null +++ b/documentation/api/source/plugins/alerts.rst @@ -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: diff --git a/documentation/api/source/plugins/custom.rst b/documentation/api/source/plugins/custom.rst new file mode 100644 index 000000000..f50b86d41 --- /dev/null +++ b/documentation/api/source/plugins/custom.rst @@ -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: diff --git a/documentation/api/source/plugins/index.rst b/documentation/api/source/plugins/index.rst index 6c5b139d5..78126ff9e 100644 --- a/documentation/api/source/plugins/index.rst +++ b/documentation/api/source/plugins/index.rst @@ -1,7 +1,7 @@ .. _plugins-index: -:mod:`plugins` Module -===================== +Plugins +======= .. automodule:: openlp.plugins :members: @@ -14,15 +14,7 @@ presentations media images - -:mod:`custom` Plugin --------------------- - -.. automodule:: openlp.plugins.custom - :members: - -:mod:`songusage` Plugin ------------------------ - -.. automodule:: openlp.plugins.songusage - :members: + custom + remotes + songusage + alerts diff --git a/documentation/api/source/plugins/remotes.rst b/documentation/api/source/plugins/remotes.rst new file mode 100644 index 000000000..0bcd37119 --- /dev/null +++ b/documentation/api/source/plugins/remotes.rst @@ -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: diff --git a/documentation/api/source/plugins/songusage.rst b/documentation/api/source/plugins/songusage.rst new file mode 100644 index 000000000..e4804ea34 --- /dev/null +++ b/documentation/api/source/plugins/songusage.rst @@ -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: diff --git a/documentation/manual/source/dualmonitors.rst b/documentation/manual/source/dualmonitors.rst index 353d7482b..7e5fdc19b 100644 --- a/documentation/manual/source/dualmonitors.rst +++ b/documentation/manual/source/dualmonitors.rst @@ -3,7 +3,7 @@ Dual Monitor Setup ================== 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. 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 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 -monitors. Sometimes with older laptops a key stroke generally involving the FN -key and another key is required to enable the second monitor on laptops. +of outputs pictured above since your laptops screen serves as one of the +monitors. Sometimes with older laptops a key stroke generally involving the +: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 projector setup as the second monitor. With the option of extending your @@ -39,49 +41,47 @@ next. Windows 7 ^^^^^^^^^ -Windows 7 has using a projector in mind. Simply connect your projector and -press the **Windows key and tap P**. +Windows 7 has using a projector in mind. Simply connect your projector and +press :kbd:`Windows+P`. -The more traditional way is also fairly straight forward. Go to the control -panel and click on display. This will open up the Display options. You can -also bypass this step by right click on a blank area on your desktop and -selecting **resolution**. +The more traditional way is also fairly straight forward. Go to +:guilabel:`Control Panel` and click on :guilabel:`Display`. This will open up +the :guilabel:`Display` dialog. You can also bypass this step by right click on +a blank area on your desktop and selecting :guilabel:`Resolution`. .. 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 -Then enable your projector and ensure your desktop is extended. - Windows Vista ^^^^^^^^^^^^^ -From the control panel click on personalize, or right click a blank place on -the desktop and click personalization. +From :guilabel:`Control Panel` click on :guilabel:`Personalize`, or right click +a blank place on the desktop and click :guilabel:`Personalization`. .. 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 -Then enable the montior that represents your projector an make sure your -you have checked Extend the desktop. - Windows XP ^^^^^^^^^^ -From the control panel select Display, or right click on a blank area of the -desktop and select properties. From the properties window click on the settings -tab. +From :guilabel:`Control Panel` select :guilabel:`Display`, or right click on a +blank area of the desktop and select :guilabel:`Properties`. From the +: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 -Then enable the monitor that represents your projector an make sure your -you have checked Extend the desktop. - 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 work. -GNOME +GNOME ^^^^^ 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 -Setup your projector with the correct resolution and make sure you do **not** -have mirrored desktop enabled (same image on all monitors). - KDE ^^^ 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 @@ -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 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. diff --git a/documentation/manual/source/pics/nvlinux1.png b/documentation/manual/source/pics/nvlinux1.png new file mode 100644 index 000000000..6c585bae4 Binary files /dev/null and b/documentation/manual/source/pics/nvlinux1.png differ diff --git a/documentation/manual/source/pics/twinview.png b/documentation/manual/source/pics/twinview.png new file mode 100644 index 000000000..d8a659f53 Binary files /dev/null and b/documentation/manual/source/pics/twinview.png differ diff --git a/documentation/manual/source/pics/xorgwrite.png b/documentation/manual/source/pics/xorgwrite.png new file mode 100644 index 000000000..812b9e0ae Binary files /dev/null and b/documentation/manual/source/pics/xorgwrite.png differ diff --git a/documentation/manual/source/pics/xpdisplaysettings.png b/documentation/manual/source/pics/xpdisplaysettings.png index e1ec66c6f..eb7a8921c 100644 Binary files a/documentation/manual/source/pics/xpdisplaysettings.png and b/documentation/manual/source/pics/xpdisplaysettings.png differ diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index bc05c7ba6..452d968b8 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -316,6 +316,7 @@ from theme import ThemeLevel, ThemeXML, BackgroundGradientType, BackgroundType, HorizontalType, VerticalType from spelltextedit import SpellTextEdit from eventreceiver import Receiver +from imagemanager import ImageManager from settingsmanager import SettingsManager from plugin import PluginStatus, StringContent, Plugin from pluginmanager import PluginManager diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index d4de27bb4..b2f46e655 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -331,6 +331,7 @@ def build_html(item, screen, alert, islive): height = screen[u'size'].height() theme = item.themedata webkitvers = webkit_version() + # Image generated and poked in if item.bg_image_bytes: image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes else: diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py new file mode 100644 index 000000000..0e0660bda --- /dev/null +++ b/openlp/core/lib/imagemanager.py @@ -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 diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index ed380f71d..9776efb83 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -51,11 +51,6 @@ class Renderer(object): self._rect = None self.theme_name = 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): """ @@ -66,14 +61,7 @@ class Renderer(object): """ log.debug(u'set 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 - 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): """ @@ -105,39 +93,6 @@ class Renderer(object): (build_lyrics_format_css(self._theme, self.page_width, 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): """ Figure out how much text can appear on a slide, using the current diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index ec6a7f8cb..bf561b4b3 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -28,7 +28,7 @@ import logging 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 log = logging.getLogger(__name__) @@ -56,7 +56,9 @@ class RenderManager(object): """ log.debug(u'Initilisation started') self.screens = screens + self.image_manager = ImageManager() self.display = MainDisplay(self, screens, False) + self.display.imageManager = self.image_manager self.display.setup() self.theme_manager = theme_manager self.renderer = Renderer() @@ -75,9 +77,11 @@ class RenderManager(object): log.debug(u'Update Display') self.calculate_default(self.screens.current[u'size']) self.display = MainDisplay(self, self.screens, False) + self.display.imageManager = self.image_manager self.display.setup() self.renderer.bg_frame = None self.themedata = None + self.image_manager.update_display(self.width, self.height) 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.renderer.set_theme(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 def build_text_rectangle(self, theme): @@ -211,7 +216,7 @@ class RenderManager(object): serviceItem.raw_footer = footer serviceItem.render(True) 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) # Reset the real screen size for subsequent render requests self.calculate_default(self.screens.current[u'size']) diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index a5417916e..9ca0ed6cb 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -30,7 +30,6 @@ type and capability of an item. import logging import os -import time import uuid from PyQt4 import QtGui @@ -160,12 +159,10 @@ class ServiceItem(object): theme = self.theme self.main, self.footer = \ 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 if self.service_item_type == ServiceItemType.Text: log.debug(u'Formatting slides') for slide in self._raw_frames: - before = time.time() formatted = self.render_manager \ .format_slide(slide[u'raw_slide'], line_break) for page in formatted: @@ -174,12 +171,8 @@ class ServiceItem(object): u'text': clean_tags(page.rstrip()), u'html': expand_tags(page.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'] = resize_image(slide[u'image'], - self.render_manager.width, self.render_manager.height) - elif self.service_item_type == ServiceItemType.Command: + elif self.service_item_type == ServiceItemType.Image or \ + self.service_item_type == ServiceItemType.Command: pass else: log.error(u'Invalid value renderer :%s' % self.service_item_type) @@ -192,7 +185,7 @@ class ServiceItem(object): else: self.foot_text = u'%s
%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. @@ -201,13 +194,11 @@ class ServiceItem(object): ``title`` A title for the slide in the service item. - - ``image`` - The actual image file name. """ self.service_item_type = ServiceItemType.Image 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() 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._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() def get_service_repr(self): @@ -310,8 +301,7 @@ class ServiceItem(object): elif self.service_item_type == ServiceItemType.Image: for text_image in serviceitem[u'serviceitem'][u'data']: filename = os.path.join(path, text_image) - real_image = QtGui.QImage(unicode(filename)) - self.add_from_image(path, text_image, real_image) + self.add_from_image(filename, text_image) elif self.service_item_type == ServiceItemType.Command: for text_image in serviceitem[u'serviceitem'][u'data']: filename = os.path.join(path, text_image[u'title']) @@ -387,9 +377,11 @@ class ServiceItem(object): renders it if required. """ 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: - return self._raw_frames[row][u'image'], u'' + return self._raw_frames[row][u'image'] def get_frame_title(self, row=0): """ diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 07e8ad728..603197c07 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -25,7 +25,6 @@ ############################################################################### import re -import sys try: import enchant from enchant import DictNotFoundError @@ -37,7 +36,7 @@ except ImportError: # http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/ 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): def __init__(self, *args): diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index 99b9d4732..adeb116d9 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -157,12 +157,12 @@ class VerticalType(object): Middle = 1 Bottom = 2 -boolean_list = [u'bold', u'italics', u'override', u'outline', u'shadow', \ -u'slide_transition'] +boolean_list = [u'italics', u'override', u'outline', u'shadow', + u'slide_transition'] -integer_list =[u'size', u'line_adjustment', u'x', u'height', u'y', \ -u'width', u'shadow_size', u'outline_size', u'horizontal_align', \ -u'vertical_align'] +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'vertical_align', u'wrap_style'] class ThemeXML(object): """ diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index df7736faf..0b6abc0cd 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -40,7 +40,6 @@ class HideMode(object): from themeform import ThemeForm from filerenameform import FileRenameForm from maindisplay import MainDisplay -from slidecontroller import HideMode from servicenoteform import ServiceNoteForm from serviceitemeditform import ServiceItemEditForm from screen import ScreenList diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index 8c344e662..b40c9e063 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -24,7 +24,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from exceptiondialog import Ui_ExceptionDialog diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py index d1c339811..2a7f7bd7d 100644 --- a/openlp/core/ui/filerenameform.py +++ b/openlp/core/ui/filerenameform.py @@ -27,7 +27,6 @@ from PyQt4 import QtCore, QtGui from filerenamedialog import Ui_FileRenameDialog -from openlp.core.lib import translate class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): """ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index d8dabd315..2da71e6ef 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -90,6 +90,9 @@ class DisplayWidget(QtGui.QGraphicsView): event.ignore() class MainDisplay(DisplayWidget): + """ + This is the display screen. + """ def __init__(self, parent, screens, live): DisplayWidget.__init__(self, live, parent=None) @@ -222,7 +225,14 @@ class MainDisplay(DisplayWidget): shrinkItem.resize(self.screen[u'size'].width(), 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 bytestream on route. @@ -231,25 +241,20 @@ class MainDisplay(DisplayWidget): The Image to be displayed can be QImage or QPixmap """ log.debug(u'image to display') - if not isinstance(image, QtGui.QImage): - image = resize_image(image, self.screen[u'size'].width(), - self.screen[u'size'].height()) + image = self.imageManager.get_image_bytes(name) self.resetVideo() self.displayImage(image) # show screen if self.isLive: self.setVisible(True) + return self.preview() def displayImage(self, image): """ Display an image, as is. """ if image: - if isinstance(image, QtGui.QImage): - js = u'show_image("data:image/png;base64,%s");' % \ - image_to_byte(image) - else: - js = u'show_image("data:image/png;base64,%s");' % image + js = u'show_image("data:image/png;base64,%s");' % image else: js = u'show_image("");' self.frame.evaluateJavaScript(js) @@ -396,6 +401,9 @@ class MainDisplay(DisplayWidget): self.loaded = False self.initialFrame = False 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, self.isLive) log.debug(u'buildHtml - pre setHtml') diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 78ac70b86..4aaa1a5ca 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -26,6 +26,7 @@ import logging import os +import time from PyQt4 import QtCore, QtGui from PyQt4.phonon import Phonon @@ -400,6 +401,7 @@ class SlideController(QtGui.QWidget): log.debug(u'screenSizeChanged live = %s' % self.isLive) # rebuild display as screen size changed self.display = MainDisplay(self, self.screens, self.isLive) + self.display.imageManager = self.parent.RenderManager.image_manager self.display.alertTab = self.alertTab self.ratio = float(self.screens.current[u'size'].width()) / \ float(self.screens.current[u'size'].height()) @@ -585,13 +587,14 @@ class SlideController(QtGui.QWidget): label = QtGui.QLabel() label.setMargin(4) label.setScaledContents(True) - if isinstance(frame[u'image'], QtGui.QImage): - label.setPixmap(QtGui.QPixmap.fromImage(frame[u'image'])) - else: - pixmap = resize_image(frame[u'image'], + if self.serviceItem.is_command(): + image = resize_image(frame[u'image'], self.parent.RenderManager.width, 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) slideHeight = width * self.parent.RenderManager.screen_ratio row += 1 @@ -782,15 +785,12 @@ class SlideController(QtGui.QWidget): [self.serviceItem, self.isLive, row]) self.updatePreview() else: - frame, raw_html = self.serviceItem.get_rendered_frame(row) + toDisplay = self.serviceItem.get_rendered_frame(row) if self.serviceItem.is_text(): - frame = self.display.text(raw_html) + frame = self.display.text(toDisplay) else: - self.display.image(frame) - if isinstance(frame, QtGui.QImage): - self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) - else: - self.SlidePreview.setPixmap(QtGui.QPixmap(frame)) + frame = self.display.image(toDisplay) + self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) self.selectedRow = row Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index e09be7c27..debbcb582 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -34,9 +34,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.theme import Theme -from openlp.core.lib import OpenLPToolbar, context_menu_action, \ - ThemeXML, str_to_bool, get_text_file_string, build_icon, Receiver, \ - context_menu_separator, SettingsManager, translate, check_item_selected +from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ + build_icon, Receiver, SettingsManager, translate, check_item_selected from openlp.core.utils import AppLocation, get_filesystem_encoding log = logging.getLogger(__name__) @@ -261,7 +260,7 @@ class ThemeManager(QtGui.QWidget): os.path.split(unicode(themeData.background_filename))[1]) save_from = themeData.background_filename 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) def onEditTheme(self): diff --git a/openlp/core/utils/languagemanager.py b/openlp/core/utils/languagemanager.py index 000328d50..187834beb 100644 --- a/openlp/core/utils/languagemanager.py +++ b/openlp/core/utils/languagemanager.py @@ -28,7 +28,6 @@ The :mod:`languagemanager` module provides all the translation settings and language file loading for OpenLP. """ import logging -import os from PyQt4 import QtCore, QtGui diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index d38967e64..bb3c1b26d 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -32,7 +32,6 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ ItemCapabilities, translate from openlp.plugins.bibles.forms import BibleImportForm -from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) diff --git a/openlp/plugins/bibles/resources/osisbooks.csv b/openlp/plugins/bibles/resources/osisbooks.csv index 2207ee553..d65e89297 100644 --- a/openlp/plugins/bibles/resources/osisbooks.csv +++ b/openlp/plugins/bibles/resources/osisbooks.csv @@ -6,8 +6,8 @@ Deut,Deuteronomy,Deut Josh,Joshua,Josh Judg,Judges,Judg Ruth,Ruth,Ruth -1Sam,1 Samual,1Sam -2Sam,2 Samual,2Sam +1Sam,1 Samuel,1Sam +2Sam,2 Samuel,2Sam 1Kgs,1 Kings,1Kgs 2Kgs,2 Kings,2Kgs 1Chr,1 Chronicles,1Chr diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index ff396658f..5f535c8bc 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -28,7 +28,6 @@ import logging from PyQt4 import QtCore, QtGui -from openlp.core.lib import Receiver, translate from editcustomslidedialog import Ui_CustomSlideEditDialog log = logging.getLogger(__name__) diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 5a3918dd9..71dbd8903 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -166,9 +166,8 @@ class ImageMediaItem(MediaManagerItem): for item in items: bitem = self.listView.item(item.row()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) - frame = QtGui.QImage(unicode(filename)) (path, name) = os.path.split(filename) - service_item.add_from_image(path, name, frame) + service_item.add_from_image(filename, name) return True else: return False @@ -185,7 +184,8 @@ class ImageMediaItem(MediaManagerItem): for item in items: bitem = self.listView.item(item.row()) 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) def onPreviewClick(self): diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 4188304cd..cb360cf59 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -28,7 +28,6 @@ The :mod:`ewimport` module provides the functionality for importing EasyWorship song databases into the current installation database. """ -import sys import os import struct @@ -192,8 +191,9 @@ class EasyWorshipSongImport(SongImport): num_fields) field_names.pop() field_descs = [] - for i,field_name in enumerate(field_names): - field_type, field_size = struct.unpack_from('BB', field_info, i * 2) + for i, field_name in enumerate(field_names): + field_type, field_size = struct.unpack_from('BB', + field_info, i * 2) field_descs.append(FieldDescEntry(field_name, field_type, field_size)) self.set_record_struct(field_descs) @@ -272,7 +272,7 @@ class EasyWorshipSongImport(SongImport): return success 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] def set_record_struct(self, field_descs): @@ -331,7 +331,7 @@ class EasyWorshipSongImport(SongImport): # Memo or Blob block_start, blob_size = \ struct.unpack_from(' 63: - return u''; + return u'' self.memo_file.seek(11 + (5 * sub_block), os.SEEK_CUR) sub_block_start, = struct.unpack('B', self.memo_file.read(1)) self.memo_file.seek(block_start + (sub_block_start * 16)) else: - return u''; + return u'' return self.memo_file.read(blob_size) else: return 0 diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 505e99a46..8b07d2b32 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -29,7 +29,6 @@ The :mod:`songbeamerimport` module provides the functionality for importing """ import logging import os -import re import chardet import codecs diff --git a/resources/bibles/osisbooks_en.txt b/resources/bibles/osisbooks_en.txt index 2207ee553..d65e89297 100644 --- a/resources/bibles/osisbooks_en.txt +++ b/resources/bibles/osisbooks_en.txt @@ -6,8 +6,8 @@ Deut,Deuteronomy,Deut Josh,Joshua,Josh Judg,Judges,Judg Ruth,Ruth,Ruth -1Sam,1 Samual,1Sam -2Sam,2 Samual,2Sam +1Sam,1 Samuel,1Sam +2Sam,2 Samuel,2Sam 1Kgs,1 Kings,1Kgs 2Kgs,2 Kings,2Kgs 1Chr,1 Chronicles,1Chr