This commit is contained in:
Andreas Preikschat 2011-04-29 13:18:52 +02:00
commit 0355db290b
105 changed files with 1904 additions and 1357 deletions

View File

@ -21,20 +21,35 @@ You will see the Bible Importer window, click :guilabel:`Next`.
.. image:: pics/bibleimport01.png .. image:: pics/bibleimport01.png
After clicking :guilabel:`Next` you can select from the various types of After clicking :guilabel:`Next` you can select from the various types of
software that OpenLP will convert Bibles from. software that OpenLP will convert Bibles from. Click on the file folder icon to
choose the file(s) of the Bible database you want to import. See the sections
below for more information on the different formats that OpenLP will import.
Click :guilabel:`Next` to continue.
.. image:: pics/bibleimport02.png .. image:: pics/bibleimport02.png
Click on the file folder icon to choose the file of the Bible database you After selecting your file(s), you'll be asked to fill in the details of the
want to import. See the following sections for information on the different Bible you are importing. Remember to check what information you need to display
formats that OpenLP will import. for your Bible's translation, as some of them have strict rules around the
copyright notice. Click :guilabel:`Next` to continue.
Importing from OpenLP Version 1 .. image:: pics/bibleimportdetails1.png
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Converting from OpenLP Version 1 is a simple process. First you will need to After filling in the copyright details, OpenLP will start to import your Bible.
locate your Version 1 Bibles. It may take some time to import your Bible so please be patient.
.. image:: pics/bibleimportfinished1.png
When the import has finished click :guilabel:`Finish` and you should be
ready to use your Bible in OpenLP.
Importing from openlp.org 1.x
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Importing Bibles from openlp.org 1.x is a simple process. First you will need to
locate your version 1.x Bibles. Version 1.x Bibles have the `.bible` file
extension.
Windows XP:: Windows XP::
@ -44,22 +59,15 @@ Windows Vista / Windows 7::
C:\ProgramData\openlp.org\Data\Bibles\ C:\ProgramData\openlp.org\Data\Bibles\
OpenLP Version 1 Bibles have the `.bible` file extension. After selecting After selecting all of the openlp.org 1.x Bibles you want to convert, click
all of the OpenLP Version 1 Bibles you want to convert, click :guilabel:`Next` :guilabel:`Next` to continue the import process.
.. image:: pics/bibleimportdetails1.png
Enter your Bible name and copyright details. Click :guilabel:`Next`. It may
take some time to convert your Bibles so please be patient.
.. image:: pics/bibleimportfinished1.png
When the import has finished click :guilabel:`Finish` and you should be
ready to use your OpenLP Version 1 Bibles.
Importing OSIS Bibles Importing OSIS Bibles
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
Importing OSIS files is very simple. Select OSIS as your import source, select
your OSIS Bible file and continue the import process.
**About OSIS Formatted Bibles** **About OSIS Formatted Bibles**
The OSIS XML standard was designed to provide a common format for distribution The OSIS XML standard was designed to provide a common format for distribution
@ -69,24 +77,11 @@ of electronic Bibles. More information can be found out at the `Bible Technologi
If you have any software installed that is part of the `Sword Project If you have any software installed that is part of the `Sword Project
<http://www.crosswire.org/sword/index.jsp>`_ it can be easily converted. <http://www.crosswire.org/sword/index.jsp>`_ it can be easily converted.
Importing OSIS files is very simple. Select your OSIS Bible file and click
:guilabel:`Next`
.. image:: pics/bibleimportdetails1.png
Enter you Bible name and copyright details. Click :guilabel:`Next`. It may take
some time to convert your Bibles so please be patient.
.. image:: pics/bibleimportfinished1.png
Click :guilabel:`Finish` and you should be ready to use your OpenLP Version
1 Bibles.
You can use the commands below convert Bibles from that software to OSIS format. You can use the commands below convert Bibles from that software to OSIS format.
The following commands are used in all platforms and the commands are case The following commands are used in all platforms and the commands are case
sensitive across all platforms. To convert a Bible using Command Prompt in sensitive across all platforms. To convert a Bible using the command prompt in
Windows or a Terminal in Linux or MAC you would type:: Windows or a terminal in Linux or Mac OS X you would type::
mod2osis biblename > biblename.osis mod2osis biblename > biblename.osis
@ -114,17 +109,9 @@ You may also import downloaded bibles from OpenSong. The process is the same,
except you will need to extract the bible from a zip file. This is usually done except you will need to extract the bible from a zip file. This is usually done
by right clicking on the downloaded file and select `Extract` or `Extract Here`. by right clicking on the downloaded file and select `Extract` or `Extract Here`.
After selecting the OpenSong Bibles you want to convert, click :guilabel:`Next` After selecting the OpenSong Bibles you want to import, follow the rest of the
import process. When the import has finished you should be ready to use your
.. image:: pics/bibleimportdetails1.png OpenSong Bibles.
Enter your Bible name and copyright details. Click :guilabel:`Next`. It may
take some time to convert your Bibles so please be patient.
.. image:: pics/bibleimportfinished1.png
When the import has finished then click :guilabel:`Finish` and you should now be
ready to use your OpenSong Bibles.
Importing Web Download Bibles Importing Web Download Bibles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -139,8 +126,6 @@ as another option and does require an internet connection.
To use the web download feature select web download from the import wizard. To use the web download feature select web download from the import wizard.
.. image:: pics/bibleimport01.png
You can select from several options of location to download from and also You can select from several options of location to download from and also
what Bible translation you need. You will probably want to choose the location what Bible translation you need. You will probably want to choose the location
from where you get the best performance or has the translation you need. from where you get the best performance or has the translation you need.
@ -154,30 +139,20 @@ not be needed.
.. image:: pics/webbibleproxy1.png .. image:: pics/webbibleproxy1.png
After selecting your download location and the Bible you wish to use, click After selecting your download location and the Bible you wish to use, click
:guilabel:`Next` When your import is completed click :guilabel:`Finish` :guilabel:`Next` to continue the import process. When your import is completed
you should now be ready to use the web bible.
.. image:: pics/biblewebcomplete.png
You should now be ready to use the web bible.
Importing CSV formatted Bibles Importing CSV formatted Bibles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you have a Bible in .csv format OpenLP can import it. CSV Bibles will If you have a Bible in .csv format OpenLP can import it. CSV Bibles will
consist of two files a `books` file and a `verse` file. consist of two files a `books` file and a `verse` file. Select CSV from the list
of Bible types to import.
Select CSV from the list of Bible types to import.
.. image:: pics/bibleimport02.png
You are now ready to select your .csv files. You will need to select both your You are now ready to select your .csv files. You will need to select both your
books and verse file location. books and verse file location.
.. image:: pics/csvimport1.png .. image:: pics/csvimport1.png
After you have selected the file locations you can click :guilabel:`Next` After you have selected the file locations you can continue with the import
process. Once it is complete you should be ready to use your imported CSV Bible.
.. image:: pics/bibleimportfinished1.png
Click :guilabel:`Finish` and you should now be ready to use your imported CSV
Bible

View File

@ -1,3 +1,5 @@
.. _dualmonitors:
================== ==================
Dual Monitor Setup Dual Monitor Setup
================== ==================
@ -32,6 +34,14 @@ projector hooked up to your computer as the second monitor. With the option of
extending your desktop across the second monitor, or your operating system's extending your desktop across the second monitor, or your operating system's
equivalent. equivalent.
**Special Note For Projectors Using USB Connections**
Users have reported experiencing difficulties when using a projector with a USB
connection, as third party software is often required to properly configure
dual monitors. If possible, it is best to use a direct output (VGA, DVI, HDMI,
S-Video) from your machine's video card. If a USB connection is your only option
please consult the manufacturer's manual for instructions on a proper setup.
Microsoft Windows Microsoft Windows
----------------- -----------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -99,4 +99,134 @@ completed.
Press :guilabel:`Finish` and OpenLP will be ready to use your songs imported Press :guilabel:`Finish` and OpenLP will be ready to use your songs imported
from CCLI SongSelect. from CCLI SongSelect.
Creating or editing a song slide
================================
If you want to create a new song slide or, once you have a song imported, you
want to edit and rearrange the Title & Lyrics, Author, Topics & Song Book,
assign a Theme, or edit Copyright Info & Comments, you will do this through the
`Song Editor`.
**Edit:** To edit an existing song you can either click on a song in the
`Media Manager` and then click the button to :guilabel:`Edit the selected song`
or right click a song from either the `Media Manager` or additionally from the
`Service Manager` and click :guilabel:`Edit item`. If you are adding a new song
click :guilabel:`Add a new Song` in the `Media Manager`.
.. image:: pics/song_edit_lyrics.png
**Title:** This is where you would name your song or edit a song name.
**Alternate title:**Alternate Title was for songs with two names
"Lord the Light" - "Shine Jesus Shine". You can also add a name in this box that
will bring up the song in Titles search. **Example:** You could use an alternate
title of "hymn" on all your hymn song titles for grouping. When you search "hymn"
it will show all the hymns that have "hymn" for the Alternate title.
**Lyrics:** The *Lyrics* window shows all lyrics imported or added. On the left
side of the lyrics you will see a capital letter followed by a number. A V1
would represent verse 1, C1 would be Chorus 1. You will use these letters and
numbers for the order to display the lyrics.
**Verse Order:** After you entered or edited your song, you will want OpenLP to
display the verses in the correct order you want them displayed. On the left side
of your lyrics you will see C1, V1, V2 etc. the way they were imported or added.
To put your lyrics in the correct order is as simple as typing in the
:guilabel:`Verse order box` at the bottom, the correct order you want them
displayed, with only a blank space in between each entry. The correct format will
look like this: V1 C1 V2 C1 V3 C1. If you forget to put a space in between the
order, or if you do not have the corresponding verse number, OpenLP will politely
tell you with a pop-up error message what is wrong so you can correct your
mistake and save it. Verse order is optional and if left blank the verses will
display in the order seen in *Lyrics*.
.. image:: pics/song_edit_verse_error.png
Adding or editing the lyrics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
**Add:** To Add a new verse, click on :guilabel:`Add`. The main window is where
you will type your lyrics. OpenLP is packaged with a spell checker for most
languages. If you misspell a word it will be underlined. Right click the
underlined word and left click *Spelling Suggestions* or you can ignore it and
continue typing. You also have the ability to format the font using *Formatting
Tags*. Highlight the word/words you want to format and right click the highlight.
Left click *Formatting Tags* and choose the format you want to apply to the font
and the format tags will be entered with your lyrics. These tags are not visible
when displayed. To remove the format, delete the tag on each end of the word or
sentence.
**Edit:** To edit an existing verse, click on the verse you wish to *Edit* then click on
:guilabel:`Edit`, make your changes and click :guilabel:`Save`.
**Edit All:** To edit the whole song at once, click on :guilabel:`Edit All`.
**Delete:** To delete a verse, click on the verse you want to delete and it will
highlight, click on the :guilabel:`Delete` button and it will be deleted.
**Warning:**, once you click the :guilabel:`Delete` button, you will not be
asked again, it will be deleted immediately.
.. image:: pics/song_edit_verse_type.png
**Verse type:** gives you 7 ways to classify your lyrics. Verse, Chorus, Bridge,
Pre-Chorus, Intro, Ending, Other.
If you have more than one verse, you would number them Verse 1, 2, 3 as needed.
If you find the verse has too many lines for your screen, you can edit and
shorten the verse and :guilabel:`Add` another slide.
Authors, Topics & Song Book
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Once your *Title & Lyrics* are added or edited the way you want them you must
add or enter the author or authors of the song. OpenLP requires all songs to
have an author entered. You can add a blank space for the author name.
.. image:: pics/song_edit_authors.png
**Authors:** Click the drop down arrow to view all authors or start typing a name
in the box and a list will appear. If the authors name has not been added, type
the authors name in the box and click :guilabel:`Add to Song`. The authors name
will appear below and will also be added to your database. If you accidently add
the wrong author you can click on the authors name and click :guilabel:`Remove`.
:guilabel:`Manage Authors, Topics, Song Books`: Clicking this button will bring
up your complete list of authors.
.. image:: pics/song_edit_maintenance.png
**Add:** Clicking the :guilabel:`Add` button will bring up a box where you will
add the Authors First name, Last name and Display name. Click :guilabel:`Save`
when you are finished.
.. image:: pics/song_edit_author_maintenance.png
**Edit:** The :guilabel:`Edit` button will bring up window where you can edit
the info that is already there.
**Delete:** The :guilabel:`Delete` button will remove the author you have
highlighted. Note: You cannot delete an author that is assigned to a song.
Authors names are displayed in the footer.
Theme, Copyright info & Comments
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On this tab you can assign a *Theme* to a song, enter the *Copyright information*
and add the *CCLI number*. If you imported a song from SongSelect this
information will usually be entered.
.. image:: pics/song_edit_theme_copyright.png
**Theme:** Click the drop down arrow to display your list of themes or start
typing a theme name in the box and the list will appear. You can also create a
new theme by clicking the :guilabel:`New Theme` button.
**Copyright information:** Add or edit the copyright information in this box. If
you would like to use the © symbol click "guilabel:`©` button. This information
is displayed in the footer.
**CCLI number:** Enter the CCLI number in this box. Note: this is the CCLI number
of the song, not your contract number. This number is not displayed in the footer
**Comments:** You can add comments in this box. This information is not
dispayed in the footer.

View File

@ -175,3 +175,23 @@ only download the section you search for. If you do not have an internet
connection where you intend to use OpenLP you will need another scripture connection where you intend to use OpenLP you will need another scripture
source. For more information about acquiring Bibles please see :ref:`bibleimporter`. source. For more information about acquiring Bibles please see :ref:`bibleimporter`.
OpenLP is using a large amount of RAM when showing a presentation
-----------------------------------------------------------------
OpenLP uses a large amount of RAM when showing a presentation due to the way it
handles presentations. OpenLP itself is unable to show those presentations or
load the presentation files, so it interacts with the presentation through
either Microsoft PowerPoint or LibreOffice Impress. In order to show the slides
in the slide controller, OpenLP requests that the presentation application
export the slides to images, and then uses those images as slides. This results
in a large amount of RAM being used, especially in presentations with more than
about 20 slides.
OpenLP is not displaying correctly, or is not on the correct screen
-------------------------------------------------------------------
Please read the documentation on :ref:`dualmonitors`. It is very important to
have dual monitors setup properly for OpenLP to function as expected.

View File

@ -140,7 +140,7 @@ class OpenLP(QtGui.QApplication):
self.sharedMemory = QtCore.QSharedMemory('OpenLP') self.sharedMemory = QtCore.QSharedMemory('OpenLP')
if self.sharedMemory.attach(): if self.sharedMemory.attach():
status = QtGui.QMessageBox.critical(None, status = QtGui.QMessageBox.critical(None,
UiStrings.Error, UiStrings.OpenLPStart, UiStrings().Error, UiStrings().OpenLPStart,
QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
if status == QtGui.QMessageBox.No: if status == QtGui.QMessageBox.No:
@ -250,4 +250,4 @@ if __name__ == u'__main__':
""" """
Instantiate and run the application. Instantiate and run the application.
""" """
main() main()

View File

@ -289,6 +289,5 @@ from htmlbuilder import build_html, build_lyrics_format_css, \
from toolbar import OpenLPToolbar from toolbar import OpenLPToolbar
from dockwidget import OpenLPDockWidget from dockwidget import OpenLPDockWidget
from renderer import Renderer from renderer import Renderer
from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem from mediamanageritem import MediaManagerItem
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList

View File

@ -435,7 +435,7 @@ class MediaManagerItem(QtGui.QWidget):
item to the preview slide controller. item to the preview slide controller.
""" """
if not self.listView.selectedIndexes() and not self.remoteTriggered: if not self.listView.selectedIndexes() and not self.remoteTriggered:
QtGui.QMessageBox.information(self, UiStrings.NISp, QtGui.QMessageBox.information(self, UiStrings().NISp,
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select one or more items to preview.')) 'You must select one or more items to preview.'))
else: else:
@ -453,7 +453,7 @@ class MediaManagerItem(QtGui.QWidget):
item to the live slide controller. item to the live slide controller.
""" """
if not self.listView.selectedIndexes(): if not self.listView.selectedIndexes():
QtGui.QMessageBox.information(self, UiStrings.NISp, QtGui.QMessageBox.information(self, UiStrings().NISp,
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select one or more items to send live.')) 'You must select one or more items to send live.'))
else: else:
@ -468,7 +468,7 @@ class MediaManagerItem(QtGui.QWidget):
Add a selected item to the current service Add a selected item to the current service
""" """
if not self.listView.selectedIndexes() and not self.remoteTriggered: if not self.listView.selectedIndexes() and not self.remoteTriggered:
QtGui.QMessageBox.information(self, UiStrings.NISp, QtGui.QMessageBox.information(self, UiStrings().NISp,
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select one or more items.')) 'You must select one or more items.'))
else: else:
@ -494,14 +494,14 @@ class MediaManagerItem(QtGui.QWidget):
Add a selected item to an existing item in the current service. Add a selected item to an existing item in the current service.
""" """
if not self.listView.selectedIndexes() and not self.remoteTriggered: if not self.listView.selectedIndexes() and not self.remoteTriggered:
QtGui.QMessageBox.information(self, UiStrings.NISp, QtGui.QMessageBox.information(self, UiStrings().NISp,
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select one or more items.')) 'You must select one or more items.'))
else: else:
log.debug(u'%s Add requested', self.plugin.name) log.debug(u'%s Add requested', self.plugin.name)
serviceItem = self.parent.serviceManager.getServiceItem() serviceItem = self.parent.serviceManager.getServiceItem()
if not serviceItem: if not serviceItem:
QtGui.QMessageBox.information(self, UiStrings.NISs, QtGui.QMessageBox.information(self, UiStrings().NISs,
translate('OpenLP.MediaManagerItem', translate('OpenLP.MediaManagerItem',
'You must select an existing service item to add to.')) 'You must select an existing service item to add to.'))
elif self.plugin.name.lower() == serviceItem.name.lower(): elif self.plugin.name.lower() == serviceItem.name.lower():
@ -554,4 +554,4 @@ class MediaManagerItem(QtGui.QWidget):
item_id = remoteItem item_id = remoteItem
else: else:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
return item_id return item_id

View File

@ -161,7 +161,7 @@ class Plugin(QtCore.QObject):
self.log = logging.getLogger(self.name) self.log = logging.getLogger(self.name)
self.previewController = plugin_helpers[u'preview'] self.previewController = plugin_helpers[u'preview']
self.liveController = plugin_helpers[u'live'] self.liveController = plugin_helpers[u'live']
self.renderManager = plugin_helpers[u'render'] self.renderer = plugin_helpers[u'renderer']
self.serviceManager = plugin_helpers[u'service'] self.serviceManager = plugin_helpers[u'service']
self.settingsForm = plugin_helpers[u'settings form'] self.settingsForm = plugin_helpers[u'settings form']
self.mediadock = plugin_helpers[u'toolbox'] self.mediadock = plugin_helpers[u'toolbox']
@ -330,28 +330,28 @@ class Plugin(QtCore.QObject):
""" """
## Load Action ## ## Load Action ##
self.__setNameTextString(StringContent.Load, self.__setNameTextString(StringContent.Load,
UiStrings.Load, tooltips[u'load']) UiStrings().Load, tooltips[u'load'])
## Import Action ## ## Import Action ##
self.__setNameTextString(StringContent.Import, self.__setNameTextString(StringContent.Import,
UiStrings.Import, tooltips[u'import']) UiStrings().Import, tooltips[u'import'])
## New Action ## ## New Action ##
self.__setNameTextString(StringContent.New, self.__setNameTextString(StringContent.New,
UiStrings.Add, tooltips[u'new']) UiStrings().Add, tooltips[u'new'])
## Edit Action ## ## Edit Action ##
self.__setNameTextString(StringContent.Edit, self.__setNameTextString(StringContent.Edit,
UiStrings.Edit, tooltips[u'edit']) UiStrings().Edit, tooltips[u'edit'])
## Delete Action ## ## Delete Action ##
self.__setNameTextString(StringContent.Delete, self.__setNameTextString(StringContent.Delete,
UiStrings.Delete, tooltips[u'delete']) UiStrings().Delete, tooltips[u'delete'])
## Preview Action ## ## Preview Action ##
self.__setNameTextString(StringContent.Preview, self.__setNameTextString(StringContent.Preview,
UiStrings.Preview, tooltips[u'preview']) UiStrings().Preview, tooltips[u'preview'])
## Send Live Action ## ## Send Live Action ##
self.__setNameTextString(StringContent.Live, self.__setNameTextString(StringContent.Live,
UiStrings.Live, tooltips[u'live']) UiStrings().Live, tooltips[u'live'])
## Add to Service Action ## ## Add to Service Action ##
self.__setNameTextString(StringContent.Service, self.__setNameTextString(StringContent.Service,
UiStrings.Service, tooltips[u'service']) UiStrings().Service, tooltips[u'service'])
def __setNameTextString(self, name, title, tooltip): def __setNameTextString(self, name, title, tooltip):
""" """

View File

@ -23,46 +23,260 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
"""
The :mod:`renderer` module enables OpenLP to take the input from plugins and
format it for the output display.
"""
import logging import logging
from PyQt4 import QtWebKit from PyQt4 import QtCore, QtWebKit
from openlp.core.lib import expand_tags, build_lyrics_format_css, \ from openlp.core.lib import ServiceItem, ImageManager, expand_tags, \
build_lyrics_outline_css, Receiver build_lyrics_format_css, build_lyrics_outline_css, Receiver, \
ItemCapabilities
from openlp.core.lib.theme import ThemeLevel
from openlp.core.ui import MainDisplay
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
VERSE = u'The Lord said to {r}Noah{/r}: \n' \
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n' \
'The Lord said to {g}Noah{/g}:\n' \
'There\'s gonna be a {st}floody{/st}, {it}floody{/it}\n' \
'Get those children out of the muddy, muddy \n' \
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
HTML_END = u'</div></body></html>'
class Renderer(object): class Renderer(object):
""" """
Genarates a pixmap image of a array of text. The Text is formatted to Class to pull all Renderer interactions into one place. The plugins will
make sure it fits on the screen and if not extra frames are generated. call helper methods to do the rendering but this class will provide
display defense code.
``theme_manager``
The ThemeManager instance, used to get the current theme details.
``screens``
Contains information about the Screens.
``screen_number``
Defaults to *0*. The index of the output/display screen.
""" """
log.info(u'Renderer Loaded') log.info(u'Renderer Loaded')
def __init__(self): def __init__(self, theme_manager, screens):
""" """
Initialise the renderer. Initialise the render manager.
""" """
self._rect = None log.debug(u'Initilisation started')
self.theme_name = None self.screens = screens
self._theme = None self.image_manager = ImageManager()
self.display = MainDisplay(self, screens, False)
self.display.imageManager = self.image_manager
self.theme_manager = theme_manager
self.service_theme = u''
self.theme_level = u''
self.override_background = None
self.theme_data = None
self.force_page = False
def set_theme(self, theme): def update_display(self):
""" """
Set the theme to be used. Updates the render manager's information about the current screen.
"""
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.bg_frame = None
self.theme_data = None
self.image_manager.update_display(self.width, self.height)
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
"""
Set the global-level theme and the theme level.
``global_theme``
The global-level theme to be set.
``theme_level``
Defaults to *``ThemeLevel.Global``*. The theme level, can be
``ThemeLevel.Global``, ``ThemeLevel.Service`` or
``ThemeLevel.Song``.
"""
self.global_theme = global_theme
self.theme_level = theme_level
self.global_theme_data = \
self.theme_manager.getThemeData(self.global_theme)
self.theme_data = None
def set_service_theme(self, service_theme):
"""
Set the service-level theme.
``service_theme``
The service-level theme to be set.
"""
self.service_theme = service_theme
self.theme_data = None
def set_override_theme(self, override_theme, override_levels=False):
"""
Set the appropriate theme depending on the theme level.
Called by the service item when building a display frame
``theme`` ``theme``
The theme to be used. The name of the song-level theme. None means the service
""" item wants to use the given value.
log.debug(u'set theme')
self._theme = theme
self.theme_name = theme.theme_name
def set_text_rectangle(self, rect_main, rect_footer): ``override_levels``
Used to force the theme data passed in to be used.
"""
log.debug(u'set override theme to %s', override_theme)
theme_level = self.theme_level
if override_levels:
theme_level = ThemeLevel.Song
if theme_level == ThemeLevel.Global:
theme = self.global_theme
elif theme_level == ThemeLevel.Service:
if self.service_theme == u'':
theme = self.global_theme
else:
theme = self.service_theme
else:
# Images have a theme of -1
if override_theme and override_theme != -1:
theme = override_theme
elif theme_level == ThemeLevel.Song or \
theme_level == ThemeLevel.Service:
if self.service_theme == u'':
theme = self.global_theme
else:
theme = self.service_theme
else:
theme = self.global_theme
log.debug(u'theme is now %s', theme)
# Force the theme to be the one passed in.
if override_levels:
self.theme_data = override_theme
else:
self.theme_data = self.theme_manager.getThemeData(theme)
self._calculate_default(self.screens.current[u'size'])
self._build_text_rectangle(self.theme_data)
self.image_manager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename)
return self._rect, self._rect_footer
def generate_preview(self, theme_data, force_page=False):
"""
Generate a preview of a theme.
``theme_data``
The theme to generated a preview for.
``force_page``
Flag to tell message lines per page need to be generated.
"""
log.debug(u'generate preview')
# save value for use in format_slide
self.force_page = force_page
# set the default image size for previews
self._calculate_default(self.screens.preview[u'size'])
# build a service item to generate preview
serviceItem = ServiceItem()
serviceItem.theme = theme_data
if self.force_page:
# make big page for theme edit dialog to get line count
serviceItem.add_from_text(u'', VERSE + VERSE + VERSE, FOOTER)
else:
self.image_manager.del_image(theme_data.theme_name)
serviceItem.add_from_text(u'', VERSE, FOOTER)
serviceItem.renderer = self
serviceItem.raw_footer = FOOTER
serviceItem.render(True)
if not self.force_page:
self.display.buildHtml(serviceItem)
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'])
return preview
def format_slide(self, text, line_break, item):
"""
Calculate how much text can fit on a slide.
``text``
The words to go on the slides.
``line_break``
Add line endings after each line of text used for bibles.
"""
log.debug(u'format slide')
# clean up line endings
lines = self._lines_split(text)
pages = self._paginate_slide(lines, line_break, self.force_page)
if len(pages) > 1:
# Songs and Custom
if item.is_capable(ItemCapabilities.AllowsVirtualSplit):
# Do not forget the line breaks !
slides = text.split(u'\n[---]\n')
pages = []
for slide in slides:
lines = self._lines(slide)
new_pages = self._paginate_slide(lines, line_break,
self.force_page)
pages.extend([page for page in new_pages])
# Bibles
elif item.is_capable(ItemCapabilities.AllowsWordSplit):
pages = self._paginate_slide_words(text, line_break)
return pages
def _calculate_default(self, screen):
"""
Calculate the default dimentions of the screen.
``screen``
The QSize of the screen.
"""
log.debug(u'calculate default %s', screen)
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)
def _build_text_rectangle(self, theme):
"""
Builds a text block using the settings in ``theme``
and the size of the display screen.height.
Note the system has a 10 pixel border round the screen
``theme``
The theme to build a text block for.
"""
log.debug(u'_build_text_rectangle')
main_rect = None
footer_rect = None
if not theme.font_main_override:
main_rect = QtCore.QRect(10, 0, self.width - 20, 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 - 20,
self.height - self.footer_start)
else:
footer_rect = QtCore.QRect(theme.font_footer_x,
theme.font_footer_y, theme.font_footer_width - 1,
theme.font_footer_height - 1)
self._set_text_rectangle(main_rect, footer_rect)
def _set_text_rectangle(self, rect_main, rect_footer):
""" """
Sets the rectangle within which text should be rendered. Sets the rectangle within which text should be rendered.
@ -77,9 +291,9 @@ class Renderer(object):
self._rect_footer = rect_footer self._rect_footer = rect_footer
self.page_width = self._rect.width() self.page_width = self._rect.width()
self.page_height = self._rect.height() self.page_height = self._rect.height()
if self._theme.font_main_shadow: if self.theme_data.font_main_shadow:
self.page_width -= int(self._theme.font_main_shadow_size) self.page_width -= int(self.theme_data.font_main_shadow_size)
self.page_height -= int(self._theme.font_main_shadow_size) self.page_height -= int(self.theme_data.font_main_shadow_size)
self.web = QtWebKit.QWebView() self.web = QtWebKit.QWebView()
self.web.setVisible(False) self.web.setVisible(False)
self.web.resize(self.page_width, self.page_height) self.web.resize(self.page_width, self.page_height)
@ -89,59 +303,163 @@ class Renderer(object):
u'*{margin: 0; padding: 0; border: 0;} '\ u'*{margin: 0; padding: 0; border: 0;} '\
u'#main {position:absolute; top:0px; %s %s}</style><body>' \ u'#main {position:absolute; top:0px; %s %s}</style><body>' \
u'<div id="main">' % \ u'<div id="main">' % \
(build_lyrics_format_css(self._theme, self.page_width, (build_lyrics_format_css(self.theme_data, self.page_width,
self.page_height), build_lyrics_outline_css(self._theme)) self.page_height), build_lyrics_outline_css(self.theme_data))
def format_slide(self, words, line_break, force_page=False): def _paginate_slide(self, lines, line_break, force_page=False):
""" """
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
theme settings. theme settings.
``words`` ``lines``
The words to be fitted on the slide. The words to be fitted on the slide split into lines.
``line_break`` ``line_break``
Add line endings after each line of text used for bibles. Add line endings after each line of text (used for bibles).
``force_page`` ``force_page``
Flag to tell message lines in page. Flag to tell message lines in page.
""" """
log.debug(u'format_slide - Start') log.debug(u'_paginate_slide - Start')
line_end = u'' line_end = u''
if line_break: if line_break:
line_end = u'<br>' line_end = u'<br>'
words = words.replace(u'\r\n', u'\n')
verses_text = words.split(u'\n')
text = []
for verse in verses_text:
lines = verse.split(u'\n')
for line in lines:
text.append(line)
formatted = [] formatted = []
html_text = u'' html_text = u''
styled_text = u'' styled_text = u''
line_count = 0 line_count = 0
for line in text: for line in lines:
if line_count != -1: if line_count != -1:
line_count += 1 line_count += 1
styled_line = expand_tags(line) + line_end styled_line = expand_tags(line) + line_end
styled_text += styled_line styled_text += styled_line
html = self.page_shell + styled_text + u'</div></body></html>' html = self.page_shell + styled_text + HTML_END
self.web.setHtml(html) self.web.setHtml(html)
# Text too long so go to next page # Text too long so go to next page
if self.web_frame.contentsSize().height() > self.page_height: if self.web_frame.contentsSize().height() > self.page_height:
if force_page and line_count > 0: if force_page and line_count > 0:
Receiver.send_message(u'theme_line_count', line_count) Receiver.send_message(u'theme_line_count', line_count)
line_count = -1 line_count = -1
if html_text.endswith(u'<br>'): html_text = html_text.rstrip(u'<br>')
html_text = html_text[:len(html_text)-4]
formatted.append(html_text) formatted.append(html_text)
html_text = u'' html_text = u''
styled_text = styled_line styled_text = styled_line
html_text += line + line_end html_text += line + line_end
if html_text.endswith(u'<br>'): html_text = html_text.rstrip(u'<br>')
html_text = html_text[:len(html_text)-4]
formatted.append(html_text) formatted.append(html_text)
log.debug(u'format_slide - End') log.debug(u'_paginate_slide - End')
return formatted return formatted
def _paginate_slide_words(self, text, line_break):
"""
Figure out how much text can appear on a slide, using the current
theme settings. This version is to handle text which needs to be split
into words to get it to fit.
``text``
The words to be fitted on the slide split into lines.
``line_break``
Add line endings after each line of text used for bibles.
"""
log.debug(u'_paginate_slide_words - Start')
line_end = u''
if line_break:
line_end = u'<br>'
formatted = []
previous_html = u''
previous_raw = u''
lines = self._lines(text)
for line in lines:
styled_line = expand_tags(line)
html = self.page_shell + previous_html + styled_line + HTML_END
self.web.setHtml(html)
# Text too long so go to next page
if self.web_frame.contentsSize().height() > self.page_height:
# Check if there was a verse before the current one and append
# it, when it fits on the page.
if previous_html:
html = self.page_shell + previous_html + HTML_END
self.web.setHtml(html)
if self.web_frame.contentsSize().height() <= \
self.page_height:
previous_raw = previous_raw.rstrip(u'<br>')
formatted.append(previous_raw)
previous_html = u''
previous_raw = u''
html = self.page_shell + styled_line + HTML_END
self.web.setHtml(html)
# Now check if the current verse will fit, if it does
# not we have to start to process the verse word by
# word.
if self.web_frame.contentsSize().height() <= \
self.page_height:
previous_html = styled_line + line_end
previous_raw = line + line_end
continue
words = self._words_split(line)
for word in words:
styled_word = expand_tags(word)
html = self.page_shell + previous_html + styled_word + \
HTML_END
self.web.setHtml(html)
# Text too long so go to next page
if self.web_frame.contentsSize().height() > \
self.page_height:
previous_raw = previous_raw.rstrip(u'<br>')
formatted.append(previous_raw)
previous_html = u''
previous_raw = u''
previous_html += styled_word
previous_raw += word
previous_html += line_end
previous_raw += line_end
else:
previous_html += styled_line + line_end
previous_raw += line + line_end
previous_raw = previous_raw.rstrip(u'<br>')
formatted.append(previous_raw)
log.debug(u'_paginate_slide_words - End')
return formatted
def _lines(self, text):
"""
Split the slide up by physical line
"""
# this parse we do not want to use this so remove it
verses_text = text.split(u'\n')
text = []
for verse in verses_text:
lines = verse.split(u'\n')
text.extend([line for line in lines])
return text
def _words_split(self, line):
"""
Split the slide up by word so can wrap better
"""
# this parse we are to be wordy
line = line.replace(u'\n', u' ')
verses_text = line.split(u' ')
text = []
for verse in verses_text:
lines = verse.split(u' ')
text.extend([line + u' ' for line in lines])
return text
def _lines_split(self, text):
"""
Split the slide up by physical line
"""
# this parse we do not want to use this so remove it
text = text.replace(u'\n[---]', u'')
lines = text.split(u'\n')
real_lines = []
for line in lines:
line = line.replace(u'[---]', u'')
sub_lines = line.split(u'\n')
real_lines.extend([sub_line for sub_line in sub_lines])
return real_lines

View File

@ -1,261 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
from PyQt4 import QtCore
from openlp.core.lib import Renderer, ServiceItem, ImageManager
from openlp.core.lib.theme import ThemeLevel
from openlp.core.ui import MainDisplay
log = logging.getLogger(__name__)
VERSE = u'The Lord said to {r}Noah{/r}: \n' \
'There\'s gonna be a {su}floody{/su}, {sb}floody{/sb}\n' \
'The Lord said to {g}Noah{/g}:\n' \
'There\'s gonna be a {st}floody{/st}, {it}floody{/it}\n' \
'Get those children out of the muddy, muddy \n' \
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
FOOTER = [u'Arky Arky (Unknown)', u'Public Domain', u'CCLI 123456']
class RenderManager(object):
"""
Class to pull all Renderer interactions into one place. The plugins will
call helper methods to do the rendering but this class will provide
display defense code.
``theme_manager``
The ThemeManager instance, used to get the current theme details.
``screens``
Contains information about the Screens.
``screen_number``
Defaults to *0*. The index of the output/display screen.
"""
log.info(u'RenderManager Loaded')
def __init__(self, theme_manager, screens):
"""
Initialise the render manager.
"""
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.theme_manager = theme_manager
self.renderer = Renderer()
self.calculate_default(self.screens.current[u'size'])
self.theme = u''
self.service_theme = u''
self.theme_level = u''
self.override_background = None
self.theme_data = None
self.force_page = False
def update_display(self):
"""
Updates the render manager's information about the current screen.
"""
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.theme_data = None
self.image_manager.update_display(self.width, self.height)
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
"""
Set the global-level theme and the theme level.
``global_theme``
The global-level theme to be set.
``theme_level``
Defaults to *``ThemeLevel.Global``*. The theme level, can be
``ThemeLevel.Global``, ``ThemeLevel.Service`` or
``ThemeLevel.Song``.
"""
self.global_theme = global_theme
self.theme_level = theme_level
self.global_theme_data = \
self.theme_manager.getThemeData(self.global_theme)
self.theme_data = None
def set_service_theme(self, service_theme):
"""
Set the service-level theme.
``service_theme``
The service-level theme to be set.
"""
self.service_theme = service_theme
self.theme_data = None
def set_override_theme(self, theme, overrideLevels=False):
"""
Set the appropriate theme depending on the theme level.
Called by the service item when building a display frame
``theme``
The name of the song-level theme. None means the service
item wants to use the given value.
``overrideLevels``
Used to force the theme data passed in to be used.
"""
log.debug(u'set override theme to %s', theme)
theme_level = self.theme_level
if overrideLevels:
theme_level = ThemeLevel.Song
if theme_level == ThemeLevel.Global:
self.theme = self.global_theme
elif theme_level == ThemeLevel.Service:
if self.service_theme == u'':
self.theme = self.global_theme
else:
self.theme = self.service_theme
else:
# Images have a theme of -1
if theme and theme != -1:
self.theme = theme
elif theme_level == ThemeLevel.Song or \
theme_level == ThemeLevel.Service:
if self.service_theme == u'':
self.theme = self.global_theme
else:
self.theme = self.service_theme
else:
self.theme = self.global_theme
if self.theme != self.renderer.theme_name or self.theme_data is None \
or overrideLevels:
log.debug(u'theme is now %s', self.theme)
# Force the theme to be the one passed in.
if overrideLevels:
self.theme_data = theme
else:
self.theme_data = self.theme_manager.getThemeData(self.theme)
self.calculate_default(self.screens.current[u'size'])
self.renderer.set_theme(self.theme_data)
self.build_text_rectangle(self.theme_data)
self.image_manager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename)
return self.renderer._rect, self.renderer._rect_footer
def build_text_rectangle(self, theme):
"""
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.
"""
log.debug(u'build_text_rectangle')
main_rect = None
footer_rect = None
if not theme.font_main_override:
main_rect = QtCore.QRect(10, 0, self.width - 20, 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 - 20,
self.height - self.footer_start)
else:
footer_rect = QtCore.QRect(theme.font_footer_x,
theme.font_footer_y, theme.font_footer_width - 1,
theme.font_footer_height - 1)
self.renderer.set_text_rectangle(main_rect, footer_rect)
def generate_preview(self, theme_data, force_page=False):
"""
Generate a preview of a theme.
``theme_data``
The theme to generated a preview for.
``force_page``
Flag to tell message lines per page need to be generated.
"""
log.debug(u'generate preview')
# save value for use in format_slide
self.force_page = force_page
# set the default image size for previews
self.calculate_default(self.screens.preview[u'size'])
# build a service item to generate preview
serviceItem = ServiceItem()
serviceItem.theme = theme_data
if self.force_page:
# make big page for theme edit dialog to get line count
serviceItem.add_from_text(u'', VERSE + VERSE + VERSE, FOOTER)
else:
self.image_manager.del_image(theme_data.theme_name)
serviceItem.add_from_text(u'', VERSE, FOOTER)
serviceItem.render_manager = self
serviceItem.raw_footer = FOOTER
serviceItem.render(True)
if not self.force_page:
self.display.buildHtml(serviceItem)
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'])
return preview
def format_slide(self, words, line_break):
"""
Calculate how much text can fit on a slide.
``words``
The words to go on the slides.
``line_break``
Add line endings after each line of text used for bibles.
"""
log.debug(u'format slide')
return self.renderer.format_slide(words, line_break, self.force_page)
def calculate_default(self, screen):
"""
Calculate the default dimentions of the screen.
``screen``
The QSize of the screen.
"""
log.debug(u'calculate default %s', screen)
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)

View File

@ -63,6 +63,8 @@ class ItemCapabilities(object):
ProvidesOwnDisplay = 10 ProvidesOwnDisplay = 10
AllowsDetailedTitleDisplay = 11 AllowsDetailedTitleDisplay = 11
AllowsVariableStartTime = 12 AllowsVariableStartTime = 12
AllowsVirtualSplit = 13
AllowsWordSplit = 14
class ServiceItem(object): class ServiceItem(object):
@ -81,7 +83,7 @@ class ServiceItem(object):
The plugin that this service item belongs to. The plugin that this service item belongs to.
""" """
if plugin: if plugin:
self.render_manager = plugin.renderManager self.renderer = plugin.renderer
self.name = plugin.name self.name = plugin.name
self.title = u'' self.title = u''
self.shortname = u'' self.shortname = u''
@ -151,7 +153,7 @@ class ServiceItem(object):
self.icon = icon self.icon = icon
self.iconic_representation = build_icon(icon) self.iconic_representation = build_icon(icon)
def render(self, useOverride=False): def render(self, use_override=False):
""" """
The render method is what generates the frames for the screen and The render method is what generates the frames for the screen and
obtains the display information from the renderemanager. obtains the display information from the renderemanager.
@ -161,24 +163,23 @@ class ServiceItem(object):
log.debug(u'Render called') log.debug(u'Render called')
self._display_frames = [] self._display_frames = []
self.bg_image_bytes = None self.bg_image_bytes = None
line_break = True line_break = not self.is_capable(ItemCapabilities.NoLineBreaks)
if self.is_capable(ItemCapabilities.NoLineBreaks):
line_break = False
theme = self.theme if self.theme else None theme = self.theme if self.theme else None
self.main, self.footer = \ self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride) self.renderer.set_override_theme(theme, use_override)
self.themedata = self.render_manager.renderer._theme self.themedata = self.renderer.theme_data
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:
formatted = self.render_manager \ formatted = self.renderer \
.format_slide(slide[u'raw_slide'], line_break) .format_slide(slide[u'raw_slide'], line_break, self)
for page in formatted: for page in formatted:
self._display_frames.append( self._display_frames.append({
{u'title': clean_tags(page), u'title': clean_tags(page),
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']
})
elif self.service_item_type == ServiceItemType.Image or \ elif self.service_item_type == ServiceItemType.Image or \
self.service_item_type == ServiceItemType.Command: self.service_item_type == ServiceItemType.Command:
pass pass
@ -205,7 +206,7 @@ class ServiceItem(object):
""" """
self.service_item_type = ServiceItemType.Image self.service_item_type = ServiceItemType.Image
self._raw_frames.append({u'title': title, u'path': path}) self._raw_frames.append({u'title': title, u'path': path})
self.render_manager.image_manager.add_image(title, path) self.renderer.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):
@ -441,10 +442,10 @@ class ServiceItem(object):
start = None start = None
end = None end = None
if self.start_time != 0: if self.start_time != 0:
start = UiStrings.StartTimeCode % \ start = UiStrings().StartTimeCode % \
unicode(datetime.timedelta(seconds=self.start_time)) unicode(datetime.timedelta(seconds=self.start_time))
if self.media_length != 0: if self.media_length != 0:
end = UiStrings.LengthTime % \ end = UiStrings().LengthTime % \
unicode(datetime.timedelta(seconds=self.media_length)) unicode(datetime.timedelta(seconds=self.media_length))
if not start and not end: if not start and not end:
return None return None
@ -454,3 +455,4 @@ class ServiceItem(object):
return end return end
else: else:
return u'%s : %s' % (start, end) return u'%s : %s' % (start, end)

View File

@ -192,7 +192,7 @@ class VerticalType(object):
Bottom = 2 Bottom = 2
Names = [u'top', u'middle', u'bottom'] Names = [u'top', u'middle', u'bottom']
TranslatedNames = [UiStrings.Top, UiStrings.Middle, UiStrings.Bottom] TranslatedNames = [UiStrings().Top, UiStrings().Middle, UiStrings().Bottom]
BOOLEAN_LIST = [u'bold', u'italics', u'override', u'outline', u'shadow', BOOLEAN_LIST = [u'bold', u'italics', u'override', u'outline', u'shadow',

View File

@ -39,78 +39,96 @@ class UiStrings(object):
""" """
Provide standard strings for objects to use. Provide standard strings for objects to use.
""" """
# These strings should need a good reason to be retranslated elsewhere. __instance__ = None
# Should some/more/less of these have an &amp; attached?
About = translate('OpenLP.Ui', 'About') def __new__(cls):
Add = translate('OpenLP.Ui', '&Add') """
Advanced = translate('OpenLP.Ui', 'Advanced') Override the default object creation method to return a single instance.
AllFiles = translate('OpenLP.Ui', 'All Files') """
Bottom = translate('OpenLP.Ui', 'Bottom') if not cls.__instance__:
Browse = translate('OpenLP.Ui', 'Browse...') cls.__instance__ = object.__new__(cls)
Cancel = translate('OpenLP.Ui', 'Cancel') return cls.__instance__
CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
CreateService = translate('OpenLP.Ui', 'Create a new service.') def __init__(self):
Continuous = translate('OpenLP.Ui', 'Continuous') """
Default = unicode(translate('OpenLP.Ui', 'Default')) These strings should need a good reason to be retranslated elsewhere.
Delete = translate('OpenLP.Ui', '&Delete') Should some/more/less of these have an &amp; attached?
DisplayStyle = translate('OpenLP.Ui', 'Display style:') """
Edit = translate('OpenLP.Ui', '&Edit') self.About = translate('OpenLP.Ui', 'About')
EmptyField = translate('OpenLP.Ui', 'Empty Field') self.Add = translate('OpenLP.Ui', '&Add')
Error = translate('OpenLP.Ui', 'Error') self.Advanced = translate('OpenLP.Ui', 'Advanced')
Export = translate('OpenLP.Ui', 'Export') self.AllFiles = translate('OpenLP.Ui', 'All Files')
File = translate('OpenLP.Ui', 'File') self.Bottom = translate('OpenLP.Ui', 'Bottom')
FontSizePtUnit = translate('OpenLP.Ui', 'pt', self.Browse = translate('OpenLP.Ui', 'Browse...')
'Abbreviated font pointsize unit') self.Cancel = translate('OpenLP.Ui', 'Cancel')
Help = translate('OpenLP.Ui', 'Help') self.CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours') self.CreateService = translate('OpenLP.Ui', 'Create a new service.')
Image = translate('OpenLP.Ui', 'Image') self.Continuous = translate('OpenLP.Ui', 'Continuous')
Import = translate('OpenLP.Ui', 'Import') self.Default = unicode(translate('OpenLP.Ui', 'Default'))
LayoutStyle = translate('OpenLP.Ui', 'Layout style:') self.Delete = translate('OpenLP.Ui', '&Delete')
LengthTime = unicode(translate('OpenLP.Ui', 'Length %s')) self.DisplayStyle = translate('OpenLP.Ui', 'Display style:')
Live = translate('OpenLP.Ui', 'Live') self.Edit = translate('OpenLP.Ui', '&Edit')
LiveBGError = translate('OpenLP.Ui', 'Live Background Error') self.EmptyField = translate('OpenLP.Ui', 'Empty Field')
LivePanel = translate('OpenLP.Ui', 'Live Panel') self.Error = translate('OpenLP.Ui', 'Error')
LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar') self.Export = translate('OpenLP.Ui', 'Export')
Load = translate('OpenLP.Ui', 'Load') self.File = translate('OpenLP.Ui', 'File')
Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes') self.FontSizePtUnit = translate('OpenLP.Ui', 'pt',
Middle = translate('OpenLP.Ui', 'Middle') 'Abbreviated font pointsize unit')
New = translate('OpenLP.Ui', 'New') self.Help = translate('OpenLP.Ui', 'Help')
NewService = translate('OpenLP.Ui', 'New Service') self.Hours = translate('OpenLP.Ui', 'h',
NewTheme = translate('OpenLP.Ui', 'New Theme') 'The abbreviated unit for hours')
NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular') self.Image = translate('OpenLP.Ui', 'Image')
NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural') self.Import = translate('OpenLP.Ui', 'Import')
NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular') self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')
NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural') self.LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x') self.Live = translate('OpenLP.Ui', 'Live')
OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0') self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. Do you ' self.LivePanel = translate('OpenLP.Ui', 'Live Panel')
'wish to continue?') self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
OpenService = translate('OpenLP.Ui', 'Open Service') self.Load = translate('OpenLP.Ui', 'Load')
Preview = translate('OpenLP.Ui', 'Preview') self.Minutes = translate('OpenLP.Ui', 'm',
PreviewPanel = translate('OpenLP.Ui', 'Preview Panel') 'The abbreviated unit for minutes')
PrintServiceOrder = translate('OpenLP.Ui', 'Print Service Order') self.Middle = translate('OpenLP.Ui', 'Middle')
ReplaceBG = translate('OpenLP.Ui', 'Replace Background') self.New = translate('OpenLP.Ui', 'New')
ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background') self.NewService = translate('OpenLP.Ui', 'New Service')
ResetBG = translate('OpenLP.Ui', 'Reset Background') self.NewTheme = translate('OpenLP.Ui', 'New Theme')
ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background') self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds') self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview') self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
Search = translate('OpenLP.Ui', 'Search') self.NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural')
SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.') self.OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x')
SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.') self.OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0')
Settings = translate('OpenLP.Ui', 'Settings') self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. '
SaveService = translate('OpenLP.Ui', 'Save Service') 'Do you wish to continue?')
Service = translate('OpenLP.Ui', 'Service') self.OpenService = translate('OpenLP.Ui', 'Open Service')
StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s')) self.Preview = translate('OpenLP.Ui', 'Preview')
Theme = translate('OpenLP.Ui', 'Theme', 'Singular') self.PreviewPanel = translate('OpenLP.Ui', 'Preview Panel')
Themes = translate('OpenLP.Ui', 'Themes', 'Plural') self.PrintServiceOrder = translate('OpenLP.Ui', 'Print Service Order')
Tools = translate('OpenLP.Ui', 'Tools') self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
Top = translate('OpenLP.Ui', 'Top') self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background')
VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide') self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
VersePerLine = translate('OpenLP.Ui', 'Verse Per Line') self.ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background')
Version = translate('OpenLP.Ui', 'Version') self.Seconds = translate('OpenLP.Ui', 's',
View = translate('OpenLP.Ui', 'View') 'The abbreviated unit for seconds')
ViewMode = translate('OpenLP.Ui', 'View Model') self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
self.Search = translate('OpenLP.Ui', 'Search')
self.SelectDelete = translate('OpenLP.Ui', 'You must select an item '
'to delete.')
self.SelectEdit = translate('OpenLP.Ui', 'You must select an item to '
'edit.')
self.Settings = translate('OpenLP.Ui', 'Settings')
self.SaveService = translate('OpenLP.Ui', 'Save Service')
self.Service = translate('OpenLP.Ui', 'Service')
self.StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')
self.Tools = translate('OpenLP.Ui', 'Tools')
self.Top = translate('OpenLP.Ui', 'Top')
self.VersePerSlide = translate('OpenLP.Ui', 'Verse Per Slide')
self.VersePerLine = translate('OpenLP.Ui', 'Verse Per Line')
self.Version = translate('OpenLP.Ui', 'Version')
self.View = translate('OpenLP.Ui', 'View')
self.ViewMode = translate('OpenLP.Ui', 'View Model')
def add_welcome_page(parent, image): def add_welcome_page(parent, image):
""" """
@ -157,7 +175,8 @@ def create_accept_reject_button_box(parent, okay=False):
accept_button = QtGui.QDialogButtonBox.Save accept_button = QtGui.QDialogButtonBox.Save
if okay: if okay:
accept_button = QtGui.QDialogButtonBox.Ok accept_button = QtGui.QDialogButtonBox.Ok
button_box.setStandardButtons(accept_button | QtGui.QDialogButtonBox.Cancel) button_box.setStandardButtons(
accept_button | QtGui.QDialogButtonBox.Cancel)
button_box.setObjectName(u'%sButtonBox' % parent) button_box.setObjectName(u'%sButtonBox' % parent)
QtCore.QObject.connect(button_box, QtCore.SIGNAL(u'accepted()'), QtCore.QObject.connect(button_box, QtCore.SIGNAL(u'accepted()'),
parent.accept) parent.accept)
@ -184,11 +203,11 @@ def critical_error_message_box(title=None, message=None, parent=None,
Should this message box question the user. Should this message box question the user.
""" """
if question: if question:
return QtGui.QMessageBox.critical(parent, UiStrings.Error, message, return QtGui.QMessageBox.critical(parent, UiStrings().Error, message,
QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
data = {u'message': message} data = {u'message': message}
data[u'title'] = title if title else UiStrings.Error data[u'title'] = title if title else UiStrings().Error
return Receiver.send_message(u'openlp_error_message', data) return Receiver.send_message(u'openlp_error_message', data)
def media_item_combo_box(parent, name): def media_item_combo_box(parent, name):
@ -218,7 +237,7 @@ def create_delete_push_button(parent, icon=None):
delete_button.setObjectName(u'deleteButton') delete_button.setObjectName(u'deleteButton')
delete_icon = icon if icon else u':/general/general_delete.png' delete_icon = icon if icon else u':/general/general_delete.png'
delete_button.setIcon(build_icon(delete_icon)) delete_button.setIcon(build_icon(delete_icon))
delete_button.setText(UiStrings.Delete) delete_button.setText(UiStrings().Delete)
delete_button.setToolTip( delete_button.setToolTip(
translate('OpenLP.Ui', 'Delete the selected item.')) translate('OpenLP.Ui', 'Delete the selected item.'))
QtCore.QObject.connect(delete_button, QtCore.QObject.connect(delete_button,
@ -304,7 +323,7 @@ def shortcut_action(parent, name, shortcuts, function, icon=None, checked=None,
action.setShortcutContext(context) action.setShortcutContext(context)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(action, category) action_list.add_action(action, category)
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), function) QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), function)
return action return action
def context_menu_action(base, icon, text, slot, shortcuts=None, category=None, def context_menu_action(base, icon, text, slot, shortcuts=None, category=None,
@ -337,7 +356,7 @@ def context_menu_action(base, icon, text, slot, shortcuts=None, category=None,
action = QtGui.QAction(text, base) action = QtGui.QAction(text, base)
if icon: if icon:
action.setIcon(build_icon(icon)) action.setIcon(build_icon(icon))
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), slot) QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered(bool)'), slot)
if shortcuts is not None: if shortcuts is not None:
action.setShortcuts(shortcuts) action.setShortcuts(shortcuts)
action.setShortcutContext(context) action.setShortcutContext(context)
@ -406,9 +425,9 @@ def create_valign_combo(form, parent, layout):
verticalLabel.setText(translate('OpenLP.Ui', '&Vertical Align:')) verticalLabel.setText(translate('OpenLP.Ui', '&Vertical Align:'))
form.verticalComboBox = QtGui.QComboBox(parent) form.verticalComboBox = QtGui.QComboBox(parent)
form.verticalComboBox.setObjectName(u'VerticalComboBox') form.verticalComboBox.setObjectName(u'VerticalComboBox')
form.verticalComboBox.addItem(UiStrings.Top) form.verticalComboBox.addItem(UiStrings().Top)
form.verticalComboBox.addItem(UiStrings.Middle) form.verticalComboBox.addItem(UiStrings().Middle)
form.verticalComboBox.addItem(UiStrings.Bottom) form.verticalComboBox.addItem(UiStrings().Bottom)
verticalLabel.setBuddy(form.verticalComboBox) verticalLabel.setBuddy(form.verticalComboBox)
layout.addRow(verticalLabel, form.verticalComboBox) layout.addRow(verticalLabel, form.verticalComboBox)

View File

@ -87,7 +87,7 @@ class Ui_AboutDialog(object):
QtCore.QMetaObject.connectSlotsByName(aboutDialog) QtCore.QMetaObject.connectSlotsByName(aboutDialog)
def retranslateUi(self, aboutDialog): def retranslateUi(self, aboutDialog):
aboutDialog.setWindowTitle(u'%s OpenLP' % UiStrings.About) aboutDialog.setWindowTitle(u'%s OpenLP' % UiStrings().About)
self.aboutTextEdit.setPlainText(translate('OpenLP.AboutForm', self.aboutTextEdit.setPlainText(translate('OpenLP.AboutForm',
'OpenLP <version><revision> - Open Source Lyrics ' 'OpenLP <version><revision> - Open Source Lyrics '
'Projection\n' 'Projection\n'
@ -105,7 +105,7 @@ class Ui_AboutDialog(object):
'consider contributing by using the button below.' 'consider contributing by using the button below.'
)) ))
self.aboutNotebook.setTabText( self.aboutNotebook.setTabText(
self.aboutNotebook.indexOf(self.aboutTab), UiStrings.About) self.aboutNotebook.indexOf(self.aboutTab), UiStrings().About)
lead = u'Raoul "superfly" Snyman' lead = u'Raoul "superfly" Snyman'
developers = [u'Tim "TRB143" Bentley', u'Jonathan "gushie" Corwin', developers = [u'Tim "TRB143" Bentley', u'Jonathan "gushie" Corwin',
u'Michael "cocooncrash" Gorven', u'Michael "cocooncrash" Gorven',
@ -615,4 +615,4 @@ class Ui_AboutDialog(object):
self.aboutNotebook.indexOf(self.licenseTab), self.aboutNotebook.indexOf(self.licenseTab),
translate('OpenLP.AboutForm', 'License')) translate('OpenLP.AboutForm', 'License'))
self.contributeButton.setText(translate('OpenLP.AboutForm', self.contributeButton.setText(translate('OpenLP.AboutForm',
'Contribute')) 'Contribute'))

View File

@ -41,11 +41,11 @@ class AdvancedTab(SettingsTab):
""" """
Initialise the settings tab Initialise the settings tab
""" """
generalTranslated = translate('AdvancedTab', 'Advanced') advancedTranslated = translate('OpenLP.AdvancedTab', 'Advanced')
SettingsTab.__init__(self, parent ,u'Advanced', generalTranslated)
self.default_image = u':/graphics/openlp-splash-screen.png' self.default_image = u':/graphics/openlp-splash-screen.png'
self.default_color = u'#ffffff' self.default_color = u'#ffffff'
self.icon_path = u':/system/system_settings.png' self.icon_path = u':/system/system_settings.png'
SettingsTab.__init__(self, parent, u'Advanced', advancedTranslated)
def setupUi(self): def setupUi(self):
""" """
@ -82,14 +82,6 @@ class AdvancedTab(SettingsTab):
u'enableAutoCloseCheckBox') u'enableAutoCloseCheckBox')
self.uiLayout.addRow(self.enableAutoCloseCheckBox) self.uiLayout.addRow(self.enableAutoCloseCheckBox)
self.leftLayout.addWidget(self.uiGroupBox) self.leftLayout.addWidget(self.uiGroupBox)
self.hideMouseGroupBox = QtGui.QGroupBox(self.leftColumn)
self.hideMouseGroupBox.setObjectName(u'hideMouseGroupBox')
self.hideMouseLayout = QtGui.QVBoxLayout(self.hideMouseGroupBox)
self.hideMouseLayout.setObjectName(u'hideMouseLayout')
self.hideMouseCheckBox = QtGui.QCheckBox(self.hideMouseGroupBox)
self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox')
self.hideMouseLayout.addWidget(self.hideMouseCheckBox)
self.leftLayout.addWidget(self.hideMouseGroupBox)
self.leftLayout.addStretch() self.leftLayout.addStretch()
self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn)
self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox') self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox')
@ -109,26 +101,42 @@ class AdvancedTab(SettingsTab):
self.defaultBrowseButton.setObjectName(u'defaultBrowseButton') self.defaultBrowseButton.setObjectName(u'defaultBrowseButton')
self.defaultBrowseButton.setIcon( self.defaultBrowseButton.setIcon(
build_icon(u':/general/general_open.png')) build_icon(u':/general/general_open.png'))
self.defaultRevertButton = QtGui.QToolButton(self.defaultImageGroupBox)
self.defaultRevertButton.setObjectName(u'defaultRevertButton')
self.defaultRevertButton.setIcon(
build_icon(u':/general/general_revert.png'))
self.defaultFileLayout = QtGui.QHBoxLayout() self.defaultFileLayout = QtGui.QHBoxLayout()
self.defaultFileLayout.setObjectName(u'defaultFileLayout') self.defaultFileLayout.setObjectName(u'defaultFileLayout')
self.defaultFileLayout.addWidget(self.defaultFileEdit) self.defaultFileLayout.addWidget(self.defaultFileEdit)
self.defaultFileLayout.addWidget(self.defaultBrowseButton) self.defaultFileLayout.addWidget(self.defaultBrowseButton)
self.defaultFileLayout.addWidget(self.defaultRevertButton)
self.defaultImageLayout.addRow(self.defaultFileLabel, self.defaultImageLayout.addRow(self.defaultFileLabel,
self.defaultFileLayout) self.defaultFileLayout)
self.rightLayout.addWidget(self.defaultImageGroupBox) self.rightLayout.addWidget(self.defaultImageGroupBox)
self.hideMouseGroupBox = QtGui.QGroupBox(self.leftColumn)
self.hideMouseGroupBox.setObjectName(u'hideMouseGroupBox')
self.hideMouseLayout = QtGui.QVBoxLayout(self.hideMouseGroupBox)
self.hideMouseLayout.setObjectName(u'hideMouseLayout')
self.hideMouseCheckBox = QtGui.QCheckBox(self.hideMouseGroupBox)
self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox')
self.hideMouseLayout.addWidget(self.hideMouseCheckBox)
self.rightLayout.addWidget(self.hideMouseGroupBox)
self.rightLayout.addStretch() self.rightLayout.addStretch()
QtCore.QObject.connect(self.defaultColorButton, QtCore.QObject.connect(self.defaultColorButton,
QtCore.SIGNAL(u'pressed()'), self.onDefaultColorButtonPressed) QtCore.SIGNAL(u'pressed()'), self.onDefaultColorButtonPressed)
QtCore.QObject.connect(self.defaultBrowseButton, QtCore.QObject.connect(self.defaultBrowseButton,
QtCore.SIGNAL(u'pressed()'), self.onDefaultBrowseButtonPressed) QtCore.SIGNAL(u'pressed()'), self.onDefaultBrowseButtonPressed)
QtCore.QObject.connect(self.defaultRevertButton,
QtCore.SIGNAL(u'pressed()'), self.onDefaultRevertButtonPressed)
def retranslateUi(self): def retranslateUi(self):
""" """
Setup the interface translation strings. Setup the interface translation strings.
""" """
self.tabTitleVisible = UiStrings.Advanced self.tabTitleVisible = UiStrings().Advanced
self.uiGroupBox.setTitle(translate('OpenLP.AdvancedTab', 'UI Settings')) self.uiGroupBox.setTitle(
translate('OpenLP.AdvancedTab', 'UI Settings'))
self.recentLabel.setText( self.recentLabel.setText(
translate('OpenLP.AdvancedTab', translate('OpenLP.AdvancedTab',
'Number of recent files to display:')) 'Number of recent files to display:'))
@ -150,8 +158,14 @@ class AdvancedTab(SettingsTab):
'Default Image')) 'Default Image'))
self.defaultColorLabel.setText(translate('OpenLP.AdvancedTab', self.defaultColorLabel.setText(translate('OpenLP.AdvancedTab',
'Background color:')) 'Background color:'))
self.defaultColorButton.setToolTip(translate('OpenLP.AdvancedTab',
'Click to select a color.'))
self.defaultFileLabel.setText(translate('OpenLP.AdvancedTab', self.defaultFileLabel.setText(translate('OpenLP.AdvancedTab',
'Image file:')) 'Image file:'))
self.defaultBrowseButton.setToolTip(translate('OpenLP.AdvancedTab',
'Browse for an image file to display.'))
self.defaultRevertButton.setToolTip(translate('OpenLP.AdvancedTab',
'Revert to the default OpenLP logo.'))
def load(self): def load(self):
""" """
@ -226,10 +240,14 @@ class AdvancedTab(SettingsTab):
def onDefaultBrowseButtonPressed(self): def onDefaultBrowseButtonPressed(self):
file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(), file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(),
UiStrings.AllFiles) UiStrings().AllFiles)
filename = QtGui.QFileDialog.getOpenFileName(self, filename = QtGui.QFileDialog.getOpenFileName(self,
translate('OpenLP.AdvancedTab', 'Open File'), '', translate('OpenLP.AdvancedTab', 'Open File'), '',
file_filters) file_filters)
if filename: if filename:
self.defaultFileEdit.setText(filename) self.defaultFileEdit.setText(filename)
self.defaultFileEdit.setFocus() self.defaultFileEdit.setFocus()
def onDefaultRevertButtonPressed(self):
self.defaultFileEdit.setText(u':/graphics/openlp-splash-screen.png')
self.defaultFileEdit.setFocus()

View File

@ -136,10 +136,10 @@ class Ui_DisplayTagDialog(object):
translate('OpenLP.DisplayTagDialog', 'Start tag')) translate('OpenLP.DisplayTagDialog', 'Start tag'))
self.endTagLabel.setText( self.endTagLabel.setText(
translate('OpenLP.DisplayTagDialog', 'End tag')) translate('OpenLP.DisplayTagDialog', 'End tag'))
self.deletePushButton.setText(UiStrings.Delete) self.deletePushButton.setText(UiStrings().Delete)
self.defaultPushButton.setText( self.defaultPushButton.setText(
translate('OpenLP.DisplayTagDialog', 'Default')) translate('OpenLP.DisplayTagDialog', 'Default'))
self.newPushButton.setText(UiStrings.New) self.newPushButton.setText(UiStrings().New)
self.tagTableWidget.horizontalHeaderItem(0).setText( self.tagTableWidget.horizontalHeaderItem(0).setText(
translate('OpenLP.DisplayTagDialog', 'Description')) translate('OpenLP.DisplayTagDialog', 'Description'))
self.tagTableWidget.horizontalHeaderItem(1).setText( self.tagTableWidget.horizontalHeaderItem(1).setText(
@ -151,4 +151,4 @@ class Ui_DisplayTagDialog(object):
self.tagTableWidget.setColumnWidth(0, 120) self.tagTableWidget.setColumnWidth(0, 120)
self.tagTableWidget.setColumnWidth(1, 40) self.tagTableWidget.setColumnWidth(1, 40)
self.tagTableWidget.setColumnWidth(2, 240) self.tagTableWidget.setColumnWidth(2, 240)
self.tagTableWidget.setColumnWidth(3, 240) self.tagTableWidget.setColumnWidth(3, 240)

View File

@ -178,11 +178,11 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
self,translate('ImagePlugin.ExceptionDialog', self,translate('ImagePlugin.ExceptionDialog',
'Select Attachment'), 'Select Attachment'),
SettingsManager.get_last_dir(u'exceptions'), SettingsManager.get_last_dir(u'exceptions'),
u'%s (*.*) (*)' % UiStrings.AllFiles) u'%s (*.*) (*)' % UiStrings().AllFiles)
log.info(u'New files(s) %s', unicode(files)) log.info(u'New files(s) %s', unicode(files))
if files: if files:
self.fileAttachment = unicode(files) self.fileAttachment = unicode(files)
def __buttonState(self, state): def __buttonState(self, state):
self.saveReportButton.setEnabled(state) self.saveReportButton.setEnabled(state)
self.sendReportButton.setEnabled(state) self.sendReportButton.setEnabled(state)

View File

@ -140,6 +140,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
return FirstTimePage.Songs return FirstTimePage.Songs
elif self.currentId() == FirstTimePage.Progress: elif self.currentId() == FirstTimePage.Progress:
return -1 return -1
elif self.currentId() == FirstTimePage.NoInternet:
return FirstTimePage.Progress
else: else:
return self.currentId() + 1 return self.currentId() + 1
@ -147,11 +149,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
""" """
Detects Page changes and updates as approprate. Detects Page changes and updates as approprate.
""" """
if pageId == FirstTimePage.NoInternet: if pageId == FirstTimePage.Defaults:
self.finishButton.setVisible(True)
self.finishButton.setEnabled(True)
self.nextButton.setVisible(False)
elif pageId == FirstTimePage.Defaults:
self.themeComboBox.clear() self.themeComboBox.clear()
for iter in xrange(self.themesListWidget.count()): for iter in xrange(self.themesListWidget.count()):
item = self.themesListWidget.item(iter) item = self.themesListWidget.item(iter)

View File

@ -238,7 +238,7 @@ class GeneralTab(SettingsTab):
self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec')) self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec'))
self.ccliGroupBox.setTitle( self.ccliGroupBox.setTitle(
translate('OpenLP.GeneralTab', 'CCLI Details')) translate('OpenLP.GeneralTab', 'CCLI Details'))
self.numberLabel.setText(UiStrings.CCLINumberLabel) self.numberLabel.setText(UiStrings().CCLINumberLabel)
self.usernameLabel.setText( self.usernameLabel.setText(
translate('OpenLP.GeneralTab', 'SongSelect username:')) translate('OpenLP.GeneralTab', 'SongSelect username:'))
self.passwordLabel.setText( self.passwordLabel.setText(
@ -394,4 +394,4 @@ class GeneralTab(SettingsTab):
""" """
Called when the width, height, x position or y position has changed. Called when the width, height, x position or y position has changed.
""" """
self.overrideChanged = True self.overrideChanged = True

View File

@ -34,7 +34,7 @@ from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \ from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte, \
build_icon, translate translate
from openlp.core.ui import HideMode from openlp.core.ui import HideMode
@ -69,8 +69,6 @@ class MainDisplay(DisplayWidget):
self.hideMode = None self.hideMode = None
self.videoHide = False self.videoHide = False
self.override = {} self.override = {}
mainIcon = build_icon(u':/icon/openlp-logo-16x16.png')
self.setWindowIcon(mainIcon)
self.retranslateUi() self.retranslateUi()
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool |
@ -144,7 +142,8 @@ class MainDisplay(DisplayWidget):
image_file = QtCore.QSettings().value(u'advanced/default image', image_file = QtCore.QSettings().value(u'advanced/default image',
QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\ QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\
.toString() .toString()
background_color = QtGui.QColor(QtCore.QSettings().value( background_color = QtGui.QColor()
background_color.setNamedColor(QtCore.QSettings().value(
u'advanced/default color', u'advanced/default color',
QtCore.QVariant(u'#ffffff')).toString()) QtCore.QVariant(u'#ffffff')).toString())
if not background_color.isValid(): if not background_color.isValid():

View File

@ -30,7 +30,7 @@ from tempfile import gettempdir
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \ from openlp.core.lib import Renderer, build_icon, OpenLPDockWidget, \
SettingsManager, PluginManager, Receiver, translate SettingsManager, PluginManager, Receiver, translate
from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \ from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \
icon_action, shortcut_action icon_action, shortcut_action
@ -71,7 +71,7 @@ class Ui_MainWindow(object):
mainWindow.setObjectName(u'MainWindow') mainWindow.setObjectName(u'MainWindow')
mainWindow.resize(self.settingsmanager.width, mainWindow.resize(self.settingsmanager.width,
self.settingsmanager.height) self.settingsmanager.height)
mainWindow.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) mainWindow.setWindowIcon(build_icon(u':/icon/openlp-logo-64x64.png'))
mainWindow.setDockNestingEnabled(True) mainWindow.setDockNestingEnabled(True)
# Set up the main container, which contains all the other form widgets. # Set up the main container, which contains all the other form widgets.
self.MainContent = QtGui.QWidget(mainWindow) self.MainContent = QtGui.QWidget(mainWindow)
@ -163,82 +163,82 @@ class Ui_MainWindow(object):
self.themeManagerDock) self.themeManagerDock)
# Create the menu items # Create the menu items
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_category(UiStrings.File, CategoryOrder.standardMenu) action_list.add_category(UiStrings().File, CategoryOrder.standardMenu)
self.FileNewItem = shortcut_action(mainWindow, u'FileNewItem', self.FileNewItem = shortcut_action(mainWindow, u'FileNewItem',
[QtGui.QKeySequence(u'Ctrl+N')], [QtGui.QKeySequence(u'Ctrl+N')],
self.ServiceManagerContents.onNewServiceClicked, self.ServiceManagerContents.onNewServiceClicked,
u':/general/general_new.png', category=UiStrings.File) u':/general/general_new.png', category=UiStrings().File)
self.FileOpenItem = shortcut_action(mainWindow, u'FileOpenItem', self.FileOpenItem = shortcut_action(mainWindow, u'FileOpenItem',
[QtGui.QKeySequence(u'Ctrl+O')], [QtGui.QKeySequence(u'Ctrl+O')],
self.ServiceManagerContents.onLoadServiceClicked, self.ServiceManagerContents.onLoadServiceClicked,
u':/general/general_open.png', category=UiStrings.File) u':/general/general_open.png', category=UiStrings().File)
self.FileSaveItem = shortcut_action(mainWindow, u'FileSaveItem', self.FileSaveItem = shortcut_action(mainWindow, u'FileSaveItem',
[QtGui.QKeySequence(u'Ctrl+S')], [QtGui.QKeySequence(u'Ctrl+S')],
self.ServiceManagerContents.saveFile, self.ServiceManagerContents.saveFile,
u':/general/general_save.png', category=UiStrings.File) u':/general/general_save.png', category=UiStrings().File)
self.FileSaveAsItem = shortcut_action(mainWindow, u'FileSaveAsItem', self.FileSaveAsItem = shortcut_action(mainWindow, u'FileSaveAsItem',
[QtGui.QKeySequence(u'Ctrl+Shift+S')], [QtGui.QKeySequence(u'Ctrl+Shift+S')],
self.ServiceManagerContents.saveFileAs, category=UiStrings.File) self.ServiceManagerContents.saveFileAs, category=UiStrings().File)
self.printServiceOrderItem = shortcut_action(mainWindow, self.printServiceOrderItem = shortcut_action(mainWindow,
u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')], u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')],
self.ServiceManagerContents.printServiceOrder, self.ServiceManagerContents.printServiceOrder,
category=UiStrings.File) category=UiStrings().File)
self.FileExitItem = shortcut_action(mainWindow, u'FileExitItem', self.FileExitItem = shortcut_action(mainWindow, u'FileExitItem',
[QtGui.QKeySequence(u'Alt+F4')], mainWindow.close, [QtGui.QKeySequence(u'Alt+F4')], mainWindow.close,
u':/system/system_exit.png', category=UiStrings.File) u':/system/system_exit.png', category=UiStrings().File)
action_list.add_category(UiStrings.Import, CategoryOrder.standardMenu) action_list.add_category(UiStrings().Import, CategoryOrder.standardMenu)
self.ImportThemeItem = base_action( self.ImportThemeItem = base_action(
mainWindow, u'ImportThemeItem', UiStrings.Import) mainWindow, u'ImportThemeItem', UiStrings().Import)
self.ImportLanguageItem = base_action( self.ImportLanguageItem = base_action(
mainWindow, u'ImportLanguageItem')#, UiStrings.Import) mainWindow, u'ImportLanguageItem')#, UiStrings().Import)
action_list.add_category(UiStrings.Export, CategoryOrder.standardMenu) action_list.add_category(UiStrings().Export, CategoryOrder.standardMenu)
self.ExportThemeItem = base_action( self.ExportThemeItem = base_action(
mainWindow, u'ExportThemeItem', UiStrings.Export) mainWindow, u'ExportThemeItem', UiStrings().Export)
self.ExportLanguageItem = base_action( self.ExportLanguageItem = base_action(
mainWindow, u'ExportLanguageItem')#, UiStrings.Export) mainWindow, u'ExportLanguageItem')#, UiStrings().Export)
action_list.add_category(UiStrings.View, CategoryOrder.standardMenu) action_list.add_category(UiStrings().View, CategoryOrder.standardMenu)
self.ViewMediaManagerItem = shortcut_action(mainWindow, self.ViewMediaManagerItem = shortcut_action(mainWindow,
u'ViewMediaManagerItem', [QtGui.QKeySequence(u'F8')], u'ViewMediaManagerItem', [QtGui.QKeySequence(u'F8')],
self.toggleMediaManager, u':/system/system_mediamanager.png', self.toggleMediaManager, u':/system/system_mediamanager.png',
self.mediaManagerDock.isVisible(), UiStrings.View) self.mediaManagerDock.isVisible(), UiStrings().View)
self.ViewThemeManagerItem = shortcut_action(mainWindow, self.ViewThemeManagerItem = shortcut_action(mainWindow,
u'ViewThemeManagerItem', [QtGui.QKeySequence(u'F10')], u'ViewThemeManagerItem', [QtGui.QKeySequence(u'F10')],
self.toggleThemeManager, u':/system/system_thememanager.png', self.toggleThemeManager, u':/system/system_thememanager.png',
self.themeManagerDock.isVisible(), UiStrings.View) self.themeManagerDock.isVisible(), UiStrings().View)
self.ViewServiceManagerItem = shortcut_action(mainWindow, self.ViewServiceManagerItem = shortcut_action(mainWindow,
u'ViewServiceManagerItem', [QtGui.QKeySequence(u'F9')], u'ViewServiceManagerItem', [QtGui.QKeySequence(u'F9')],
self.toggleServiceManager, u':/system/system_servicemanager.png', self.toggleServiceManager, u':/system/system_servicemanager.png',
self.serviceManagerDock.isVisible(), UiStrings.View) self.serviceManagerDock.isVisible(), UiStrings().View)
self.ViewPreviewPanel = shortcut_action(mainWindow, self.ViewPreviewPanel = shortcut_action(mainWindow,
u'ViewPreviewPanel', [QtGui.QKeySequence(u'F11')], u'ViewPreviewPanel', [QtGui.QKeySequence(u'F11')],
self.setPreviewPanelVisibility, checked=previewVisible, self.setPreviewPanelVisibility, checked=previewVisible,
category=UiStrings.View) category=UiStrings().View)
self.ViewLivePanel = shortcut_action(mainWindow, u'ViewLivePanel', self.ViewLivePanel = shortcut_action(mainWindow, u'ViewLivePanel',
[QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility, [QtGui.QKeySequence(u'F12')], self.setLivePanelVisibility,
checked=liveVisible, category=UiStrings.View) checked=liveVisible, category=UiStrings().View)
action_list.add_category(UiStrings.ViewMode, CategoryOrder.standardMenu) action_list.add_category(UiStrings().ViewMode, CategoryOrder.standardMenu)
self.ModeDefaultItem = checkable_action( self.ModeDefaultItem = checkable_action(
mainWindow, u'ModeDefaultItem', category=UiStrings.ViewMode) mainWindow, u'ModeDefaultItem', category=UiStrings().ViewMode)
self.ModeSetupItem = checkable_action( self.ModeSetupItem = checkable_action(
mainWindow, u'ModeLiveItem', category=UiStrings.ViewMode) mainWindow, u'ModeLiveItem', category=UiStrings().ViewMode)
self.ModeLiveItem = checkable_action( self.ModeLiveItem = checkable_action(
mainWindow, u'ModeLiveItem', True, UiStrings.ViewMode) mainWindow, u'ModeLiveItem', True, UiStrings().ViewMode)
self.ModeGroup = QtGui.QActionGroup(mainWindow) self.ModeGroup = QtGui.QActionGroup(mainWindow)
self.ModeGroup.addAction(self.ModeDefaultItem) self.ModeGroup.addAction(self.ModeDefaultItem)
self.ModeGroup.addAction(self.ModeSetupItem) self.ModeGroup.addAction(self.ModeSetupItem)
self.ModeGroup.addAction(self.ModeLiveItem) self.ModeGroup.addAction(self.ModeLiveItem)
self.ModeDefaultItem.setChecked(True) self.ModeDefaultItem.setChecked(True)
action_list.add_category(UiStrings.Tools, CategoryOrder.standardMenu) action_list.add_category(UiStrings().Tools, CategoryOrder.standardMenu)
self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem', self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem',
u':/tools/tools_add.png', category=UiStrings.Tools) u':/tools/tools_add.png', category=UiStrings().Tools)
self.ToolsOpenDataFolder = icon_action(mainWindow, self.ToolsOpenDataFolder = icon_action(mainWindow,
u'ToolsOpenDataFolder', u':/general/general_open.png', u'ToolsOpenDataFolder', u':/general/general_open.png',
category=UiStrings.Tools) category=UiStrings().Tools)
action_list.add_category(UiStrings.Settings, CategoryOrder.standardMenu) action_list.add_category(UiStrings().Settings, CategoryOrder.standardMenu)
self.settingsPluginListItem = shortcut_action(mainWindow, self.settingsPluginListItem = shortcut_action(mainWindow,
u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')], u'settingsPluginListItem', [QtGui.QKeySequence(u'Alt+F7')],
self.onPluginItemClicked, u':/system/settings_plugin_list.png', self.onPluginItemClicked, u':/system/settings_plugin_list.png',
category=UiStrings.Settings) category=UiStrings().Settings)
# i18n Language Items # i18n Language Items
self.AutoLanguageItem = checkable_action(mainWindow, self.AutoLanguageItem = checkable_action(mainWindow,
u'AutoLanguageItem', LanguageManager.auto_language) u'AutoLanguageItem', LanguageManager.auto_language)
@ -255,25 +255,25 @@ class Ui_MainWindow(object):
self.SettingsShortcutsItem = icon_action(mainWindow, self.SettingsShortcutsItem = icon_action(mainWindow,
u'SettingsShortcutsItem', u'SettingsShortcutsItem',
u':/system/system_configure_shortcuts.png', u':/system/system_configure_shortcuts.png',
category=UiStrings.Settings) category=UiStrings().Settings)
self.DisplayTagItem = icon_action(mainWindow, self.DisplayTagItem = icon_action(mainWindow,
u'DisplayTagItem', u':/system/tag_editor.png', u'DisplayTagItem', u':/system/tag_editor.png',
category=UiStrings.Settings) category=UiStrings().Settings)
self.SettingsConfigureItem = icon_action(mainWindow, self.SettingsConfigureItem = icon_action(mainWindow,
u'SettingsConfigureItem', u':/system/system_settings.png', u'SettingsConfigureItem', u':/system/system_settings.png',
category=UiStrings.Settings) category=UiStrings().Settings)
action_list.add_category(UiStrings.Help, CategoryOrder.standardMenu) action_list.add_category(UiStrings().Help, CategoryOrder.standardMenu)
self.HelpDocumentationItem = icon_action(mainWindow, self.HelpDocumentationItem = icon_action(mainWindow,
u'HelpDocumentationItem', u':/system/system_help_contents.png', u'HelpDocumentationItem', u':/system/system_help_contents.png',
category=None)#UiStrings.Help) category=None)#UiStrings().Help)
self.HelpDocumentationItem.setEnabled(False) self.HelpDocumentationItem.setEnabled(False)
self.HelpAboutItem = shortcut_action(mainWindow, u'HelpAboutItem', self.HelpAboutItem = shortcut_action(mainWindow, u'HelpAboutItem',
[QtGui.QKeySequence(u'Ctrl+F1')], self.onHelpAboutItemClicked, [QtGui.QKeySequence(u'Ctrl+F1')], self.onHelpAboutItemClicked,
u':/system/system_about.png', category=UiStrings.Help) u':/system/system_about.png', category=UiStrings().Help)
self.HelpOnlineHelpItem = base_action( self.HelpOnlineHelpItem = base_action(
mainWindow, u'HelpOnlineHelpItem', category=UiStrings.Help) mainWindow, u'HelpOnlineHelpItem', category=UiStrings().Help)
self.helpWebSiteItem = base_action( self.helpWebSiteItem = base_action(
mainWindow, u'helpWebSiteItem', category=UiStrings.Help) mainWindow, u'helpWebSiteItem', category=UiStrings().Help)
add_actions(self.FileImportMenu, add_actions(self.FileImportMenu,
(self.ImportThemeItem, self.ImportLanguageItem)) (self.ImportThemeItem, self.ImportLanguageItem))
add_actions(self.FileExportMenu, add_actions(self.FileExportMenu,
@ -320,7 +320,7 @@ class Ui_MainWindow(object):
""" """
Set up the translation system Set up the translation system
""" """
mainWindow.mainTitle = UiStrings.OLPV2 mainWindow.mainTitle = UiStrings().OLPV2
mainWindow.setWindowTitle(mainWindow.mainTitle) mainWindow.setWindowTitle(mainWindow.mainTitle)
self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File')) self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import')) self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
@ -339,14 +339,14 @@ class Ui_MainWindow(object):
self.themeManagerDock.setWindowTitle( self.themeManagerDock.setWindowTitle(
translate('OpenLP.MainWindow', 'Theme Manager')) translate('OpenLP.MainWindow', 'Theme Manager'))
self.FileNewItem.setText(translate('OpenLP.MainWindow', '&New')) self.FileNewItem.setText(translate('OpenLP.MainWindow', '&New'))
self.FileNewItem.setToolTip(UiStrings.NewService) self.FileNewItem.setToolTip(UiStrings().NewService)
self.FileNewItem.setStatusTip(UiStrings.CreateService) self.FileNewItem.setStatusTip(UiStrings().CreateService)
self.FileOpenItem.setText(translate('OpenLP.MainWindow', '&Open')) self.FileOpenItem.setText(translate('OpenLP.MainWindow', '&Open'))
self.FileOpenItem.setToolTip(UiStrings.OpenService) self.FileOpenItem.setToolTip(UiStrings().OpenService)
self.FileOpenItem.setStatusTip( self.FileOpenItem.setStatusTip(
translate('OpenLP.MainWindow', 'Open an existing service.')) translate('OpenLP.MainWindow', 'Open an existing service.'))
self.FileSaveItem.setText(translate('OpenLP.MainWindow', '&Save')) self.FileSaveItem.setText(translate('OpenLP.MainWindow', '&Save'))
self.FileSaveItem.setToolTip(UiStrings.SaveService) self.FileSaveItem.setToolTip(UiStrings().SaveService)
self.FileSaveItem.setStatusTip( self.FileSaveItem.setStatusTip(
translate('OpenLP.MainWindow', 'Save the current service to disk.')) translate('OpenLP.MainWindow', 'Save the current service to disk.'))
self.FileSaveAsItem.setText( self.FileSaveAsItem.setText(
@ -355,7 +355,7 @@ class Ui_MainWindow(object):
translate('OpenLP.MainWindow', 'Save Service As')) translate('OpenLP.MainWindow', 'Save Service As'))
self.FileSaveAsItem.setStatusTip(translate('OpenLP.MainWindow', self.FileSaveAsItem.setStatusTip(translate('OpenLP.MainWindow',
'Save the current service under a new name.')) 'Save the current service under a new name.'))
self.printServiceOrderItem.setText(UiStrings.PrintServiceOrder) self.printServiceOrderItem.setText(UiStrings().PrintServiceOrder)
self.printServiceOrderItem.setStatusTip(translate('OpenLP.MainWindow', self.printServiceOrderItem.setStatusTip(translate('OpenLP.MainWindow',
'Print the current Service Order.')) 'Print the current Service Order.'))
self.FileExitItem.setText( self.FileExitItem.setText(
@ -545,9 +545,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'openlp_information_message'), QtCore.SIGNAL(u'openlp_information_message'),
self.onInformationMessage) self.onInformationMessage)
# warning cyclic dependency # warning cyclic dependency
# RenderManager needs to call ThemeManager and # renderer needs to call ThemeManager and
# ThemeManager needs to call RenderManager # ThemeManager needs to call Renderer
self.renderManager = RenderManager( self.renderer = Renderer(
self.themeManagerContents, self.screens) self.themeManagerContents, self.screens)
# Define the media Dock Manager # Define the media Dock Manager
self.mediaDockManager = MediaDockManager(self.MediaToolBox) self.mediaDockManager = MediaDockManager(self.MediaToolBox)
@ -555,7 +555,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# make the controllers available to the plugins # make the controllers available to the plugins
self.pluginHelpers[u'preview'] = self.previewController self.pluginHelpers[u'preview'] = self.previewController
self.pluginHelpers[u'live'] = self.liveController self.pluginHelpers[u'live'] = self.liveController
self.pluginHelpers[u'render'] = self.renderManager self.pluginHelpers[u'renderer'] = self.renderer
self.pluginHelpers[u'service'] = self.ServiceManagerContents self.pluginHelpers[u'service'] = self.ServiceManagerContents
self.pluginHelpers[u'settings form'] = self.settingsForm self.pluginHelpers[u'settings form'] = self.settingsForm
self.pluginHelpers[u'toolbox'] = self.mediaDockManager self.pluginHelpers[u'toolbox'] = self.mediaDockManager
@ -781,7 +781,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
their locations their locations
""" """
log.debug(u'screenChanged') log.debug(u'screenChanged')
self.renderManager.update_display() self.renderer.update_display()
self.setFocus() self.setFocus()
self.activateWindow() self.activateWindow()
@ -896,7 +896,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def toggleThemeManager(self): def toggleThemeManager(self):
self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible()) self.themeManagerDock.setVisible(not self.themeManagerDock.isVisible())
def setPreviewPanelVisibility(self, visible=None): def setPreviewPanelVisibility(self, visible):
""" """
Sets the visibility of the preview panel including saving the setting Sets the visibility of the preview panel including saving the setting
and updating the menu. and updating the menu.
@ -906,14 +906,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
True - Visible True - Visible
False - Hidden False - Hidden
""" """
if visible is None:
visible = self.ViewPreviewPanel.isVisible()
self.previewController.panel.setVisible(visible) self.previewController.panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/preview panel', QtCore.QSettings().setValue(u'user interface/preview panel',
QtCore.QVariant(visible)) QtCore.QVariant(visible))
self.ViewPreviewPanel.setChecked(visible) self.ViewPreviewPanel.setChecked(visible)
def setLivePanelVisibility(self, visible=None): def setLivePanelVisibility(self, visible):
""" """
Sets the visibility of the live panel including saving the setting and Sets the visibility of the live panel including saving the setting and
updating the menu. updating the menu.
@ -923,8 +921,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
True - Visible True - Visible
False - Hidden False - Hidden
""" """
if visible is None:
visible = self.ViewLivePanel.isVisible()
self.liveController.panel.setVisible(visible) self.liveController.panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/live panel', QtCore.QSettings().setValue(u'user interface/live panel',
QtCore.QVariant(visible)) QtCore.QVariant(visible))

View File

@ -78,11 +78,11 @@ class Ui_PluginViewDialog(object):
translate('OpenLP.PluginForm', 'Plugin List')) translate('OpenLP.PluginForm', 'Plugin List'))
self.pluginInfoGroupBox.setTitle( self.pluginInfoGroupBox.setTitle(
translate('OpenLP.PluginForm', 'Plugin Details')) translate('OpenLP.PluginForm', 'Plugin Details'))
self.versionLabel.setText(u'%s:' % UiStrings.Version) self.versionLabel.setText(u'%s:' % UiStrings().Version)
self.aboutLabel.setText(u'%s:' % UiStrings.About) self.aboutLabel.setText(u'%s:' % UiStrings().About)
self.statusLabel.setText( self.statusLabel.setText(
translate('OpenLP.PluginForm', 'Status:')) translate('OpenLP.PluginForm', 'Status:'))
self.statusComboBox.setItemText(0, self.statusComboBox.setItemText(0,
translate('OpenLP.PluginForm', 'Active')) translate('OpenLP.PluginForm', 'Active'))
self.statusComboBox.setItemText(1, self.statusComboBox.setItemText(1,
translate('OpenLP.PluginForm', 'Inactive')) translate('OpenLP.PluginForm', 'Inactive'))

View File

@ -148,7 +148,7 @@ class Ui_PrintServiceDialog(object):
QtCore.SIGNAL(u'toggled(bool)'), self.toggleOptions) QtCore.SIGNAL(u'toggled(bool)'), self.toggleOptions)
def retranslateUi(self, printServiceDialog): def retranslateUi(self, printServiceDialog):
printServiceDialog.setWindowTitle(UiStrings.PrintServiceOrder) printServiceDialog.setWindowTitle(UiStrings().PrintServiceOrder)
self.slideTextCheckBox.setText(translate('OpenLP.PrintServiceForm', self.slideTextCheckBox.setText(translate('OpenLP.PrintServiceForm',
'Include slide text if available')) 'Include slide text if available'))
self.pageBreakAfterText.setText(translate('OpenLP.PrintServiceForm', self.pageBreakAfterText.setText(translate('OpenLP.PrintServiceForm',
@ -164,4 +164,4 @@ class Ui_PrintServiceDialog(object):
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.OneHundred]) self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.OneHundred])
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.SeventyFive]) self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.SeventyFive])
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Fifty]) self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Fifty])
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.TwentyFive]) self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.TwentyFive])

View File

@ -46,41 +46,58 @@ http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties
color:black; color:black;
} }
.item {
color:black;
}
.itemTitle { .itemTitle {
font-weight:600; font-weight:600;
font-size:large; font-size:large;
color:black;
} }
.itemText { .itemText {}
color:black;
}
.itemFooter { .itemFooter {
font-size:8px; font-size:8px;
color:black;
} }
.itemNotes {}
.itemNotesTitle { .itemNotesTitle {
font-weight:bold; font-weight:bold;
font-size:12px; font-size:12px;
color:black;
} }
.itemNotesText { .itemNotesText {
font-size:11px; font-size:11px;
color:black; }
.media {}
.mediaTitle {
font-weight:bold;
font-size:11px;
}
.mediaText {}
.imageList {}
.customNotes {
margin-top: 10px;
} }
.customNotesTitle { .customNotesTitle {
font-weight:bold; font-weight:bold;
font-size:11px; font-size:11px;
color:black;
} }
.customNotesText { .customNotesText {
font-size:11px; font-size:11px;
color:black; }
.newPage {
page-break-before:always;
} }
""" """
@ -153,86 +170,90 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
""" """
Creates the html text and updates the html of *self.document*. Creates the html text and updates the html of *self.document*.
""" """
html_data = html.fromstring( html_data = self._addElement(u'html')
u'<title>%s</title>' % unicode(self.titleLineEdit.text())) self._addElement(u'head', parent=html_data)
self._addElement(u'title', unicode(self.titleLineEdit.text()),
html_data.head)
css_path = os.path.join( css_path = os.path.join(
AppLocation.get_data_path(), u'servicePrint.css') AppLocation.get_data_path(), u'service_print.css')
if not os.path.isfile(css_path):
# Create default css file.
css_file = open(css_path, u'w')
css_file.write(DEFAULT_CSS)
css_file.close()
custom_css = get_text_file_string(css_path) custom_css = get_text_file_string(css_path)
self._addChildToParent( if not custom_css:
u'style', custom_css, html_data.head, u'type', u'text/css') custom_css = DEFAULT_CSS
self._addChildToParent(u'body', parent=html_data) self._addElement(u'style', custom_css, html_data.head,
self._addChildToParent(u'span', unicode(self.titleLineEdit.text()), attribute=(u'type', u'text/css'))
html_data.body, u'class', u'serviceTitle') self._addElement(u'body', parent=html_data)
self._addElement(u'h1', unicode(self.titleLineEdit.text()),
html_data.body, classId=u'serviceTitle')
for index, item in enumerate(self.serviceManager.serviceItems): for index, item in enumerate(self.serviceManager.serviceItems):
item = item[u'service_item'] self._addPreviewItem(html_data.body, item[u'service_item'], index)
div = self._addChildToParent(u'div', parent=html_data.body)
# Add the title of the service item.
item_title = self._addChildToParent(
u'h2', parent=div, attribute=u'class', value=u'itemTitle')
self._addChildToParent(
u'img', parent=item_title, attribute=u'src', value=item.icon)
self._fromstring(
u'<span> %s</span>' % item.get_display_title(), item_title)
if self.slideTextCheckBox.isChecked():
# Add the text of the service item.
if item.is_text():
verse_def = None
for slide in item.get_frames():
if not verse_def or verse_def != slide[u'verseTag']:
p = self._addChildToParent(u'p', parent=div,
attribute=u'class', value=u'itemText')
else:
self._addChildToParent(u'br', parent=p)
self._fromstring(u'<span>%s</span>' % slide[u'html'], p)
verse_def = slide[u'verseTag']
# Break the page before the div element.
if index != 0 and self.pageBreakAfterText.isChecked():
div.set(u'style', u'page-break-before:always')
# Add the image names of the service item.
elif item.is_image():
ol = self._addChildToParent(u'ol', parent=div)
for slide in range(len(item.get_frames())):
self._addChildToParent(u'li', item.get_frame_title(slide), ol)
# add footer
if item.foot_text:
self._fromstring(
item.foot_text, div, u'class', u'itemFooter')
# Add service items' notes.
if self.notesCheckBox.isChecked():
if item.notes:
p = self._addChildToParent(u'p', parent=div)
self._addChildToParent(u'span', unicode(
translate('OpenLP.ServiceManager', 'Notes:')), p,
u'class', u'itemNotesTitle')
self._fromstring(u'<span> %s</span>' % item.notes.replace(
u'\n', u'<br />'), p, u'class', u'itemNotesText')
# Add play length of media files.
if item.is_media() and self.metaDataCheckBox.isChecked():
tme = item.media_length
if item.end_time > 0:
tme = item.end_time - item.start_time
title = self._fromstring(u'<p><strong>%s</strong> </p>' %
translate('OpenLP.ServiceManager', 'Playing time:'), div)
self._fromstring(u'<span>%s</span>' %
unicode(datetime.timedelta(seconds=tme)), title)
# Add the custom service notes: # Add the custom service notes:
if self.footerTextEdit.toPlainText(): if self.footerTextEdit.toPlainText():
div = self._addChildToParent(u'div', parent=html_data.body) div = self._addElement(u'div', parent=html_data.body,
self._addChildToParent(u'span', translate('OpenLP.ServiceManager', classId=u'customNotes')
u'Custom Service Notes:'), div, u'class', u'customNotesTitle') self._addElement(u'span', translate('OpenLP.ServiceManager',
self._addChildToParent( 'Custom Service Notes: '), div, classId=u'customNotesTitle')
u'span', u' %s' % self.footerTextEdit.toPlainText(), div, self._addElement(u'span', self.footerTextEdit.toPlainText(), div,
u'class', u'customNotesText') classId=u'customNotesText')
self.document.setHtml(html.tostring(html_data)) self.document.setHtml(html.tostring(html_data))
self.previewWidget.updatePreview() self.previewWidget.updatePreview()
def _addChildToParent(self, tag, text=None, parent=None, attribute=None, def _addPreviewItem(self, body, item, index):
value=None): div = self._addElement(u'div', classId=u'item', parent=body)
# Add the title of the service item.
item_title = self._addElement(u'h2', parent=div, classId=u'itemTitle')
self._addElement(u'img', parent=item_title,
attribute=(u'src', item.icon))
self._addElement(u'span', u'&nbsp;' + item.get_display_title(),
item_title)
if self.slideTextCheckBox.isChecked():
# Add the text of the service item.
if item.is_text():
verse_def = None
for slide in item.get_frames():
if not verse_def or verse_def != slide[u'verseTag']:
p = self._addElement(u'div', parent=div,
classId=u'itemText')
else:
self._addElement(u'br', parent=p)
self._addElement(u'p', slide[u'html'], p)
verse_def = slide[u'verseTag']
# Break the page before the div element.
if index != 0 and self.pageBreakAfterText.isChecked():
div.set(u'class', u'item newPage')
# Add the image names of the service item.
elif item.is_image():
ol = self._addElement(u'ol', parent=div, classId=u'imageList')
for slide in range(len(item.get_frames())):
self._addElement(u'li', item.get_frame_title(slide), ol)
# add footer
foot_text = item.foot_text
foot_text = foot_text.partition(u'<br>')[2]
if foot_text:
foot = self._addElement(u'div', foot_text, parent=div,
classId=u'itemFooter')
# Add service items' notes.
if self.notesCheckBox.isChecked():
if item.notes:
p = self._addElement(u'div', classId=u'itemNotes', parent=div)
self._addElement(u'span',
translate('OpenLP.ServiceManager', 'Notes: '), p,
classId=u'itemNotesTitle')
notes = self._addElement(u'span',
item.notes.replace(u'\n', u'<br />'), p,
classId=u'itemNotesText')
# Add play length of media files.
if item.is_media() and self.metaDataCheckBox.isChecked():
tme = item.media_length
if item.end_time > 0:
tme = item.end_time - item.start_time
title = self._addElement(u'div', classId=u'media', parent=div)
self._addElement(u'span', translate('OpenLP.ServiceManager',
'Playing time: '), title, classId=u'mediaTitle')
self._addElement(u'span', unicode(datetime.timedelta(seconds=tme)),
title, classId=u'mediaText')
def _addElement(self, tag, text=None, parent=None, classId=None,
attribute=None):
""" """
Creates a html element. If ``text`` is given, the element's text will Creates a html element. If ``text`` is given, the element's text will
set and if a ``parent`` is given, the element is appended. set and if a ``parent`` is given, the element is appended.
@ -246,30 +267,22 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
``parent`` ``parent``
The parent element. Defaults to ``None``. The parent element. Defaults to ``None``.
``attribute`` ``classId``
An optional attribute, for instance ``u'class``. Value for the class attribute
``value`` ``attribute``
The value for the given ``attribute``. It does not have a meaning, Tuple name/value pair to add as an optional attribute
if the attribute is left to its default.
""" """
element = html.Element(tag)
if text is not None: if text is not None:
element.text = unicode(text) element = html.fragment_fromstring(unicode(text), create_parent=tag)
else:
element = html.Element(tag)
if parent is not None: if parent is not None:
parent.append(element) parent.append(element)
if classId is not None:
element.set(u'class', classId)
if attribute is not None: if attribute is not None:
element.set(attribute, value if value is not None else u'') element.set(attribute[0], attribute[1])
return element
def _fromstring(self, string, parent, attribute=None, value=None):
"""
This is used to create a child html element from a string.
"""
element = html.fromstring(string)
if attribute is not None:
element.set(attribute, value if value is not None else u'')
parent.append(element)
return element return element
def paintRequested(self, printer): def paintRequested(self, printer):
@ -354,9 +367,9 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
Called when html copy check box is selected. Called when html copy check box is selected.
""" """
if value == QtCore.Qt.Checked: if value == QtCore.Qt.Checked:
self.copyTextButton.setText(UiStrings.CopyToHtml) self.copyTextButton.setText(UiStrings().CopyToHtml)
else: else:
self.copyTextButton.setText(UiStrings.CopyToText) self.copyTextButton.setText(UiStrings().CopyToText)
def onSlideTextCheckBoxChanged(self, state): def onSlideTextCheckBoxChanged(self, state):
""" """

View File

@ -111,18 +111,18 @@ class ServiceManager(QtGui.QWidget):
# Create the top toolbar # Create the top toolbar
self.toolbar = OpenLPToolbar(self) self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton( self.toolbar.addToolbarButton(
UiStrings.NewService, u':/general/general_new.png', UiStrings().NewService, u':/general/general_new.png',
UiStrings.CreateService, self.onNewServiceClicked) UiStrings().CreateService, self.onNewServiceClicked)
self.toolbar.addToolbarButton( self.toolbar.addToolbarButton(
UiStrings.OpenService, u':/general/general_open.png', UiStrings().OpenService, u':/general/general_open.png',
translate('OpenLP.ServiceManager', 'Load an existing service'), translate('OpenLP.ServiceManager', 'Load an existing service'),
self.onLoadServiceClicked) self.onLoadServiceClicked)
self.toolbar.addToolbarButton( self.toolbar.addToolbarButton(
UiStrings.SaveService, u':/general/general_save.png', UiStrings().SaveService, u':/general/general_save.png',
translate('OpenLP.ServiceManager', 'Save this service'), translate('OpenLP.ServiceManager', 'Save this service'),
self.saveFile) self.saveFile)
self.toolbar.addSeparator() self.toolbar.addSeparator()
self.themeLabel = QtGui.QLabel(u'%s:' % UiStrings.Theme, self) self.themeLabel = QtGui.QLabel(u'%s:' % UiStrings().Theme, self)
self.themeLabel.setMargin(3) self.themeLabel.setMargin(3)
self.themeLabel.setObjectName(u'themeLabel') self.themeLabel.setObjectName(u'themeLabel')
self.toolbar.addToolbarWidget(u'ThemeLabel', self.themeLabel) self.toolbar.addToolbarWidget(u'ThemeLabel', self.themeLabel)
@ -169,9 +169,10 @@ class ServiceManager(QtGui.QWidget):
self.onServiceTop, shortcuts=[QtCore.Qt.Key_Home]) self.onServiceTop, shortcuts=[QtCore.Qt.Key_Home])
self.serviceManagerList.moveTop.setObjectName(u'moveTop') self.serviceManagerList.moveTop.setObjectName(u'moveTop')
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_category(UiStrings.Service, CategoryOrder.standardToolbar) action_list.add_category(
UiStrings().Service, CategoryOrder.standardToolbar)
action_list.add_action( action_list.add_action(
self.serviceManagerList.moveTop, UiStrings.Service) self.serviceManagerList.moveTop, UiStrings().Service)
self.serviceManagerList.moveUp = self.orderToolbar.addToolbarButton( self.serviceManagerList.moveUp = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Move &up'), translate('OpenLP.ServiceManager', 'Move &up'),
u':/services/service_up.png', u':/services/service_up.png',
@ -179,7 +180,8 @@ class ServiceManager(QtGui.QWidget):
'Move item up one position in the service.'), 'Move item up one position in the service.'),
self.onServiceUp, shortcuts=[QtCore.Qt.Key_PageUp]) self.onServiceUp, shortcuts=[QtCore.Qt.Key_PageUp])
self.serviceManagerList.moveUp.setObjectName(u'moveUp') self.serviceManagerList.moveUp.setObjectName(u'moveUp')
action_list.add_action(self.serviceManagerList.moveUp, UiStrings.Service) action_list.add_action(
self.serviceManagerList.moveUp, UiStrings().Service)
self.serviceManagerList.moveDown = self.orderToolbar.addToolbarButton( self.serviceManagerList.moveDown = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Move &down'), translate('OpenLP.ServiceManager', 'Move &down'),
u':/services/service_down.png', u':/services/service_down.png',
@ -188,7 +190,7 @@ class ServiceManager(QtGui.QWidget):
self.onServiceDown, shortcuts=[QtCore.Qt.Key_PageDown]) self.onServiceDown, shortcuts=[QtCore.Qt.Key_PageDown])
self.serviceManagerList.moveDown.setObjectName(u'moveDown') self.serviceManagerList.moveDown.setObjectName(u'moveDown')
action_list.add_action( action_list.add_action(
self.serviceManagerList.moveDown, UiStrings.Service) self.serviceManagerList.moveDown, UiStrings().Service)
self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarButton( self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Move to &bottom'), translate('OpenLP.ServiceManager', 'Move to &bottom'),
u':/services/service_bottom.png', u':/services/service_bottom.png',
@ -197,7 +199,7 @@ class ServiceManager(QtGui.QWidget):
self.onServiceEnd, shortcuts=[QtCore.Qt.Key_End]) self.onServiceEnd, shortcuts=[QtCore.Qt.Key_End])
self.serviceManagerList.moveBottom.setObjectName(u'moveBottom') self.serviceManagerList.moveBottom.setObjectName(u'moveBottom')
action_list.add_action( action_list.add_action(
self.serviceManagerList.moveBottom, UiStrings.Service) self.serviceManagerList.moveBottom, UiStrings().Service)
self.serviceManagerList.down = self.orderToolbar.addToolbarButton( self.serviceManagerList.down = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Move &down'), translate('OpenLP.ServiceManager', 'Move &down'),
None, None,
@ -231,7 +233,8 @@ class ServiceManager(QtGui.QWidget):
'Expand all the service items.'), 'Expand all the service items.'),
self.onExpandAll, shortcuts=[QtCore.Qt.Key_Plus]) self.onExpandAll, shortcuts=[QtCore.Qt.Key_Plus])
self.serviceManagerList.expand.setObjectName(u'expand') self.serviceManagerList.expand.setObjectName(u'expand')
action_list.add_action(self.serviceManagerList.expand, UiStrings.Service) action_list.add_action(
self.serviceManagerList.expand, UiStrings().Service)
self.serviceManagerList.collapse = self.orderToolbar.addToolbarButton( self.serviceManagerList.collapse = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', '&Collapse all'), translate('OpenLP.ServiceManager', '&Collapse all'),
u':/services/service_collapse_all.png', u':/services/service_collapse_all.png',
@ -240,7 +243,7 @@ class ServiceManager(QtGui.QWidget):
self.onCollapseAll, shortcuts=[QtCore.Qt.Key_Minus]) self.onCollapseAll, shortcuts=[QtCore.Qt.Key_Minus])
self.serviceManagerList.collapse.setObjectName(u'collapse') self.serviceManagerList.collapse.setObjectName(u'collapse')
action_list.add_action( action_list.add_action(
self.serviceManagerList.collapse, UiStrings.Service) self.serviceManagerList.collapse, UiStrings().Service)
self.orderToolbar.addSeparator() self.orderToolbar.addSeparator()
self.serviceManagerList.makeLive = self.orderToolbar.addToolbarButton( self.serviceManagerList.makeLive = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Go Live'), translate('OpenLP.ServiceManager', 'Go Live'),
@ -250,7 +253,7 @@ class ServiceManager(QtGui.QWidget):
shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return]) shortcuts=[QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return])
self.serviceManagerList.makeLive.setObjectName(u'orderToolbar') self.serviceManagerList.makeLive.setObjectName(u'orderToolbar')
action_list.add_action( action_list.add_action(
self.serviceManagerList.makeLive, UiStrings.Service) self.serviceManagerList.makeLive, UiStrings().Service)
self.layout.addWidget(self.orderToolbar) self.layout.addWidget(self.orderToolbar)
# Connect up our signals and slots # Connect up our signals and slots
QtCore.QObject.connect(self.themeComboBox, QtCore.QObject.connect(self.themeComboBox,
@ -344,7 +347,8 @@ class ServiceManager(QtGui.QWidget):
has been modified. has been modified.
""" """
self._modified = modified self._modified = modified
serviceFile = self.shortFileName() or u'Untitled Service' serviceFile = self.shortFileName() or translate(
'OpenLP.ServiceManager', 'Untitled Service')
self.mainwindow.setServiceModified(modified, serviceFile) self.mainwindow.setServiceModified(modified, serviceFile)
def isModified(self): def isModified(self):
@ -525,7 +529,7 @@ class ServiceManager(QtGui.QWidget):
save the file. save the file.
""" """
fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow, fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow,
UiStrings.SaveService, UiStrings().SaveService,
SettingsManager.get_last_dir( SettingsManager.get_last_dir(
self.mainwindow.serviceSettingsSection), self.mainwindow.serviceSettingsSection),
translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)')))
@ -575,7 +579,7 @@ class ServiceManager(QtGui.QWidget):
for item in items: for item in items:
serviceItem = ServiceItem() serviceItem = ServiceItem()
serviceItem.from_service = True serviceItem.from_service = True
serviceItem.render_manager = self.mainwindow.renderManager serviceItem.renderer = self.mainwindow.renderer
serviceItem.set_from_service(item, self.servicePath) serviceItem.set_from_service(item, self.servicePath)
self.validateItem(serviceItem) self.validateItem(serviceItem)
self.addServiceItem(serviceItem) self.addServiceItem(serviceItem)
@ -611,7 +615,7 @@ class ServiceManager(QtGui.QWidget):
u'%s' % fileName) u'%s' % fileName)
QtGui.QMessageBox.information(self, QtGui.QMessageBox.information(self,
translate('OpenLP.ServiceManager', 'Corrupt File'), translate('OpenLP.ServiceManager', 'Corrupt File'),
translate('OpenLP.ServiceManager', 'This file is either' translate('OpenLP.ServiceManager', 'This file is either '
'corrupt or not an OpenLP 2.0 service file.')) 'corrupt or not an OpenLP 2.0 service file.'))
return return
finally: finally:
@ -682,6 +686,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems[item][u'service_item'].notes = \ self.serviceItems[item][u'service_item'].notes = \
self.serviceNoteForm.textEdit.toPlainText() self.serviceNoteForm.textEdit.toPlainText()
self.repaintServiceList(item, -1) self.repaintServiceList(item, -1)
self.setModified()
def onStartTimeForm(self): def onStartTimeForm(self):
item = self.findServiceItem()[0] item = self.findServiceItem()[0]
@ -785,7 +790,7 @@ class ServiceManager(QtGui.QWidget):
# Top Item was selected so set the last one # Top Item was selected so set the last one
if setLastItem: if setLastItem:
lastItem.setSelected(True) lastItem.setSelected(True)
self.setModified(True) self.setModified()
def onMoveSelectionDown(self): def onMoveSelectionDown(self):
""" """
@ -807,7 +812,7 @@ class ServiceManager(QtGui.QWidget):
serviceIterator += 1 serviceIterator += 1
if setSelected: if setSelected:
firstItem.setSelected(True) firstItem.setSelected(True)
self.setModified(True) self.setModified()
def onCollapseAll(self): def onCollapseAll(self):
""" """
@ -851,7 +856,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(0, temp) self.serviceItems.insert(0, temp)
self.repaintServiceList(0, child) self.repaintServiceList(0, child)
self.setModified(True) self.setModified()
def onServiceUp(self): def onServiceUp(self):
""" """
@ -863,7 +868,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(item - 1, temp) self.serviceItems.insert(item - 1, temp)
self.repaintServiceList(item - 1, child) self.repaintServiceList(item - 1, child)
self.setModified(True) self.setModified()
def onServiceDown(self): def onServiceDown(self):
""" """
@ -875,7 +880,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(item + 1, temp) self.serviceItems.insert(item + 1, temp)
self.repaintServiceList(item + 1, child) self.repaintServiceList(item + 1, child)
self.setModified(True) self.setModified()
def onServiceEnd(self): def onServiceEnd(self):
""" """
@ -887,7 +892,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(len(self.serviceItems), temp) self.serviceItems.insert(len(self.serviceItems), temp)
self.repaintServiceList(len(self.serviceItems) - 1, child) self.repaintServiceList(len(self.serviceItems) - 1, child)
self.setModified(True) self.setModified()
def onDeleteFromService(self): def onDeleteFromService(self):
""" """
@ -897,7 +902,7 @@ class ServiceManager(QtGui.QWidget):
if item != -1: if item != -1:
self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.remove(self.serviceItems[item])
self.repaintServiceList(item - 1, -1) self.repaintServiceList(item - 1, -1)
self.setModified(True) self.setModified()
def repaintServiceList(self, serviceItem, serviceItemChild): def repaintServiceList(self, serviceItem, serviceItemChild):
""" """
@ -984,7 +989,7 @@ class ServiceManager(QtGui.QWidget):
""" """
log.debug(u'onThemeComboBoxSelected') log.debug(u'onThemeComboBoxSelected')
self.service_theme = unicode(self.themeComboBox.currentText()) self.service_theme = unicode(self.themeComboBox.currentText())
self.mainwindow.renderManager.set_service_theme(self.service_theme) self.mainwindow.renderer.set_service_theme(self.service_theme)
QtCore.QSettings().setValue( QtCore.QSettings().setValue(
self.mainwindow.serviceSettingsSection + u'/service theme', self.mainwindow.serviceSettingsSection + u'/service theme',
QtCore.QVariant(self.service_theme)) QtCore.QVariant(self.service_theme))
@ -996,7 +1001,7 @@ class ServiceManager(QtGui.QWidget):
sure the theme combo box is in the correct state. sure the theme combo box is in the correct state.
""" """
log.debug(u'themeChange') log.debug(u'themeChange')
if self.mainwindow.renderManager.theme_level == ThemeLevel.Global: if self.mainwindow.renderer.theme_level == ThemeLevel.Global:
self.toolbar.actions[u'ThemeLabel'].setVisible(False) self.toolbar.actions[u'ThemeLabel'].setVisible(False)
self.toolbar.actions[u'ThemeWidget'].setVisible(False) self.toolbar.actions[u'ThemeWidget'].setVisible(False)
else: else:
@ -1011,7 +1016,7 @@ class ServiceManager(QtGui.QWidget):
Receiver.send_message(u'cursor_busy') Receiver.send_message(u'cursor_busy')
log.debug(u'regenerateServiceItems') log.debug(u'regenerateServiceItems')
# force reset of renderer as theme data has changed # force reset of renderer as theme data has changed
self.mainwindow.renderManager.themedata = None self.mainwindow.renderer.themedata = None
if self.serviceItems: if self.serviceItems:
tempServiceItems = self.serviceItems tempServiceItems = self.serviceItems
self.serviceManagerList.clear() self.serviceManagerList.clear()
@ -1022,7 +1027,7 @@ class ServiceManager(QtGui.QWidget):
item[u'service_item'], False, expand=item[u'expanded']) item[u'service_item'], False, expand=item[u'expanded'])
# Set to False as items may have changed rendering # Set to False as items may have changed rendering
# does not impact the saved song so True may also be valid # does not impact the saved song so True may also be valid
self.setModified(True) self.setModified()
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
def serviceItemUpdate(self, message): def serviceItemUpdate(self, message):
@ -1033,7 +1038,7 @@ class ServiceManager(QtGui.QWidget):
for item in self.serviceItems: for item in self.serviceItems:
if item[u'service_item']._uuid == uuid: if item[u'service_item']._uuid == uuid:
item[u'service_item'].edit_id = int(editId) item[u'service_item'].edit_id = int(editId)
self.setModified(True) self.setModified()
def replaceServiceItem(self, newItem): def replaceServiceItem(self, newItem):
""" """
@ -1049,7 +1054,7 @@ class ServiceManager(QtGui.QWidget):
self.repaintServiceList(itemcount + 1, 0) self.repaintServiceList(itemcount + 1, 0)
self.mainwindow.liveController.replaceServiceManagerItem( self.mainwindow.liveController.replaceServiceManagerItem(
newItem) newItem)
self.setModified(True) self.setModified()
def addServiceItem(self, item, rebuild=False, expand=None, replace=False): def addServiceItem(self, item, rebuild=False, expand=None, replace=False):
""" """
@ -1094,7 +1099,7 @@ class ServiceManager(QtGui.QWidget):
if rebuild: if rebuild:
self.mainwindow.liveController.replaceServiceManagerItem(item) self.mainwindow.liveController.replaceServiceManagerItem(item)
self.dropPosition = 0 self.dropPosition = 0
self.setModified(True) self.setModified()
def makePreview(self): def makePreview(self):
""" """
@ -1231,7 +1236,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.remove(serviceItem) self.serviceItems.remove(serviceItem)
self.serviceItems.insert(endpos, serviceItem) self.serviceItems.insert(endpos, serviceItem)
self.repaintServiceList(endpos, child) self.repaintServiceList(endpos, child)
self.setModified(True) self.setModified()
else: else:
# we are not over anything so drop # we are not over anything so drop
replace = False replace = False
@ -1273,7 +1278,7 @@ class ServiceManager(QtGui.QWidget):
self.onThemeChangeAction, context=QtCore.Qt.WidgetShortcut) self.onThemeChangeAction, context=QtCore.Qt.WidgetShortcut)
self.themeMenu.addAction(action) self.themeMenu.addAction(action)
find_and_set_in_combo_box(self.themeComboBox, self.service_theme) find_and_set_in_combo_box(self.themeComboBox, self.service_theme)
self.mainwindow.renderManager.set_service_theme(self.service_theme) self.mainwindow.renderer.set_service_theme(self.service_theme)
self.regenerateServiceItems() self.regenerateServiceItems()
def onThemeChangeAction(self): def onThemeChangeAction(self):

View File

@ -37,7 +37,7 @@ class Ui_SettingsDialog(object):
build_icon(u':/system/system_settings.png')) build_icon(u':/system/system_settings.png'))
self.dialogLayout = QtGui.QGridLayout(settingsDialog) self.dialogLayout = QtGui.QGridLayout(settingsDialog)
self.dialogLayout.setObjectName(u'dialogLayout') self.dialogLayout.setObjectName(u'dialogLayout')
self.dialogLayout.setMargin(0) self.dialogLayout.setMargin(8)
self.settingListWidget = QtGui.QListWidget(settingsDialog) self.settingListWidget = QtGui.QListWidget(settingsDialog)
self.settingListWidget.setUniformItemSizes(True) self.settingListWidget.setUniformItemSizes(True)
self.settingListWidget.setMinimumSize(QtCore.QSize(150, 0)) self.settingListWidget.setMinimumSize(QtCore.QSize(150, 0))

View File

@ -75,6 +75,7 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
Add a tab to the form at a specific location Add a tab to the form at a specific location
""" """
log.debug(u'Inserting %s tab' % tab.tabTitle) log.debug(u'Inserting %s tab' % tab.tabTitle)
# add the tab to get it to display in the correct part of the screen
pos = self.stackedLayout.addWidget(tab) pos = self.stackedLayout.addWidget(tab)
if is_active: if is_active:
item_name = QtGui.QListWidgetItem(tab.tabTitleVisible) item_name = QtGui.QListWidgetItem(tab.tabTitleVisible)
@ -82,7 +83,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
item_name.setIcon(icon) item_name.setIcon(icon)
self.settingListWidget.insertItem(location, item_name) self.settingListWidget.insertItem(location, item_name)
else: else:
self.stackedLayout.takeAt(location) # then remove tab to stop the UI displaying it even if
# it is not required.
self.stackedLayout.takeAt(pos)
def accept(self): def accept(self):
""" """

View File

@ -29,6 +29,7 @@ import re
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver
from openlp.core.utils import translate from openlp.core.utils import translate
from openlp.core.utils.actions import ActionList from openlp.core.utils.actions import ActionList
from shortcutlistdialog import Ui_ShortcutListDialog from shortcutlistdialog import Ui_ShortcutListDialog
@ -95,43 +96,7 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
QtCore.Qt.ShiftModifier: QtCore.Qt.ShiftModifier:
key_string = u'Shift+' + key_string key_string = u'Shift+' + key_string
key_sequence = QtGui.QKeySequence(key_string) key_sequence = QtGui.QKeySequence(key_string)
# The action we are attempting to change. if self._validiate_shortcut(self._currentItemAction(), key_sequence):
changing_action = self._currentItemAction()
shortcut_valid = True
for category in self.action_list.categories:
for action in category.actions:
shortcuts = self._actionShortcuts(action)
if key_sequence not in shortcuts:
continue
if action is changing_action:
if self.primaryPushButton.isChecked() and \
shortcuts.index(key_sequence) == 0:
continue
if self.alternatePushButton.isChecked() and \
shortcuts.index(key_sequence) == 1:
continue
# Have the same parent, thus they cannot have the same shortcut.
if action.parent() is changing_action.parent():
shortcut_valid = False
# The new shortcut is already assigned, but if both shortcuts
# are only valid in a different widget the new shortcut is
# vaild, because they will not interfere.
if action.shortcutContext() in [QtCore.Qt.WindowShortcut,
QtCore.Qt.ApplicationShortcut]:
shortcut_valid = False
if changing_action.shortcutContext() in \
[QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
shortcut_valid = False
if not shortcut_valid:
QtGui.QMessageBox.warning(self,
translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
unicode(translate('OpenLP.ShortcutListDialog', 'The shortcut '
'"%s" is already assigned to another action, please '
'use a different shortcut.')) % key_sequence.toString(),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok
)
else:
if self.primaryPushButton.isChecked(): if self.primaryPushButton.isChecked():
self._adjustButton(self.primaryPushButton, self._adjustButton(self.primaryPushButton,
False, text=key_sequence.toString()) False, text=key_sequence.toString())
@ -227,6 +192,12 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
new_shortcuts.append( new_shortcuts.append(
QtGui.QKeySequence(self.alternatePushButton.text())) QtGui.QKeySequence(self.alternatePushButton.text()))
self.changedActions[action] = new_shortcuts self.changedActions[action] = new_shortcuts
if not self.primaryPushButton.text():
# When we do not have a primary shortcut, the just entered alternate
# shortcut will automatically become the primary shortcut. That is
# why we have to adjust the primary button's text.
self.primaryPushButton.setText(self.alternatePushButton.text())
self.alternatePushButton.setText(u'')
self.refreshShortcutList() self.refreshShortcutList()
def onItemDoubleClicked(self, item, column): def onItemDoubleClicked(self, item, column):
@ -374,6 +345,16 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
new_shortcuts = [] new_shortcuts = []
if len(action.defaultShortcuts) != 0: if len(action.defaultShortcuts) != 0:
new_shortcuts.append(action.defaultShortcuts[0]) new_shortcuts.append(action.defaultShortcuts[0])
# We have to check if the primary default shortcut is available. But
# we only have to check, if the action has a default primary
# shortcut (an "empty" shortcut is always valid and if the action
# does not have a default primary shortcut, then the alternative
# shortcut (not the default one) will become primary shortcut, thus
# the check will assume that an action were going to have the same
# shortcut twice.
if not self._validiate_shortcut(action, new_shortcuts[0]) and \
new_shortcuts[0] != shortcuts[0]:
return
if len(shortcuts) == 2: if len(shortcuts) == 2:
new_shortcuts.append(shortcuts[1]) new_shortcuts.append(shortcuts[1])
self.changedActions[action] = new_shortcuts self.changedActions[action] = new_shortcuts
@ -394,10 +375,60 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
new_shortcuts.append(shortcuts[0]) new_shortcuts.append(shortcuts[0])
if len(action.defaultShortcuts) == 2: if len(action.defaultShortcuts) == 2:
new_shortcuts.append(action.defaultShortcuts[1]) new_shortcuts.append(action.defaultShortcuts[1])
if len(new_shortcuts) == 2:
if not self._validiate_shortcut(action, new_shortcuts[1]):
return
self.changedActions[action] = new_shortcuts self.changedActions[action] = new_shortcuts
self.refreshShortcutList() self.refreshShortcutList()
self.onCurrentItemChanged(self.treeWidget.currentItem()) self.onCurrentItemChanged(self.treeWidget.currentItem())
def _validiate_shortcut(self, changing_action, key_sequence):
"""
Checks if the given ``changing_action `` can use the given
``key_sequence``. Returns ``True`` if the ``key_sequence`` can be used
by the action, otherwise displays a dialog and returns ``False``.
``changing_action``
The action which wants to use the ``key_sequence``.
``key_sequence``
The key sequence which the action want so use.
"""
is_valid = True
for category in self.action_list.categories:
for action in category.actions:
shortcuts = self._actionShortcuts(action)
if key_sequence not in shortcuts:
continue
if action is changing_action:
if self.primaryPushButton.isChecked() and \
shortcuts.index(key_sequence) == 0:
continue
if self.alternatePushButton.isChecked() and \
shortcuts.index(key_sequence) == 1:
continue
# Have the same parent, thus they cannot have the same shortcut.
if action.parent() is changing_action.parent():
is_valid = False
# The new shortcut is already assigned, but if both shortcuts
# are only valid in a different widget the new shortcut is
# vaild, because they will not interfere.
if action.shortcutContext() in [QtCore.Qt.WindowShortcut,
QtCore.Qt.ApplicationShortcut]:
is_valid = False
if changing_action.shortcutContext() in \
[QtCore.Qt.WindowShortcut, QtCore.Qt.ApplicationShortcut]:
is_valid = False
if not is_valid:
Receiver.send_message(u'openlp_warning_message', {
u'title': translate('OpenLP.ShortcutListDialog',
'Duplicate Shortcut'),
u'message': unicode(translate('OpenLP.ShortcutListDialog',
'The shortcut "%s" is already assigned to another action, '
'please use a different shortcut.')) % key_sequence.toString()
})
return is_valid
def _actionShortcuts(self, action): def _actionShortcuts(self, action):
""" """
This returns the shortcuts for the given ``action``, which also includes This returns the shortcuts for the given ``action``, which also includes

View File

@ -88,11 +88,11 @@ class SlideController(QtGui.QWidget):
# Type label for the top of the slide controller # Type label for the top of the slide controller
self.typeLabel = QtGui.QLabel(self.panel) self.typeLabel = QtGui.QLabel(self.panel)
if self.isLive: if self.isLive:
self.typeLabel.setText(UiStrings.Live) self.typeLabel.setText(UiStrings().Live)
self.split = 1 self.split = 1
self.typePrefix = u'live' self.typePrefix = u'live'
else: else:
self.typeLabel.setText(UiStrings.Preview) self.typeLabel.setText(UiStrings().Preview)
self.split = 0 self.split = 0
self.typePrefix = u'preview' self.typePrefix = u'preview'
self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;') self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;')
@ -161,18 +161,18 @@ class SlideController(QtGui.QWidget):
translate('OpenLP.SlideController', 'Hide'), self.toolbar)) translate('OpenLP.SlideController', 'Hide'), self.toolbar))
self.blankScreen = shortcut_action(self.hideMenu, u'blankScreen', self.blankScreen = shortcut_action(self.hideMenu, u'blankScreen',
[QtCore.Qt.Key_Period], self.onBlankDisplay, [QtCore.Qt.Key_Period], self.onBlankDisplay,
u':/slides/slide_blank.png', False, UiStrings.LiveToolbar) u':/slides/slide_blank.png', False, UiStrings().LiveToolbar)
self.blankScreen.setText( self.blankScreen.setText(
translate('OpenLP.SlideController', 'Blank Screen')) translate('OpenLP.SlideController', 'Blank Screen'))
self.themeScreen = shortcut_action(self.hideMenu, u'themeScreen', self.themeScreen = shortcut_action(self.hideMenu, u'themeScreen',
[QtGui.QKeySequence(u'T')], self.onThemeDisplay, [QtGui.QKeySequence(u'T')], self.onThemeDisplay,
u':/slides/slide_theme.png', False, UiStrings.LiveToolbar) u':/slides/slide_theme.png', False, UiStrings().LiveToolbar)
self.themeScreen.setText( self.themeScreen.setText(
translate('OpenLP.SlideController', 'Blank to Theme')) translate('OpenLP.SlideController', 'Blank to Theme'))
self.desktopScreen = shortcut_action(self.hideMenu, self.desktopScreen = shortcut_action(self.hideMenu,
u'desktopScreen', [QtGui.QKeySequence(u'D')], u'desktopScreen', [QtGui.QKeySequence(u'D')],
self.onHideDisplay, u':/slides/slide_desktop.png', False, self.onHideDisplay, u':/slides/slide_desktop.png', False,
UiStrings.LiveToolbar) UiStrings().LiveToolbar)
self.desktopScreen.setText( self.desktopScreen.setText(
translate('OpenLP.SlideController', 'Show Desktop')) translate('OpenLP.SlideController', 'Show Desktop'))
self.hideMenu.setDefaultAction(self.blankScreen) self.hideMenu.setDefaultAction(self.blankScreen)
@ -180,21 +180,30 @@ class SlideController(QtGui.QWidget):
self.hideMenu.menu().addAction(self.themeScreen) self.hideMenu.menu().addAction(self.themeScreen)
self.hideMenu.menu().addAction(self.desktopScreen) self.hideMenu.menu().addAction(self.desktopScreen)
self.toolbar.addToolbarSeparator(u'Loop Separator') self.toolbar.addToolbarSeparator(u'Loop Separator')
self.toolbar.addToolbarButton( startLoop = self.toolbar.addToolbarButton(
# Does not need translating - control string. # Does not need translating - control string.
u'Start Loop', u':/media/media_time.png', u'Start Loop', u':/media/media_time.png',
translate('OpenLP.SlideController', 'Start continuous loop'), translate('OpenLP.SlideController', 'Start continuous loop'),
self.onStartLoop) self.onStartLoop)
self.toolbar.addToolbarButton( action_list = ActionList.get_instance()
action_list.add_action(startLoop, UiStrings().LiveToolbar)
stopLoop = self.toolbar.addToolbarButton(
# Does not need translating - control string. # Does not need translating - control string.
u'Stop Loop', u':/media/media_stop.png', u'Stop Loop', u':/media/media_stop.png',
translate('OpenLP.SlideController', 'Stop continuous loop'), translate('OpenLP.SlideController', 'Stop continuous loop'),
self.onStopLoop) self.onStopLoop)
action_list.add_action(stopLoop, UiStrings().LiveToolbar)
self.toogleLoop = shortcut_action(self, u'toogleLoop',
[QtGui.QKeySequence(u'L')], self.onToggleLoop,
category=UiStrings().LiveToolbar)
self.toogleLoop.setText(translate('OpenLP.SlideController',
'Start/Stop continuous loop'))
self.addAction(self.toogleLoop)
self.delaySpinBox = QtGui.QSpinBox() self.delaySpinBox = QtGui.QSpinBox()
self.delaySpinBox.setMinimum(1) self.delaySpinBox.setMinimum(1)
self.delaySpinBox.setMaximum(180) self.delaySpinBox.setMaximum(180)
self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox) self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox)
self.delaySpinBox.setSuffix(UiStrings.Seconds) self.delaySpinBox.setSuffix(UiStrings().Seconds)
self.delaySpinBox.setToolTip(translate('OpenLP.SlideController', self.delaySpinBox.setToolTip(translate('OpenLP.SlideController',
'Delay between slides in seconds')) 'Delay between slides in seconds'))
else: else:
@ -376,22 +385,25 @@ class SlideController(QtGui.QWidget):
self.nextItem.setObjectName(u'nextItemLive') self.nextItem.setObjectName(u'nextItemLive')
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_category( action_list.add_category(
UiStrings.LiveToolbar, CategoryOrder.standardToolbar) UiStrings().LiveToolbar, CategoryOrder.standardToolbar)
action_list.add_action(self.previousItem) action_list.add_action(self.previousItem)
action_list.add_action(self.nextItem) action_list.add_action(self.nextItem)
self.previousService = shortcut_action(parent, u'previousService', self.previousService = shortcut_action(parent, u'previousService',
[QtCore.Qt.Key_Left], self.servicePrevious, UiStrings.LiveToolbar) [QtCore.Qt.Key_Left], self.servicePrevious,
self.previousService.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) category=UiStrings().LiveToolbar,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.previousService.setText( self.previousService.setText(
translate('OpenLP.SlideController', 'Previous Service')) translate('OpenLP.SlideController', 'Previous Service'))
self.nextService = shortcut_action(parent, 'nextService', self.nextService = shortcut_action(parent, 'nextService',
[QtCore.Qt.Key_Right], self.serviceNext, UiStrings.LiveToolbar) [QtCore.Qt.Key_Right], self.serviceNext,
self.nextService.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) category=UiStrings().LiveToolbar,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.nextService.setText( self.nextService.setText(
translate('OpenLP.SlideController', 'Next Service')) translate('OpenLP.SlideController', 'Next Service'))
self.escapeItem = shortcut_action(parent, 'escapeItem', self.escapeItem = shortcut_action(parent, 'escapeItem',
[QtCore.Qt.Key_Escape], self.liveEscape, UiStrings.LiveToolbar) [QtCore.Qt.Key_Escape], self.liveEscape,
self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) category=UiStrings().LiveToolbar,
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.escapeItem.setText( self.escapeItem.setText(
translate('OpenLP.SlideController', 'Escape Item')) translate('OpenLP.SlideController', 'Escape Item'))
@ -412,7 +424,7 @@ class SlideController(QtGui.QWidget):
""" """
# 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.imageManager = self.parent.renderer.image_manager
self.display.alertTab = self.alertTab self.display.alertTab = self.alertTab
self.display.setup() self.display.setup()
if self.isLive: if self.isLive:
@ -491,6 +503,9 @@ class SlideController(QtGui.QWidget):
self.mediabar.setVisible(False) self.mediabar.setVisible(False)
self.toolbar.makeWidgetsInvisible([u'Song Menu']) self.toolbar.makeWidgetsInvisible([u'Song Menu'])
self.toolbar.makeWidgetsInvisible(self.loopList) self.toolbar.makeWidgetsInvisible(self.loopList)
self.toogleLoop.setEnabled(False)
self.toolbar.actions[u'Start Loop'].setEnabled(False)
self.toolbar.actions[u'Stop Loop'].setEnabled(False)
self.toolbar.actions[u'Stop Loop'].setVisible(False) self.toolbar.actions[u'Stop Loop'].setVisible(False)
if item.is_text(): if item.is_text():
if QtCore.QSettings().value( if QtCore.QSettings().value(
@ -500,6 +515,9 @@ class SlideController(QtGui.QWidget):
if item.is_capable(ItemCapabilities.AllowsLoop) and \ if item.is_capable(ItemCapabilities.AllowsLoop) and \
len(item.get_frames()) > 1: len(item.get_frames()) > 1:
self.toolbar.makeWidgetsVisible(self.loopList) self.toolbar.makeWidgetsVisible(self.loopList)
self.toogleLoop.setEnabled(True)
self.toolbar.actions[u'Start Loop'].setEnabled(True)
self.toolbar.actions[u'Stop Loop'].setEnabled(True)
if item.is_media(): if item.is_media():
self.toolbar.setVisible(False) self.toolbar.setVisible(False)
self.mediabar.setVisible(True) self.mediabar.setVisible(True)
@ -614,19 +632,19 @@ class SlideController(QtGui.QWidget):
label.setScaledContents(True) label.setScaledContents(True)
if self.serviceItem.is_command(): if self.serviceItem.is_command():
image = resize_image(frame[u'image'], image = resize_image(frame[u'image'],
self.parent.renderManager.width, self.parent.renderer.width,
self.parent.renderManager.height) self.parent.renderer.height)
else: else:
# If current slide set background to image # If current slide set background to image
if framenumber == slideno: if framenumber == slideno:
self.serviceItem.bg_image_bytes = \ self.serviceItem.bg_image_bytes = \
self.parent.renderManager.image_manager. \ self.parent.renderer.image_manager. \
get_image_bytes(frame[u'title']) get_image_bytes(frame[u'title'])
image = self.parent.renderManager.image_manager. \ image = self.parent.renderer.image_manager. \
get_image(frame[u'title']) get_image(frame[u'title'])
label.setPixmap(QtGui.QPixmap.fromImage(image)) 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.renderer.screen_ratio
row += 1 row += 1
text.append(unicode(row)) text.append(unicode(row))
self.previewListWidget.setItem(framenumber, 0, item) self.previewListWidget.setItem(framenumber, 0, item)
@ -992,6 +1010,15 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.rowCount() - 1) self.previewListWidget.rowCount() - 1)
self.slideSelected() self.slideSelected()
def onToggleLoop(self, toggled):
"""
Toggles the loop state.
"""
if self.toolbar.actions[u'Start Loop'].isVisible():
self.onStartLoop()
else:
self.onStopLoop()
def onStartLoop(self): def onStartLoop(self):
""" """
Start the timer loop running and store the timer id Start the timer loop running and store the timer id

View File

@ -107,15 +107,15 @@ class Ui_StartTimeDialog(object):
def retranslateUi(self, StartTimeDialog): def retranslateUi(self, StartTimeDialog):
self.setWindowTitle(translate('OpenLP.StartTimeForm', self.setWindowTitle(translate('OpenLP.StartTimeForm',
'Item Start and Finish Time')) 'Item Start and Finish Time'))
self.hourSpinBox.setSuffix(UiStrings.Hours) self.hourSpinBox.setSuffix(UiStrings().Hours)
self.minuteSpinBox.setSuffix(UiStrings.Minutes) self.minuteSpinBox.setSuffix(UiStrings().Minutes)
self.secondSpinBox.setSuffix(UiStrings.Seconds) self.secondSpinBox.setSuffix(UiStrings().Seconds)
self.hourFinishSpinBox.setSuffix(UiStrings.Hours) self.hourFinishSpinBox.setSuffix(UiStrings().Hours)
self.minuteFinishSpinBox.setSuffix(UiStrings.Minutes) self.minuteFinishSpinBox.setSuffix(UiStrings().Minutes)
self.secondFinishSpinBox.setSuffix(UiStrings.Seconds) self.secondFinishSpinBox.setSuffix(UiStrings().Seconds)
self.hourLabel.setText(translate('OpenLP.StartTimeForm', 'Hours:')) self.hourLabel.setText(translate('OpenLP.StartTimeForm', 'Hours:'))
self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:')) self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:'))
self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:')) self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:'))
self.startLabel.setText(translate('OpenLP.StartTimeForm', 'Start')) self.startLabel.setText(translate('OpenLP.StartTimeForm', 'Start'))
self.finishLabel.setText(translate('OpenLP.StartTimeForm', 'Finish')) self.finishLabel.setText(translate('OpenLP.StartTimeForm', 'Finish'))
self.lengthLabel.setText(translate('OpenLP.StartTimeForm', 'Length')) self.lengthLabel.setText(translate('OpenLP.StartTimeForm', 'Length'))

View File

@ -53,11 +53,12 @@ class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
self.hourFinishSpinBox.setValue(hours) self.hourFinishSpinBox.setValue(hours)
self.minuteFinishSpinBox.setValue(minutes) self.minuteFinishSpinBox.setValue(minutes)
self.secondFinishSpinBox.setValue(seconds) self.secondFinishSpinBox.setValue(seconds)
self.hourFinishLabel.setText(u'%s%s' % (unicode(hour), UiStrings.Hours)) self.hourFinishLabel.setText(u'%s%s' % (unicode(hour),
UiStrings().Hours))
self.minuteFinishLabel.setText(u'%s%s' % self.minuteFinishLabel.setText(u'%s%s' %
(unicode(minutes), UiStrings.Minutes)) (unicode(minutes), UiStrings().Minutes))
self.secondFinishLabel.setText(u'%s%s' % self.secondFinishLabel.setText(u'%s%s' %
(unicode(seconds), UiStrings.Seconds)) (unicode(seconds), UiStrings().Seconds))
return QtGui.QDialog.exec_(self) return QtGui.QDialog.exec_(self)
def accept(self): def accept(self):

View File

@ -56,6 +56,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.setupUi(self) self.setupUi(self)
self.registerFields() self.registerFields()
self.updateThemeAllowed = True self.updateThemeAllowed = True
self.temp_background_filename = u''
QtCore.QObject.connect(self.backgroundComboBox, QtCore.QObject.connect(self.backgroundComboBox,
QtCore.SIGNAL(u'currentIndexChanged(int)'), QtCore.SIGNAL(u'currentIndexChanged(int)'),
self.onBackgroundComboBoxCurrentIndexChanged) self.onBackgroundComboBoxCurrentIndexChanged)
@ -279,6 +280,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
Run the wizard. Run the wizard.
""" """
log.debug(u'Editing theme %s' % self.theme.theme_name) log.debug(u'Editing theme %s' % self.theme.theme_name)
self.temp_background_filename = u''
self.updateThemeAllowed = False self.updateThemeAllowed = False
self.setDefaults() self.setDefaults()
self.updateThemeAllowed = True self.updateThemeAllowed = True
@ -290,7 +292,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
'Edit Theme - %s')) % self.theme.theme_name) 'Edit Theme - %s')) % self.theme.theme_name)
self.next() self.next()
else: else:
self.setWindowTitle(UiStrings.NewTheme) self.setWindowTitle(UiStrings().NewTheme)
return QtGui.QWizard.exec_(self) return QtGui.QWizard.exec_(self)
def initializePage(self, id): def initializePage(self, id):
@ -432,6 +434,16 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
# do not allow updates when screen is building for the first time. # do not allow updates when screen is building for the first time.
if self.updateThemeAllowed: if self.updateThemeAllowed:
self.theme.background_type = BackgroundType.to_string(index) self.theme.background_type = BackgroundType.to_string(index)
if self.theme.background_type != \
BackgroundType.to_string(BackgroundType.Image) and \
self.temp_background_filename == u'':
self.temp_background_filename = self.theme.background_filename
self.theme.background_filename = u''
if self.theme.background_type == \
BackgroundType.to_string(BackgroundType.Image) and \
self.temp_background_filename != u'':
self.theme.background_filename = self.temp_background_filename
self.temp_background_filename = u''
self.setBackgroundPageValues() self.setBackgroundPageValues()
def onGradientComboBoxCurrentIndexChanged(self, index): def onGradientComboBoxCurrentIndexChanged(self, index):
@ -473,7 +485,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
""" """
images_filter = get_images_filter() images_filter = get_images_filter()
images_filter = u'%s;;%s (*.*) (*)' % ( images_filter = u'%s;;%s (*.*) (*)' % (
images_filter, UiStrings.AllFiles) images_filter, UiStrings().AllFiles)
filename = QtGui.QFileDialog.getOpenFileName(self, filename = QtGui.QFileDialog.getOpenFileName(self,
translate('OpenLP.ThemeForm', 'Select Image'), u'', translate('OpenLP.ThemeForm', 'Select Image'), u'',
images_filter) images_filter)

View File

@ -63,7 +63,7 @@ class ThemeManager(QtGui.QWidget):
self.layout.setMargin(0) self.layout.setMargin(0)
self.layout.setObjectName(u'layout') self.layout.setObjectName(u'layout')
self.toolbar = OpenLPToolbar(self) self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton(UiStrings.NewTheme, self.toolbar.addToolbarButton(UiStrings().NewTheme,
u':/themes/theme_new.png', u':/themes/theme_new.png',
translate('OpenLP.ThemeManager', 'Create a new theme.'), translate('OpenLP.ThemeManager', 'Create a new theme.'),
self.onAddTheme) self.onAddTheme)
@ -280,6 +280,8 @@ class ThemeManager(QtGui.QWidget):
self.fileRenameForm.fileNameEdit.setText(oldThemeName) self.fileRenameForm.fileNameEdit.setText(oldThemeName)
if self.fileRenameForm.exec_(): if self.fileRenameForm.exec_():
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
if oldThemeName == newThemeName:
return
if self.checkIfThemeExists(newThemeName): if self.checkIfThemeExists(newThemeName):
oldThemeData = self.getThemeData(oldThemeName) oldThemeData = self.getThemeData(oldThemeName)
self.cloneThemeData(oldThemeData, newThemeName) self.cloneThemeData(oldThemeData, newThemeName)
@ -333,6 +335,7 @@ class ThemeManager(QtGui.QWidget):
self.oldBackgroundImage = theme.background_filename self.oldBackgroundImage = theme.background_filename
self.themeForm.theme = theme self.themeForm.theme = theme
self.themeForm.exec_(True) self.themeForm.exec_(True)
self.oldBackgroundImage = None
def onDeleteTheme(self): def onDeleteTheme(self):
""" """
@ -449,7 +452,7 @@ class ThemeManager(QtGui.QWidget):
# No themes have been found so create one # No themes have been found so create one
if len(files) == 0: if len(files) == 0:
theme = ThemeXML() theme = ThemeXML()
theme.theme_name = UiStrings.Default theme.theme_name = UiStrings().Default
self._writeTheme(theme, None, None) self._writeTheme(theme, None, None)
QtCore.QSettings().setValue( QtCore.QSettings().setValue(
self.settingsSection + u'/global theme', self.settingsSection + u'/global theme',
@ -657,7 +660,7 @@ class ThemeManager(QtGui.QWidget):
def generateImage(self, themeData, forcePage=False): def generateImage(self, themeData, forcePage=False):
""" """
Call the RenderManager to build a Sample Image Call the renderer to build a Sample Image
``themeData`` ``themeData``
The theme to generated a preview for. The theme to generated a preview for.
@ -666,7 +669,7 @@ class ThemeManager(QtGui.QWidget):
Flag to tell message lines per page need to be generated. Flag to tell message lines per page need to be generated.
""" """
log.debug(u'generateImage \n%s ', themeData) log.debug(u'generateImage \n%s ', themeData)
return self.mainwindow.renderManager.generate_preview( return self.mainwindow.renderer.generate_preview(
themeData, forcePage) themeData, forcePage)
def getPreviewImage(self, theme): def getPreviewImage(self, theme):
@ -803,4 +806,4 @@ class ThemeManager(QtGui.QWidget):
vAlignCorrection = VerticalType.Bottom vAlignCorrection = VerticalType.Bottom
newtheme.display_horizontal_align = theme.HorizontalAlign newtheme.display_horizontal_align = theme.HorizontalAlign
newtheme.display_vertical_align = vAlignCorrection newtheme.display_vertical_align = vAlignCorrection
return newtheme.extract_xml() return newtheme.extract_xml()

View File

@ -102,7 +102,7 @@ class ThemesTab(SettingsTab):
QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList) QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList)
def retranslateUi(self): def retranslateUi(self):
self.tabTitleVisible = UiStrings.Themes self.tabTitleVisible = UiStrings().Themes
self.GlobalGroupBox.setTitle( self.GlobalGroupBox.setTitle(
translate('OpenLP.ThemesTab', 'Global Theme')) translate('OpenLP.ThemesTab', 'Global Theme'))
self.LevelGroupBox.setTitle( self.LevelGroupBox.setTitle(
@ -149,7 +149,7 @@ class ThemesTab(SettingsTab):
settings.setValue(u'global theme', settings.setValue(u'global theme',
QtCore.QVariant(self.global_theme)) QtCore.QVariant(self.global_theme))
settings.endGroup() settings.endGroup()
self.mainwindow.renderManager.set_global_theme( self.mainwindow.renderer.set_global_theme(
self.global_theme, self.theme_level) self.global_theme, self.theme_level)
Receiver.send_message(u'theme_update_global', self.global_theme) Receiver.send_message(u'theme_update_global', self.global_theme)
@ -167,7 +167,7 @@ class ThemesTab(SettingsTab):
def onDefaultComboBoxChanged(self, value): def onDefaultComboBoxChanged(self, value):
self.global_theme = unicode(self.DefaultComboBox.currentText()) self.global_theme = unicode(self.DefaultComboBox.currentText())
self.mainwindow.renderManager.set_global_theme( self.mainwindow.renderer.set_global_theme(
self.global_theme, self.theme_level) self.global_theme, self.theme_level)
self.__previewGlobalTheme() self.__previewGlobalTheme()
@ -188,7 +188,7 @@ class ThemesTab(SettingsTab):
for theme in theme_list: for theme in theme_list:
self.DefaultComboBox.addItem(theme) self.DefaultComboBox.addItem(theme)
find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme) find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme)
self.mainwindow.renderManager.set_global_theme( self.mainwindow.renderer.set_global_theme(
self.global_theme, self.theme_level) self.global_theme, self.theme_level)
if self.global_theme is not u'': if self.global_theme is not u'':
self.__previewGlobalTheme() self.__previewGlobalTheme()

View File

@ -424,7 +424,7 @@ class Ui_ThemeWizard(object):
self.backgroundComboBox.setItemText(BackgroundType.Gradient, self.backgroundComboBox.setItemText(BackgroundType.Gradient,
translate('OpenLP.ThemeWizard', 'Gradient')) translate('OpenLP.ThemeWizard', 'Gradient'))
self.backgroundComboBox.setItemText( self.backgroundComboBox.setItemText(
BackgroundType.Image, UiStrings.Image) BackgroundType.Image, UiStrings().Image)
self.colorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.colorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:'))
self.gradientStartLabel.setText( self.gradientStartLabel.setText(
translate(u'OpenLP.ThemeWizard', 'Starting color:')) translate(u'OpenLP.ThemeWizard', 'Starting color:'))
@ -442,7 +442,7 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right')) translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right'))
self.gradientComboBox.setItemText(BackgroundGradientType.LeftBottom, self.gradientComboBox.setItemText(BackgroundGradientType.LeftBottom,
translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right')) translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right'))
self.imageLabel.setText(u'%s:' % UiStrings.Image) self.imageLabel.setText(u'%s:' % UiStrings().Image)
self.mainAreaPage.setTitle( self.mainAreaPage.setTitle(
translate('OpenLP.ThemeWizard', 'Main Area Font Details')) translate('OpenLP.ThemeWizard', 'Main Area Font Details'))
self.mainAreaPage.setSubTitle( self.mainAreaPage.setSubTitle(
@ -451,17 +451,17 @@ class Ui_ThemeWizard(object):
self.mainFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:')) self.mainFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:'))
self.mainColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.mainColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:'))
self.mainSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) self.mainSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:'))
self.mainSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.mainSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
self.lineSpacingLabel.setText( self.lineSpacingLabel.setText(
translate('OpenLP.ThemeWizard', 'Line Spacing:')) translate('OpenLP.ThemeWizard', 'Line Spacing:'))
self.lineSpacingSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.lineSpacingSpinBox.setSuffix(UiStrings().FontSizePtUnit)
self.outlineCheckBox.setText( self.outlineCheckBox.setText(
translate('OpenLP.ThemeWizard', '&Outline:')) translate('OpenLP.ThemeWizard', '&Outline:'))
self.outlineSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) self.outlineSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:'))
self.outlineSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.outlineSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
self.shadowCheckBox.setText(translate('OpenLP.ThemeWizard', '&Shadow:')) self.shadowCheckBox.setText(translate('OpenLP.ThemeWizard', '&Shadow:'))
self.shadowSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) self.shadowSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:'))
self.shadowSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.shadowSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
self.mainBoldCheckBox.setText(translate('OpenLP.ThemeWizard', 'Bold')) self.mainBoldCheckBox.setText(translate('OpenLP.ThemeWizard', 'Bold'))
self.mainItalicsCheckBox.setText( self.mainItalicsCheckBox.setText(
translate('OpenLP.ThemeWizard', 'Italic')) translate('OpenLP.ThemeWizard', 'Italic'))
@ -473,7 +473,7 @@ class Ui_ThemeWizard(object):
self.footerFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:')) self.footerFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:'))
self.footerColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.footerColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:'))
self.footerSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) self.footerSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:'))
self.footerSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.footerSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
self.alignmentPage.setTitle( self.alignmentPage.setTitle(
translate('OpenLP.ThemeWizard', 'Text Formatting Details')) translate('OpenLP.ThemeWizard', 'Text Formatting Details'))
self.alignmentPage.setSubTitle( self.alignmentPage.setSubTitle(
@ -537,4 +537,4 @@ class Ui_ThemeWizard(object):
labelWidth = max(self.backgroundLabel.minimumSizeHint().width(), labelWidth = max(self.backgroundLabel.minimumSizeHint().width(),
self.horizontalLabel.minimumSizeHint().width()) self.horizontalLabel.minimumSizeHint().width())
self.spacer.changeSize(labelWidth, 0, self.spacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)

View File

@ -95,6 +95,10 @@ class OpenLPWizard(QtGui.QWizard):
self.customSignals() self.customSignals()
QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'),
self.onCurrentIdChanged) self.onCurrentIdChanged)
QtCore.QObject.connect(self.errorCopyToButton,
QtCore.SIGNAL(u'clicked()'), self.onErrorCopyToButtonClicked)
QtCore.QObject.connect(self.errorSaveToButton,
QtCore.SIGNAL(u'clicked()'), self.onErrorSaveToButtonClicked)
def setupUi(self, image): def setupUi(self, image):
""" """
@ -129,10 +133,36 @@ class OpenLPWizard(QtGui.QWizard):
self.progressLayout.setObjectName(u'progressLayout') self.progressLayout.setObjectName(u'progressLayout')
self.progressLabel = QtGui.QLabel(self.progressPage) self.progressLabel = QtGui.QLabel(self.progressPage)
self.progressLabel.setObjectName(u'progressLabel') self.progressLabel.setObjectName(u'progressLabel')
self.progressLabel.setWordWrap(True)
self.progressLayout.addWidget(self.progressLabel) self.progressLayout.addWidget(self.progressLabel)
self.progressBar = QtGui.QProgressBar(self.progressPage) self.progressBar = QtGui.QProgressBar(self.progressPage)
self.progressBar.setObjectName(u'progressBar') self.progressBar.setObjectName(u'progressBar')
self.progressLayout.addWidget(self.progressBar) self.progressLayout.addWidget(self.progressBar)
# Add a QTextEdit and a copy to file and copy to clipboard button to be
# able to provide feedback to the user. Hidden by default.
self.errorReportTextEdit = QtGui.QTextEdit(self.progressPage)
self.errorReportTextEdit.setObjectName(u'progresserrorReportTextEdit')
self.errorReportTextEdit.setHidden(True)
self.errorReportTextEdit.setReadOnly(True)
self.progressLayout.addWidget(self.errorReportTextEdit)
self.errorButtonLayout = QtGui.QHBoxLayout()
self.errorButtonLayout.setObjectName(u'errorButtonLayout')
spacer = QtGui.QSpacerItem(40, 20,
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.errorButtonLayout.addItem(spacer)
self.errorCopyToButton = QtGui.QPushButton(self.progressPage)
self.errorCopyToButton.setObjectName(u'errorCopyToButton')
self.errorCopyToButton.setHidden(True)
self.errorCopyToButton.setIcon(
build_icon(u':/system/system_edit_copy.png'))
self.errorButtonLayout.addWidget(self.errorCopyToButton)
self.errorSaveToButton = QtGui.QPushButton(self.progressPage)
self.errorSaveToButton.setObjectName(u'errorSaveToButton')
self.errorSaveToButton.setHidden(True)
self.errorSaveToButton.setIcon(
build_icon(u':/general/general_save.png'))
self.errorButtonLayout.addWidget(self.errorSaveToButton)
self.progressLayout.addLayout(self.errorButtonLayout)
self.addPage(self.progressPage) self.addPage(self.progressPage)
def exec_(self): def exec_(self):
@ -160,6 +190,18 @@ class OpenLPWizard(QtGui.QWizard):
self.performWizard() self.performWizard()
self.postWizard() self.postWizard()
def onErrorCopyToButtonClicked(self):
"""
Called when the ``onErrorCopyToButtonClicked`` has been clicked.
"""
pass
def onErrorSaveToButtonClicked(self):
"""
Called when the ``onErrorSaveToButtonClicked`` has been clicked.
"""
pass
def incrementProgressBar(self, status_text, increment=1): def incrementProgressBar(self, status_text, increment=1):
""" """
Update the wizard progress page. Update the wizard progress page.
@ -212,7 +254,7 @@ class OpenLPWizard(QtGui.QWizard):
""" """
if filters: if filters:
filters += u';;' filters += u';;'
filters += u'%s (*)' % UiStrings.AllFiles filters += u'%s (*)' % UiStrings().AllFiles
filename = QtGui.QFileDialog.getOpenFileName(self, title, filename = QtGui.QFileDialog.getOpenFileName(self, title,
os.path.dirname(SettingsManager.get_last_dir( os.path.dirname(SettingsManager.get_last_dir(
self.plugin.settingsSection, 1)), filters) self.plugin.settingsSection, 1)), filters)
@ -220,3 +262,4 @@ class OpenLPWizard(QtGui.QWizard):
editbox.setText(filename) editbox.setText(filename)
SettingsManager.set_last_dir(self.plugin.settingsSection, SettingsManager.set_last_dir(self.plugin.settingsSection,
filename, 1) filename, 1)

View File

@ -77,7 +77,7 @@ class AlertsPlugin(Plugin):
Plugin.initialise(self) Plugin.initialise(self)
self.toolsAlertItem.setVisible(True) self.toolsAlertItem.setVisible(True)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(self.toolsAlertItem, UiStrings.Tools) action_list.add_action(self.toolsAlertItem, UiStrings().Tools)
self.liveController.alertTab = self.settings_tab self.liveController.alertTab = self.settings_tab
def finalise(self): def finalise(self):
@ -118,4 +118,4 @@ class AlertsPlugin(Plugin):
## Name for MediaDockManager, SettingsManager ## ## Name for MediaDockManager, SettingsManager ##
self.textStrings[StringContent.VisibleName] = { self.textStrings[StringContent.VisibleName] = {
u'title': translate('AlertsPlugin', 'Alerts', 'container title') u'title': translate('AlertsPlugin', 'Alerts', 'container title')
} }

View File

@ -61,6 +61,12 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
QtCore.QObject.connect(self.alertListWidget, QtCore.QObject.connect(self.alertListWidget,
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged) QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
def exec_(self):
self.displayButton.setEnabled(False)
self.displayCloseButton.setEnabled(False)
self.alertTextEdit.setText(u'')
return QtGui.QDialog.exec_(self)
def loadList(self): def loadList(self):
""" """
Loads the list with alerts. Loads the list with alerts.
@ -125,6 +131,12 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
# Only enable the button, if we are editing an item. # Only enable the button, if we are editing an item.
if self.item_id: if self.item_id:
self.saveButton.setEnabled(True) self.saveButton.setEnabled(True)
if self.alertTextEdit.text():
self.displayButton.setEnabled(True)
self.displayCloseButton.setEnabled(True)
else:
self.displayButton.setEnabled(False)
self.displayCloseButton.setEnabled(False)
def onDoubleClick(self): def onDoubleClick(self):
""" """

View File

@ -109,12 +109,12 @@ class AlertsTab(SettingsTab):
translate('AlertsPlugin.AlertsTab', 'Background color:')) translate('AlertsPlugin.AlertsTab', 'Background color:'))
self.FontSizeLabel.setText( self.FontSizeLabel.setText(
translate('AlertsPlugin.AlertsTab', 'Font size:')) translate('AlertsPlugin.AlertsTab', 'Font size:'))
self.FontSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.FontSizeSpinBox.setSuffix(UiStrings().FontSizePtUnit)
self.TimeoutLabel.setText( self.TimeoutLabel.setText(
translate('AlertsPlugin.AlertsTab', 'Alert timeout:')) translate('AlertsPlugin.AlertsTab', 'Alert timeout:'))
self.TimeoutSpinBox.setSuffix(UiStrings.Seconds) self.TimeoutSpinBox.setSuffix(UiStrings().Seconds)
self.PreviewGroupBox.setTitle(UiStrings.Preview) self.PreviewGroupBox.setTitle(UiStrings().Preview)
self.FontPreview.setText(UiStrings.OLPV2) self.FontPreview.setText(UiStrings().OLPV2)
def onBackgroundColorButtonClicked(self): def onBackgroundColorButtonClicked(self):
new_color = QtGui.QColorDialog.getColor( new_color = QtGui.QColorDialog.getColor(
@ -191,4 +191,4 @@ class AlertsTab(SettingsTab):
font.setPointSize(self.font_size) font.setPointSize(self.font_size)
self.FontPreview.setFont(font) self.FontPreview.setFont(font)
self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' % self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' %
(self.bg_color, self.font_color)) (self.bg_color, self.font_color))

View File

@ -53,9 +53,9 @@ class BiblePlugin(Plugin):
Plugin.initialise(self) Plugin.initialise(self)
self.importBibleItem.setVisible(True) self.importBibleItem.setVisible(True)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.add_action(self.importBibleItem, UiStrings.Import) action_list.add_action(self.importBibleItem, UiStrings().Import)
# Do not add the action to the list yet. # Do not add the action to the list yet.
#action_list.add_action(self.exportBibleItem, UiStrings.Export) #action_list.add_action(self.exportBibleItem, UiStrings().Export)
# Set to invisible until we can export bibles # Set to invisible until we can export bibles
self.exportBibleItem.setVisible(False) self.exportBibleItem.setVisible(False)
@ -67,9 +67,9 @@ class BiblePlugin(Plugin):
self.manager.finalise() self.manager.finalise()
Plugin.finalise(self) Plugin.finalise(self)
action_list = ActionList.get_instance() action_list = ActionList.get_instance()
action_list.remove_action(self.importBibleItem, UiStrings.Import) action_list.remove_action(self.importBibleItem, UiStrings().Import)
self.importBibleItem.setVisible(False) self.importBibleItem.setVisible(False)
#action_list.remove_action(self.exportBibleItem, UiStrings.Export) #action_list.remove_action(self.exportBibleItem, UiStrings().Export)
self.exportBibleItem.setVisible(False) self.exportBibleItem.setVisible(False)
def addImportMenuItem(self, import_menu): def addImportMenuItem(self, import_menu):
@ -146,4 +146,4 @@ class BiblePlugin(Plugin):
u'service': translate('BiblesPlugin', u'service': translate('BiblesPlugin',
'Add the selected Bible to the service') 'Add the selected Bible to the service')
} }
self.setPluginUiTextStrings(tooltips) self.setPluginUiTextStrings(tooltips)

View File

@ -377,7 +377,7 @@ class BibleImportForm(OpenLPWizard):
self.formatComboBox.setItemText(BibleFormat.OpenSong, WizardStrings.OS) self.formatComboBox.setItemText(BibleFormat.OpenSong, WizardStrings.OS)
self.formatComboBox.setItemText(BibleFormat.WebDownload, self.formatComboBox.setItemText(BibleFormat.WebDownload,
translate('BiblesPlugin.ImportWizardForm', 'Web Download')) translate('BiblesPlugin.ImportWizardForm', 'Web Download'))
self.formatComboBox.setItemText(BibleFormat.OpenLP1, UiStrings.OLPV1) self.formatComboBox.setItemText(BibleFormat.OpenLP1, UiStrings().OLPV1)
self.openlp1FileLabel.setText( self.openlp1FileLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Bible file:')) translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.osisFileLabel.setText( self.osisFileLabel.setText(
@ -451,13 +451,13 @@ class BibleImportForm(OpenLPWizard):
elif self.currentPage() == self.selectPage: elif self.currentPage() == self.selectPage:
if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS: if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS:
if not self.field(u'osis_location').toString(): if not self.field(u'osis_location').toString():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
WizardStrings.YouSpecifyFile % WizardStrings.OSIS) WizardStrings.YouSpecifyFile % WizardStrings.OSIS)
self.osisFileEdit.setFocus() self.osisFileEdit.setFocus()
return False return False
elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV: elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV:
if not self.field(u'csv_testamentsfile').toString(): if not self.field(u'csv_testamentsfile').toString():
answer = critical_error_message_box(UiStrings.NFSs, answer = critical_error_message_box(UiStrings().NFSs,
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'You have not specified a testaments file. Do you ' 'You have not specified a testaments file. Do you '
'want to proceed with the import?'), question=True) 'want to proceed with the import?'), question=True)
@ -465,14 +465,14 @@ class BibleImportForm(OpenLPWizard):
self.csvTestamentsEdit.setFocus() self.csvTestamentsEdit.setFocus()
return False return False
if not self.field(u'csv_booksfile').toString(): if not self.field(u'csv_booksfile').toString():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'You need to specify a file with books of ' 'You need to specify a file with books of '
'the Bible to use in the import.')) 'the Bible to use in the import.'))
self.csvBooksEdit.setFocus() self.csvBooksEdit.setFocus()
return False return False
elif not self.field(u'csv_versefile').toString(): elif not self.field(u'csv_versefile').toString():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'You need to specify a file of Bible ' 'You need to specify a file of Bible '
'verses to import.')) 'verses to import.'))
@ -481,14 +481,14 @@ class BibleImportForm(OpenLPWizard):
elif self.field(u'source_format').toInt()[0] == \ elif self.field(u'source_format').toInt()[0] == \
BibleFormat.OpenSong: BibleFormat.OpenSong:
if not self.field(u'opensong_file').toString(): if not self.field(u'opensong_file').toString():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
WizardStrings.YouSpecifyFile % WizardStrings.OS) WizardStrings.YouSpecifyFile % WizardStrings.OS)
self.openSongFileEdit.setFocus() self.openSongFileEdit.setFocus()
return False return False
elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1: elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1:
if not self.field(u'openlp1_location').toString(): if not self.field(u'openlp1_location').toString():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
WizardStrings.YouSpecifyFile % UiStrings.OLPV1) WizardStrings.YouSpecifyFile % UiStrings().OLPV1)
self.openlp1FileEdit.setFocus() self.openlp1FileEdit.setFocus()
return False return False
return True return True
@ -497,13 +497,13 @@ class BibleImportForm(OpenLPWizard):
license_copyright = \ license_copyright = \
unicode(self.field(u'license_copyright').toString()) unicode(self.field(u'license_copyright').toString())
if not license_version: if not license_version:
critical_error_message_box(UiStrings.EmptyField, critical_error_message_box(UiStrings().EmptyField,
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'You need to specify a version name for your Bible.')) 'You need to specify a version name for your Bible.'))
self.versionNameEdit.setFocus() self.versionNameEdit.setFocus()
return False return False
elif not license_copyright: elif not license_copyright:
critical_error_message_box(UiStrings.EmptyField, critical_error_message_box(UiStrings().EmptyField,
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'You need to set a copyright for your Bible. ' 'You need to set a copyright for your Bible. '
'Bibles in the Public Domain need to be marked as such.')) 'Bibles in the Public Domain need to be marked as such.'))
@ -576,7 +576,7 @@ class BibleImportForm(OpenLPWizard):
""" """
Show the file open dialog for the openlp.org 1.x file. Show the file open dialog for the openlp.org 1.x file.
""" """
self.getFileName(WizardStrings.OpenTypeFile % UiStrings.OLPV1, self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV1,
self.openlp1FileEdit, u'%s (*.bible)' % self.openlp1FileEdit, u'%s (*.bible)' %
translate('BiblesPlugin.ImportWizardForm', translate('BiblesPlugin.ImportWizardForm',
'openlp.org 1.x Bible Files')) 'openlp.org 1.x Bible Files'))
@ -765,4 +765,4 @@ class BibleImportForm(OpenLPWizard):
self.progressLabel.setText(translate( self.progressLabel.setText(translate(
'BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) 'BiblesPlugin.ImportWizardForm', 'Your Bible import failed.'))
del self.manager.db_cache[importer.name] del self.manager.db_cache[importer.name]
delete_database(self.plugin.settingsSection, importer.file) delete_database(self.plugin.settingsSection, importer.file)

View File

@ -118,16 +118,16 @@ class BiblesTab(SettingsTab):
self.newChaptersCheckBox.setText( self.newChaptersCheckBox.setText(
translate('BiblesPlugin.BiblesTab', translate('BiblesPlugin.BiblesTab',
'Only show new chapter numbers')) 'Only show new chapter numbers'))
self.layoutStyleLabel.setText(UiStrings.LayoutStyle) self.layoutStyleLabel.setText(UiStrings().LayoutStyle)
self.displayStyleLabel.setText(UiStrings.DisplayStyle) self.displayStyleLabel.setText(UiStrings().DisplayStyle)
self.bibleThemeLabel.setText( self.bibleThemeLabel.setText(
translate('BiblesPlugin.BiblesTab', 'Bible theme:')) translate('BiblesPlugin.BiblesTab', 'Bible theme:'))
self.layoutStyleComboBox.setItemText(LayoutStyle.VersePerSlide, self.layoutStyleComboBox.setItemText(LayoutStyle.VersePerSlide,
UiStrings.VersePerSlide) UiStrings().VersePerSlide)
self.layoutStyleComboBox.setItemText(LayoutStyle.VersePerLine, self.layoutStyleComboBox.setItemText(LayoutStyle.VersePerLine,
UiStrings.VersePerLine) UiStrings().VersePerLine)
self.layoutStyleComboBox.setItemText(LayoutStyle.Continuous, self.layoutStyleComboBox.setItemText(LayoutStyle.Continuous,
UiStrings.Continuous) UiStrings().Continuous)
self.displayStyleComboBox.setItemText(DisplayStyle.NoBrackets, self.displayStyleComboBox.setItemText(DisplayStyle.NoBrackets,
translate('BiblesPlugin.BiblesTab', 'No Brackets')) translate('BiblesPlugin.BiblesTab', 'No Brackets'))
self.displayStyleComboBox.setItemText(DisplayStyle.Round, self.displayStyleComboBox.setItemText(DisplayStyle.Round,
@ -207,4 +207,4 @@ class BiblesTab(SettingsTab):
self.bibleThemeComboBox.addItem(u'') self.bibleThemeComboBox.addItem(u'')
for theme in theme_list: for theme in theme_list:
self.bibleThemeComboBox.addItem(theme) self.bibleThemeComboBox.addItem(theme)
find_and_set_in_combo_box(self.bibleThemeComboBox, self.bible_theme) find_and_set_in_combo_box(self.bibleThemeComboBox, self.bible_theme)

View File

@ -193,7 +193,7 @@ class BibleMediaItem(MediaManagerItem):
self.advancedSearchButtonLayout.addWidget(self.advancedSearchButton) self.advancedSearchButtonLayout.addWidget(self.advancedSearchButton)
self.advancedLayout.addLayout( self.advancedLayout.addLayout(
self.advancedSearchButtonLayout, 7, 0, 1, 3) self.advancedSearchButtonLayout, 7, 0, 1, 3)
self.searchTabWidget.addTab(self.advancedTab, UiStrings.Advanced) self.searchTabWidget.addTab(self.advancedTab, UiStrings().Advanced)
# Add the search tab widget to the page layout. # Add the search tab widget to the page layout.
self.pageLayout.addWidget(self.searchTabWidget) self.pageLayout.addWidget(self.searchTabWidget)
# Combo Boxes # Combo Boxes
@ -242,15 +242,15 @@ class BibleMediaItem(MediaManagerItem):
def retranslateUi(self): def retranslateUi(self):
log.debug(u'retranslateUi') log.debug(u'retranslateUi')
self.quickVersionLabel.setText(u'%s:' % UiStrings.Version) self.quickVersionLabel.setText(u'%s:' % UiStrings().Version)
self.quickSecondLabel.setText( self.quickSecondLabel.setText(
translate('BiblesPlugin.MediaItem', 'Second:')) translate('BiblesPlugin.MediaItem', 'Second:'))
self.quickSearchLabel.setText( self.quickSearchLabel.setText(
translate('BiblesPlugin.MediaItem', 'Find:')) translate('BiblesPlugin.MediaItem', 'Find:'))
self.quickSearchButton.setText(UiStrings.Search) self.quickSearchButton.setText(UiStrings().Search)
self.quickClearLabel.setText( self.quickClearLabel.setText(
translate('BiblesPlugin.MediaItem', 'Results:')) translate('BiblesPlugin.MediaItem', 'Results:'))
self.advancedVersionLabel.setText(u'%s:' % UiStrings.Version) self.advancedVersionLabel.setText(u'%s:' % UiStrings().Version)
self.advancedSecondLabel.setText( self.advancedSecondLabel.setText(
translate('BiblesPlugin.MediaItem', 'Second:')) translate('BiblesPlugin.MediaItem', 'Second:'))
self.advancedBookLabel.setText( self.advancedBookLabel.setText(
@ -265,7 +265,7 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', 'To:')) translate('BiblesPlugin.MediaItem', 'To:'))
self.advancedClearLabel.setText( self.advancedClearLabel.setText(
translate('BiblesPlugin.MediaItem', 'Results:')) translate('BiblesPlugin.MediaItem', 'Results:'))
self.advancedSearchButton.setText(UiStrings.Search) self.advancedSearchButton.setText(UiStrings().Search)
self.quickClearComboBox.addItem( self.quickClearComboBox.addItem(
translate('BiblesPlugin.MediaItem', 'Clear')) translate('BiblesPlugin.MediaItem', 'Clear'))
self.quickClearComboBox.addItem( self.quickClearComboBox.addItem(
@ -274,13 +274,13 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', 'Clear')) translate('BiblesPlugin.MediaItem', 'Clear'))
self.advancedClearComboBox.addItem( self.advancedClearComboBox.addItem(
translate('BiblesPlugin.MediaItem', 'Keep')) translate('BiblesPlugin.MediaItem', 'Keep'))
self.quickLayoutLabel.setText(UiStrings.LayoutStyle) self.quickLayoutLabel.setText(UiStrings().LayoutStyle)
self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerSlide, self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerSlide,
UiStrings.VersePerSlide) UiStrings().VersePerSlide)
self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerLine, self.quickLayoutComboBox.setItemText(LayoutStyle.VersePerLine,
UiStrings.VersePerLine) UiStrings().VersePerLine)
self.quickLayoutComboBox.setItemText(LayoutStyle.Continuous, self.quickLayoutComboBox.setItemText(LayoutStyle.Continuous,
UiStrings.Continuous) UiStrings().Continuous)
def initialise(self): def initialise(self):
log.debug(u'bible manager initialise') log.debug(u'bible manager initialise')
@ -723,6 +723,7 @@ class BibleMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.NoLineBreaks) service_item.add_capability(ItemCapabilities.NoLineBreaks)
service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop) service_item.add_capability(ItemCapabilities.AllowsLoop)
service_item.add_capability(ItemCapabilities.AllowsWordSplit)
# Service Item: Title # Service Item: Title
service_item.title = u', '.join(raw_title) service_item.title = u', '.join(raw_title)
# Service Item: Theme # Service Item: Theme

View File

@ -37,6 +37,9 @@ from openlp.plugins.bibles.lib.db import BibleDB
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def replacement(match):
return match.group(2).upper()
class OSISBible(BibleDB): class OSISBible(BibleDB):
""" """
`OSIS <http://www.bibletechnologies.net/>`_ Bible format importer class. `OSIS <http://www.bibletechnologies.net/>`_ Bible format importer class.
@ -60,6 +63,7 @@ class OSISBible(BibleDB):
self.lg_regex = re.compile(r'<lg(.*?)>') self.lg_regex = re.compile(r'<lg(.*?)>')
self.l_regex = re.compile(r'<l (.*?)>') self.l_regex = re.compile(r'<l (.*?)>')
self.w_regex = re.compile(r'<w (.*?)>') self.w_regex = re.compile(r'<w (.*?)>')
self.q_regex = re.compile(r'<q(.*?)>')
self.q1_regex = re.compile(r'<q(.*?)level="1"(.*?)>') self.q1_regex = re.compile(r'<q(.*?)level="1"(.*?)>')
self.q2_regex = re.compile(r'<q(.*?)level="2"(.*?)>') self.q2_regex = re.compile(r'<q(.*?)level="2"(.*?)>')
self.trans_regex = re.compile(r'<transChange(.*?)>(.*?)</transChange>') self.trans_regex = re.compile(r'<transChange(.*?)>(.*?)</transChange>')
@ -106,6 +110,7 @@ class OSISBible(BibleDB):
detect_file.close() detect_file.close()
try: try:
osis = codecs.open(self.filename, u'r', details['encoding']) osis = codecs.open(self.filename, u'r', details['encoding'])
repl = replacement
for file_record in osis: for file_record in osis:
if self.stop_import_flag: if self.stop_import_flag:
break break
@ -148,12 +153,13 @@ class OSISBible(BibleDB):
verse_text = self.rf_regex.sub(u'', verse_text) verse_text = self.rf_regex.sub(u'', verse_text)
verse_text = self.lb_regex.sub(u' ', verse_text) verse_text = self.lb_regex.sub(u' ', verse_text)
verse_text = self.lg_regex.sub(u'', verse_text) verse_text = self.lg_regex.sub(u'', verse_text)
verse_text = self.l_regex.sub(u'', verse_text) verse_text = self.l_regex.sub(u' ', verse_text)
verse_text = self.w_regex.sub(u'', verse_text) verse_text = self.w_regex.sub(u'', verse_text)
verse_text = self.q1_regex.sub(u'"', verse_text) verse_text = self.q1_regex.sub(u'"', verse_text)
verse_text = self.q2_regex.sub(u'\'', verse_text) verse_text = self.q2_regex.sub(u'\'', verse_text)
verse_text = self.q_regex.sub(u'', verse_text)
verse_text = self.divine_name_regex.sub(repl, verse_text)
verse_text = self.trans_regex.sub(u'', verse_text) verse_text = self.trans_regex.sub(u'', verse_text)
verse_text = self.divine_name_regex.sub(u'', verse_text)
verse_text = verse_text.replace(u'</lb>', u'')\ verse_text = verse_text.replace(u'</lb>', u'')\
.replace(u'</l>', u'').replace(u'<lg>', u'')\ .replace(u'</l>', u'').replace(u'<lg>', u'')\
.replace(u'</lg>', u'').replace(u'</q>', u'')\ .replace(u'</lg>', u'').replace(u'</q>', u'')\

View File

@ -107,11 +107,11 @@ class Ui_CustomEditDialog(object):
translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides')) translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides'))
self.titleLabel.setText( self.titleLabel.setText(
translate('CustomPlugin.EditCustomForm', '&Title:')) translate('CustomPlugin.EditCustomForm', '&Title:'))
self.addButton.setText(UiStrings.Add) self.addButton.setText(UiStrings().Add)
self.addButton.setToolTip( self.addButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Add a new slide at ' translate('CustomPlugin.EditCustomForm', 'Add a new slide at '
'bottom.')) 'bottom.'))
self.editButton.setText(UiStrings.Edit) self.editButton.setText(UiStrings().Edit)
self.editButton.setToolTip( self.editButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Edit the selected ' translate('CustomPlugin.EditCustomForm', 'Edit the selected '
'slide.')) 'slide.'))
@ -124,4 +124,4 @@ class Ui_CustomEditDialog(object):
translate('CustomPlugin.EditCustomForm', 'The&me:')) translate('CustomPlugin.EditCustomForm', 'The&me:'))
self.creditLabel.setText( self.creditLabel.setText(
translate('CustomPlugin.EditCustomForm', '&Credits:')) translate('CustomPlugin.EditCustomForm', '&Credits:'))
self.previewButton.setText(UiStrings.SaveAndPreview) self.previewButton.setText(UiStrings().SaveAndPreview)

View File

@ -169,7 +169,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
item = self.slideListView.item(row) item = self.slideListView.item(row)
slide_list += item.text() slide_list += item.text()
if row != self.slideListView.count() - 1: if row != self.slideListView.count() - 1:
slide_list += u'\n[---]\n' slide_list += u'\n[===]\n'
self.editSlideForm.setText(slide_list) self.editSlideForm.setText(slide_list)
if self.editSlideForm.exec_(): if self.editSlideForm.exec_():
self.updateSlideList(self.editSlideForm.getText(), True) self.updateSlideList(self.editSlideForm.getText(), True)

View File

@ -63,7 +63,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
""" """
Returns a list with all slides. Returns a list with all slides.
""" """
return self.slideTextEdit.toPlainText().split(u'\n[---]\n') return self.slideTextEdit.toPlainText().split(u'\n[===]\n')
def onSplitButtonPressed(self): def onSplitButtonPressed(self):
""" """
@ -71,5 +71,5 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
""" """
if self.slideTextEdit.textCursor().columnNumber() != 0: if self.slideTextEdit.textCursor().columnNumber() != 0:
self.slideTextEdit.insertPlainText(u'\n') self.slideTextEdit.insertPlainText(u'\n')
self.slideTextEdit.insertPlainText(u'[---]\n') self.slideTextEdit.insertPlainText(u'[===]\n')
self.slideTextEdit.setFocus() self.slideTextEdit.setFocus()

View File

@ -110,7 +110,7 @@ class CustomMediaItem(MediaManagerItem):
""" """
Edit a custom item Edit a custom item
""" """
if check_item_selected(self.listView, UiStrings.SelectEdit): if check_item_selected(self.listView, UiStrings().SelectEdit):
item = self.listView.currentItem() item = self.listView.currentItem()
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.parent.edit_custom_form.loadCustom(item_id, False) self.parent.edit_custom_form.loadCustom(item_id, False)
@ -121,7 +121,7 @@ class CustomMediaItem(MediaManagerItem):
""" """
Remove a custom item from the list and database Remove a custom item from the list and database
""" """
if check_item_selected(self.listView, UiStrings.SelectDelete): if check_item_selected(self.listView, UiStrings().SelectDelete):
row_list = [item.row() for item in self.listView.selectedIndexes()] row_list = [item.row() for item in self.listView.selectedIndexes()]
row_list.sort(reverse=True) row_list.sort(reverse=True)
id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0] id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0]
@ -140,6 +140,7 @@ class CustomMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsEdit)
service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop) service_item.add_capability(ItemCapabilities.AllowsLoop)
service_item.add_capability(ItemCapabilities.AllowsVirtualSplit)
customSlide = self.parent.manager.get_object(CustomSlide, item_id) customSlide = self.parent.manager.get_object(CustomSlide, item_id)
title = customSlide.title title = customSlide.title
credit = customSlide.credits credit = customSlide.credits
@ -160,4 +161,4 @@ class CustomMediaItem(MediaManagerItem):
else: else:
raw_footer.append(u'') raw_footer.append(u'')
service_item.raw_footer = raw_footer service_item.raw_footer = raw_footer
return True return True

View File

@ -55,11 +55,11 @@ class ImageMediaItem(MediaManagerItem):
'Select Image(s)') 'Select Image(s)')
file_formats = get_images_filter() file_formats = get_images_filter()
self.onNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats, self.onNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats,
UiStrings.AllFiles) UiStrings().AllFiles)
self.replaceAction.setText(UiStrings.ReplaceBG) self.replaceAction.setText(UiStrings().ReplaceBG)
self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG) self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
self.resetAction.setText(UiStrings.ResetBG) self.resetAction.setText(UiStrings().ResetBG)
self.resetAction.setToolTip(UiStrings.ResetLiveBG) self.resetAction.setToolTip(UiStrings().ResetLiveBG)
def requiredIcons(self): def requiredIcons(self):
MediaManagerItem.requiredIcons(self) MediaManagerItem.requiredIcons(self)
@ -198,7 +198,7 @@ class ImageMediaItem(MediaManagerItem):
self.parent.liveController.display.directImage(name, filename) self.parent.liveController.display.directImage(name, filename)
self.resetAction.setVisible(True) self.resetAction.setVisible(True)
else: else:
critical_error_message_box(UiStrings.LiveBGError, critical_error_message_box(UiStrings().LiveBGError,
unicode(translate('ImagePlugin.MediaItem', unicode(translate('ImagePlugin.MediaItem',
'There was a problem replacing your background, ' 'There was a problem replacing your background, '
'the image file "%s" no longer exists.')) % filename) 'the image file "%s" no longer exists.')) % filename)

View File

@ -60,11 +60,11 @@ class MediaMediaItem(MediaManagerItem):
self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem', self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
'Videos (%s);;Audio (%s);;%s (*)')) % ( 'Videos (%s);;Audio (%s);;%s (*)')) % (
u' '.join(self.parent.video_extensions_list), u' '.join(self.parent.video_extensions_list),
u' '.join(self.parent.audio_extensions_list), UiStrings.AllFiles) u' '.join(self.parent.audio_extensions_list), UiStrings().AllFiles)
self.replaceAction.setText(UiStrings.ReplaceBG) self.replaceAction.setText(UiStrings().ReplaceBG)
self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG) self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
self.resetAction.setText(UiStrings.ResetBG) self.resetAction.setText(UiStrings().ResetBG)
self.resetAction.setToolTip(UiStrings.ResetLiveBG) self.resetAction.setToolTip(UiStrings().ResetLiveBG)
def requiredIcons(self): def requiredIcons(self):
MediaManagerItem.requiredIcons(self) MediaManagerItem.requiredIcons(self)
@ -111,7 +111,7 @@ class MediaMediaItem(MediaManagerItem):
self.parent.liveController.display.video(filename, 0, True) self.parent.liveController.display.video(filename, 0, True)
self.resetAction.setVisible(True) self.resetAction.setVisible(True)
else: else:
critical_error_message_box(UiStrings.LiveBGError, critical_error_message_box(UiStrings().LiveBGError,
unicode(translate('MediaPlugin.MediaItem', unicode(translate('MediaPlugin.MediaItem',
'There was a problem replacing your background, ' 'There was a problem replacing your background, '
'the media file "%s" no longer exists.')) % filename) 'the media file "%s" no longer exists.')) % filename)
@ -209,4 +209,4 @@ class MediaMediaItem(MediaManagerItem):
img = QtGui.QPixmap(u':/media/media_video.png').toImage() img = QtGui.QPixmap(u':/media/media_video.png').toImage()
item_name.setIcon(build_icon(img)) item_name.setIcon(build_icon(img))
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
self.listView.addItem(item_name) self.listView.addItem(item_name)

View File

@ -244,7 +244,7 @@ class ImpressDocument(PresentationDocument):
return False return False
self.presentation = self.document.getPresentation() self.presentation = self.document.getPresentation()
self.presentation.Display = \ self.presentation.Display = \
self.controller.plugin.renderManager.screens.current_display + 1 self.controller.plugin.renderer.screens.current_display + 1
self.control = None self.control = None
self.create_thumbnails() self.create_thumbnails()
return True return True
@ -463,4 +463,4 @@ class ImpressDocument(PresentationDocument):
shape = page.getByIndex(idx) shape = page.getByIndex(idx)
if shape.supportsService("com.sun.star.drawing.Text"): if shape.supportsService("com.sun.star.drawing.Text"):
text += shape.getString() + '\n' text += shape.getString() + '\n'
return text return text

View File

@ -203,7 +203,7 @@ class PresentationMediaItem(MediaManagerItem):
""" """
Remove a presentation item from the list Remove a presentation item from the list
""" """
if check_item_selected(self.listView, UiStrings.SelectDelete): if check_item_selected(self.listView, UiStrings().SelectDelete):
items = self.listView.selectedIndexes() items = self.listView.selectedIndexes()
row_list = [item.row() for item in items] row_list = [item.row() for item in items]
row_list.sort(reverse=True) row_list.sort(reverse=True)
@ -296,4 +296,4 @@ class PresentationMediaItem(MediaManagerItem):
if self.controllers[controller].enabled(): if self.controllers[controller].enabled():
if filetype in self.controllers[controller].alsosupports: if filetype in self.controllers[controller].alsosupports:
return controller return controller
return None return None

View File

@ -251,14 +251,15 @@ class PowerpointDocument(PresentationDocument):
win32ui.GetForegroundWindow().GetDC().GetDeviceCaps(88) win32ui.GetForegroundWindow().GetDC().GetDeviceCaps(88)
except win32ui.error: except win32ui.error:
dpi = 96 dpi = 96
rendermanager = self.controller.plugin.renderManager renderer = self.controller.plugin.renderer
rect = rendermanager.screens.current[u'size'] rect = renderer.screens.current[u'size']
ppt_window = self.presentation.SlideShowSettings.Run() ppt_window = self.presentation.SlideShowSettings.Run()
ppt_window.Top = rect.y() * 72 / dpi ppt_window.Top = rect.y() * 72 / dpi
ppt_window.Height = rect.height() * 72 / dpi ppt_window.Height = rect.height() * 72 / dpi
ppt_window.Left = rect.x() * 72 / dpi ppt_window.Left = rect.x() * 72 / dpi
ppt_window.Width = rect.width() * 72 / dpi ppt_window.Width = rect.width() * 72 / dpi
def get_slide_number(self): def get_slide_number(self):
""" """
Returns the current slide number. Returns the current slide number.

View File

@ -121,8 +121,8 @@ class PptviewDocument(PresentationDocument):
The file name of the presentations to run. The file name of the presentations to run.
""" """
log.debug(u'LoadPresentation') log.debug(u'LoadPresentation')
rendermanager = self.controller.plugin.renderManager renderer = self.controller.plugin.renderer
rect = rendermanager.screens.current[u'size'] rect = renderer.screens.current[u'size']
rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom()) rect = RECT(rect.x(), rect.y(), rect.right(), rect.bottom())
filepath = str(self.filepath.replace(u'/', u'\\')) filepath = str(self.filepath.replace(u'/', u'\\'))
if not os.path.isdir(self.get_temp_folder()): if not os.path.isdir(self.get_temp_folder()):
@ -244,4 +244,4 @@ class PptviewDocument(PresentationDocument):
""" """
Triggers the previous slide on the running presentation Triggers the previous slide on the running presentation
""" """
self.controller.process.PrevStep(self.pptid) self.controller.process.PrevStep(self.pptid)

View File

@ -27,6 +27,8 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <io.h>
#include <direct.h>
#include <time.h> #include <time.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -88,7 +90,12 @@ DllExport BOOL CheckInstalled()
char cmdLine[MAX_PATH * 2]; char cmdLine[MAX_PATH * 2];
DEBUG("CheckInstalled\n"); DEBUG("CheckInstalled\n");
return GetPPTViewerPath(cmdLine, sizeof(cmdLine)); BOOL found = GetPPTViewerPath(cmdLine, sizeof(cmdLine));
if(found)
{
DEBUG("Exe: %s\n", cmdLine);
}
return found;
} }
// Open the PointPoint, count the slides and take a snapshot of each slide // Open the PointPoint, count the slides and take a snapshot of each slide
@ -160,7 +167,7 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect,
pptView[id].rect.bottom = rect.bottom; pptView[id].rect.bottom = rect.bottom;
pptView[id].rect.right = rect.right; pptView[id].rect.right = rect.right;
} }
strcat_s(cmdLine, MAX_PATH * 2, "/F /S \""); strcat_s(cmdLine, MAX_PATH * 2, " /F /S \"");
strcat_s(cmdLine, MAX_PATH * 2, filename); strcat_s(cmdLine, MAX_PATH * 2, filename);
strcat_s(cmdLine, MAX_PATH * 2, "\""); strcat_s(cmdLine, MAX_PATH * 2, "\"");
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
@ -189,7 +196,7 @@ DllExport int OpenPPT(char *filename, HWND hParentWnd, RECT rect,
Sleep(10); Sleep(10);
if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi)) if (!CreateProcess(NULL, cmdLine, NULL, NULL, FALSE, 0, 0, NULL, &si, &pi))
{ {
DEBUG("OpenPPT: CreateProcess failed\n"); DEBUG("OpenPPT: CreateProcess failed: %s\n", cmdLine);
ClosePPT(id); ClosePPT(id);
return -1; return -1;
} }
@ -344,16 +351,71 @@ BOOL SavePPTInfo(int id)
// Get the path of the PowerPoint viewer from the registry // Get the path of the PowerPoint viewer from the registry
BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize) BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize)
{
char cwd[MAX_PATH];
DEBUG("GetPPTViewerPath: start\n");
if(GetPPTViewerPathFromReg(pptViewerPath, stringSize))
{
if(_access(pptViewerPath, 0) != -1)
{
DEBUG("GetPPTViewerPath: exit registry\n");
return TRUE;
}
}
// This is where it gets ugly. PPT2007 it seems no longer stores its
// location in the registry. So we have to use the defaults which will
// upset those who like to put things somewhere else
// Viewer 2007 in 64bit Windows:
if(_access("C:\\Program Files (x86)\\Microsoft Office\\Office12\\PPTVIEW.EXE",
0) != -1)
{
strcpy_s(
"C:\\Program Files (x86)\\Microsoft Office\\Office12\\PPTVIEW.EXE",
stringSize, pptViewerPath);
DEBUG("GetPPTViewerPath: exit 64bit 2007\n");
return TRUE;
}
// Viewer 2007 in 32bit Windows:
if(_access("C:\\Program Files\\Microsoft Office\\Office12\\PPTVIEW.EXE", 0)
!= -1)
{
strcpy_s("C:\\Program Files\\Microsoft Office\\Office12\\PPTVIEW.EXE",
stringSize, pptViewerPath);
DEBUG("GetPPTViewerPath: exit 32bit 2007\n");
return TRUE;
}
// Give them the opportunity to place it in the same folder as the app
_getcwd(cwd, MAX_PATH);
strcat_s(cwd, MAX_PATH, "\\PPTVIEW.EXE");
if(_access(cwd, 0) != -1)
{
strcpy_s(pptViewerPath, stringSize, cwd);
DEBUG("GetPPTViewerPath: exit local\n");
return TRUE;
}
DEBUG("GetPPTViewerPath: exit fail\n");
return FALSE;
}
BOOL GetPPTViewerPathFromReg(char *pptViewerPath, int stringSize)
{ {
HKEY hKey; HKEY hKey;
DWORD dwType, dwSize; DWORD dwType, dwSize;
LRESULT lResult; LRESULT lResult;
DEBUG("GetPPTViewerPath: start\n"); // The following registry settings are for, respectively, (I think)
// PPT Viewer 2007 (older versions. Latest not in registry) & PPT Viewer 2010
// PPT Viewer 2003 (recent versions)
// PPT Viewer 2003 (older versions)
// PPT Viewer 97
if ((RegOpenKeyEx(HKEY_CLASSES_ROOT, if ((RegOpenKeyEx(HKEY_CLASSES_ROOT,
"PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey) "PowerPointViewer.Show.12\\shell\\Show\\command", 0, KEY_READ, &hKey)
!= ERROR_SUCCESS) != ERROR_SUCCESS)
&& (RegOpenKeyEx(HKEY_CLASSES_ROOT, && (RegOpenKeyEx(HKEY_CLASSES_ROOT,
"PowerPointViewer.Show.11\\shell\\Show\\command", 0, KEY_READ, &hKey)
!= ERROR_SUCCESS)
&& (RegOpenKeyEx(HKEY_CLASSES_ROOT,
"Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey) "Applications\\PPTVIEW.EXE\\shell\\open\\command", 0, KEY_READ, &hKey)
!= ERROR_SUCCESS) != ERROR_SUCCESS)
&& (RegOpenKeyEx(HKEY_CLASSES_ROOT, && (RegOpenKeyEx(HKEY_CLASSES_ROOT,
@ -373,7 +435,6 @@ BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize)
} }
// remove "%1" from end of key value // remove "%1" from end of key value
pptViewerPath[strlen(pptViewerPath) - 4] = '\0'; pptViewerPath[strlen(pptViewerPath) - 4] = '\0';
DEBUG("GetPPTViewerPath: exit ok\n");
return TRUE; return TRUE;
} }

View File

@ -49,6 +49,7 @@ LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK CwpProc(int nCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize); BOOL GetPPTViewerPath(char *pptViewerPath, int stringSize);
BOOL GetPPTViewerPathFromReg(char *pptViewerPath, int stringSize);
HBITMAP CaptureWindow(HWND hWnd); HBITMAP CaptureWindow(HWND hWnd);
VOID SaveBitmap(CHAR* filename, HBITMAP hBmp) ; VOID SaveBitmap(CHAR* filename, HBITMAP hBmp) ;
VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename); VOID CaptureAndSaveWindow(HWND hWnd, CHAR* filename);

View File

@ -86,7 +86,7 @@ class PresentationTab(SettingsTab):
checkbox.setText( checkbox.setText(
unicode(translate('PresentationPlugin.PresentationTab', unicode(translate('PresentationPlugin.PresentationTab',
'%s (unavailable)')) % controller.name) '%s (unavailable)')) % controller.name)
self.AdvancedGroupBox.setTitle(UiStrings.Advanced) self.AdvancedGroupBox.setTitle(UiStrings().Advanced)
self.OverrideAppCheckBox.setText( self.OverrideAppCheckBox.setText(
translate('PresentationPlugin.PresentationTab', translate('PresentationPlugin.PresentationTab',
'Allow presentation application to be overriden')) 'Allow presentation application to be overriden'))
@ -131,4 +131,4 @@ class PresentationTab(SettingsTab):
QtCore.QVariant(self.OverrideAppCheckBox.checkState())) QtCore.QVariant(self.OverrideAppCheckBox.checkState()))
changed = True changed = True
if changed: if changed:
Receiver.send_message(u'mediaitem_presentation_rebuild') Receiver.send_message(u'mediaitem_presentation_rebuild')

View File

@ -260,11 +260,11 @@ class Ui_EditSongDialog(object):
translate('SongsPlugin.EditSongForm', '&Lyrics:')) translate('SongsPlugin.EditSongForm', '&Lyrics:'))
self.verseOrderLabel.setText( self.verseOrderLabel.setText(
translate('SongsPlugin.EditSongForm', '&Verse order:')) translate('SongsPlugin.EditSongForm', '&Verse order:'))
self.verseAddButton.setText(UiStrings.Add) self.verseAddButton.setText(UiStrings().Add)
self.verseEditButton.setText(UiStrings.Edit) self.verseEditButton.setText(UiStrings().Edit)
self.verseEditAllButton.setText( self.verseEditAllButton.setText(
translate('SongsPlugin.EditSongForm', 'Ed&it All')) translate('SongsPlugin.EditSongForm', 'Ed&it All'))
self.verseDeleteButton.setText(UiStrings.Delete) self.verseDeleteButton.setText(UiStrings().Delete)
self.songTabWidget.setTabText( self.songTabWidget.setTabText(
self.songTabWidget.indexOf(self.lyricsTab), self.songTabWidget.indexOf(self.lyricsTab),
translate('SongsPlugin.EditSongForm', 'Title && Lyrics')) translate('SongsPlugin.EditSongForm', 'Title && Lyrics'))
@ -289,13 +289,13 @@ class Ui_EditSongDialog(object):
self.songTabWidget.indexOf(self.authorsTab), self.songTabWidget.indexOf(self.authorsTab),
translate('SongsPlugin.EditSongForm', translate('SongsPlugin.EditSongForm',
'Authors, Topics && Song Book')) 'Authors, Topics && Song Book'))
self.themeGroupBox.setTitle(UiStrings.Theme) self.themeGroupBox.setTitle(UiStrings().Theme)
self.themeAddButton.setText( self.themeAddButton.setText(
translate('SongsPlugin.EditSongForm', 'New &Theme')) translate('SongsPlugin.EditSongForm', 'New &Theme'))
self.rightsGroupBox.setTitle( self.rightsGroupBox.setTitle(
translate('SongsPlugin.EditSongForm', 'Copyright Information')) translate('SongsPlugin.EditSongForm', 'Copyright Information'))
self.copyrightInsertButton.setText(SongStrings.CopyrightSymbol) self.copyrightInsertButton.setText(SongStrings.CopyrightSymbol)
self.CCLILabel.setText(UiStrings.CCLINumberLabel) self.CCLILabel.setText(UiStrings().CCLINumberLabel)
self.commentsGroupBox.setTitle( self.commentsGroupBox.setTitle(
translate('SongsPlugin.EditSongForm', 'Comments')) translate('SongsPlugin.EditSongForm', 'Comments'))
self.songTabWidget.setTabText( self.songTabWidget.setTabText(
@ -313,4 +313,4 @@ def editSongDialogComboBox(parent, name):
comboBox.setEditable(True) comboBox.setEditable(True)
comboBox.setInsertPolicy(QtGui.QComboBox.NoInsert) comboBox.setInsertPolicy(QtGui.QComboBox.NoInsert)
comboBox.setObjectName(name) comboBox.setObjectName(name)
return comboBox return comboBox

View File

@ -89,14 +89,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.onVerseListViewPressed) self.onVerseListViewPressed)
QtCore.QObject.connect(self.themeAddButton, QtCore.QObject.connect(self.themeAddButton,
QtCore.SIGNAL(u'clicked()'), QtCore.SIGNAL(u'clicked()'),
self.parent.parent.renderManager.theme_manager.onAddTheme) self.parent.parent.renderer.theme_manager.onAddTheme)
QtCore.QObject.connect(self.maintenanceButton, QtCore.QObject.connect(self.maintenanceButton,
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked) QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes) QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
self.previewButton = QtGui.QPushButton() self.previewButton = QtGui.QPushButton()
self.previewButton.setObjectName(u'previewButton') self.previewButton.setObjectName(u'previewButton')
self.previewButton.setText(UiStrings.SaveAndPreview) self.previewButton.setText(UiStrings().SaveAndPreview)
self.buttonBox.addButton( self.buttonBox.addButton(
self.previewButton, QtGui.QDialogButtonBox.ActionRole) self.previewButton, QtGui.QDialogButtonBox.ActionRole)
QtCore.QObject.connect(self.buttonBox, QtCore.QObject.connect(self.buttonBox,
@ -355,7 +355,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.__addAuthorToList(author) self.__addAuthorToList(author)
self.authorsComboBox.setCurrentIndex(0) self.authorsComboBox.setCurrentIndex(0)
else: else:
QtGui.QMessageBox.warning(self, UiStrings.NISs, QtGui.QMessageBox.warning(self, UiStrings().NISs,
translate('SongsPlugin.EditSongForm', 'You have not selected ' translate('SongsPlugin.EditSongForm', 'You have not selected '
'a valid author. Either select an author from the list, ' 'a valid author. Either select an author from the list, '
'or type in a new author and click the "Add Author to ' 'or type in a new author and click the "Add Author to '
@ -414,7 +414,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.topicsListView.addItem(topic_item) self.topicsListView.addItem(topic_item)
self.topicsComboBox.setCurrentIndex(0) self.topicsComboBox.setCurrentIndex(0)
else: else:
QtGui.QMessageBox.warning(self, UiStrings.NISs, QtGui.QMessageBox.warning(self, UiStrings().NISs,
translate('SongsPlugin.EditSongForm', 'You have not selected ' translate('SongsPlugin.EditSongForm', 'You have not selected '
'a valid topic. Either select a topic from the list, or ' 'a valid topic. Either select a topic from the list, or '
'type in a new topic and click the "Add Topic to Song" ' 'type in a new topic and click the "Add Topic to Song" '
@ -576,11 +576,13 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
if verse_index is not None: if verse_index is not None:
order.append(VerseType.Tags[verse_index] + u'1') order.append(VerseType.Tags[verse_index] + u'1')
else: else:
order.append(u'') # it matches no verses anyway # it matches no verses anyway
order.append(u'')
else: else:
verse_index = VerseType.from_translated_tag(item[0]) verse_index = VerseType.from_translated_tag(item[0])
if verse_index is None: if verse_index is None:
order.append(u'') # same as above # it matches no verses anyway
order.append(u'')
else: else:
verse_tag = VerseType.Tags[verse_index] verse_tag = VerseType.Tags[verse_index]
verse_num = item[1:].lower() verse_num = item[1:].lower()
@ -779,4 +781,4 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.song.verse_order) self.song.verse_order)
except: except:
log.exception(u'Problem processing song Lyrics \n%s', log.exception(u'Problem processing song Lyrics \n%s',
sxml.dump_xml()) sxml.dump_xml())

View File

@ -175,7 +175,7 @@ class SongExportForm(OpenLPWizard):
self.availableSongsPage.setSubTitle( self.availableSongsPage.setSubTitle(
translate('SongsPlugin.ExportWizardForm', translate('SongsPlugin.ExportWizardForm',
'Check the songs you want to export.')) 'Check the songs you want to export.'))
self.searchLabel.setText(u'%s:' % UiStrings.Search) self.searchLabel.setText(u'%s:' % UiStrings().Search)
self.uncheckButton.setText( self.uncheckButton.setText(
translate('SongsPlugin.ExportWizardForm', 'Uncheck All')) translate('SongsPlugin.ExportWizardForm', 'Uncheck All'))
self.checkButton.setText( self.checkButton.setText(
@ -207,7 +207,7 @@ class SongExportForm(OpenLPWizard):
self.availableListWidget) if item.checkState() self.availableListWidget) if item.checkState()
] ]
if not items: if not items:
critical_error_message_box(UiStrings.NISp, critical_error_message_box(UiStrings().NISp,
translate('SongsPlugin.ExportWizardForm', translate('SongsPlugin.ExportWizardForm',
'You need to add at least one Song to export.')) 'You need to add at least one Song to export.'))
return False return False
@ -360,4 +360,4 @@ class SongExportForm(OpenLPWizard):
SettingsManager.get_last_dir(self.plugin.settingsSection, 1), SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
options=QtGui.QFileDialog.ShowDirsOnly)) options=QtGui.QFileDialog.ShowDirsOnly))
SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1) SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1)
self.directoryLineEdit.setText(path) self.directoryLineEdit.setText(path)

View File

@ -26,6 +26,7 @@
""" """
The song import functions for OpenLP. The song import functions for OpenLP.
""" """
import codecs
import logging import logging
import os import os
@ -55,6 +56,7 @@ class SongImportForm(OpenLPWizard):
``plugin`` ``plugin``
The songs plugin. The songs plugin.
""" """
self.clipboard = plugin.formparent.clipboard
OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard', OpenLPWizard.__init__(self, parent, plugin, u'songImportWizard',
u':/wizards/wizard_importsong.bmp') u':/wizards/wizard_importsong.bmp')
@ -235,8 +237,8 @@ class SongImportForm(OpenLPWizard):
self.sourcePage.setTitle(WizardStrings.ImportSelect) self.sourcePage.setTitle(WizardStrings.ImportSelect)
self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong)
self.formatLabel.setText(WizardStrings.FormatLabel) self.formatLabel.setText(WizardStrings.FormatLabel)
self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings.OLPV2) self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings().OLPV2)
self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings.OLPV1) self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings().OLPV1)
self.formatComboBox.setItemText( self.formatComboBox.setItemText(
SongFormat.OpenLyrics, WizardStrings.OL) SongFormat.OpenLyrics, WizardStrings.OL)
self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS) self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
@ -261,10 +263,10 @@ class SongImportForm(OpenLPWizard):
# self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV) # self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV)
self.openLP2FilenameLabel.setText( self.openLP2FilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:')) translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.openLP2BrowseButton.setText(UiStrings.Browse) self.openLP2BrowseButton.setText(UiStrings().Browse)
self.openLP1FilenameLabel.setText( self.openLP1FilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:')) translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.openLP1BrowseButton.setText(UiStrings.Browse) self.openLP1BrowseButton.setText(UiStrings().Browse)
self.openLP1DisabledLabel.setText(WizardStrings.NoSqlite) self.openLP1DisabledLabel.setText(WizardStrings.NoSqlite)
self.openLyricsAddButton.setText( self.openLyricsAddButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Add Files...')) translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
@ -305,10 +307,10 @@ class SongImportForm(OpenLPWizard):
'find OpenOffice.org on your computer.')) 'find OpenOffice.org on your computer.'))
self.easiSlidesFilenameLabel.setText( self.easiSlidesFilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:')) translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.easiSlidesBrowseButton.setText(UiStrings.Browse) self.easiSlidesBrowseButton.setText(UiStrings().Browse)
self.ewFilenameLabel.setText( self.ewFilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:')) translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.ewBrowseButton.setText(UiStrings.Browse) self.ewBrowseButton.setText(UiStrings().Browse)
self.songBeamerAddButton.setText( self.songBeamerAddButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Add Files...')) translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.songBeamerRemoveButton.setText( self.songBeamerRemoveButton.setText(
@ -323,13 +325,17 @@ class SongImportForm(OpenLPWizard):
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
# self.csvFilenameLabel.setText( # self.csvFilenameLabel.setText(
# translate('SongsPlugin.ImportWizardForm', 'Filename:')) # translate('SongsPlugin.ImportWizardForm', 'Filename:'))
# self.csvBrowseButton.setText(UiStrings.Browse) # self.csvBrowseButton.setText(UiStrings().Browse)
self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setTitle(WizardStrings.Importing)
self.progressPage.setSubTitle( self.progressPage.setSubTitle(
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'Please wait while your songs are imported.')) 'Please wait while your songs are imported.'))
self.progressLabel.setText(WizardStrings.Ready) self.progressLabel.setText(WizardStrings.Ready)
self.progressBar.setFormat(WizardStrings.PercentSymbolFormat) self.progressBar.setFormat(WizardStrings.PercentSymbolFormat)
self.errorCopyToButton.setText(translate('SongsPlugin.ImportWizardForm',
'Copy'))
self.errorSaveToButton.setText(translate('SongsPlugin.ImportWizardForm',
'Save to File'))
# Align all QFormLayouts towards each other. # Align all QFormLayouts towards each other.
width = max(self.formatLabel.minimumSizeHint().width(), width = max(self.formatLabel.minimumSizeHint().width(),
self.openLP2FilenameLabel.minimumSizeHint().width()) self.openLP2FilenameLabel.minimumSizeHint().width())
@ -346,49 +352,49 @@ class SongImportForm(OpenLPWizard):
source_format = self.formatComboBox.currentIndex() source_format = self.formatComboBox.currentIndex()
if source_format == SongFormat.OpenLP2: if source_format == SongFormat.OpenLP2:
if self.openLP2FilenameEdit.text().isEmpty(): if self.openLP2FilenameEdit.text().isEmpty():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
WizardStrings.YouSpecifyFile % UiStrings.OLPV2) WizardStrings.YouSpecifyFile % UiStrings().OLPV2)
self.openLP2BrowseButton.setFocus() self.openLP2BrowseButton.setFocus()
return False return False
elif source_format == SongFormat.OpenLP1: elif source_format == SongFormat.OpenLP1:
if self.openLP1FilenameEdit.text().isEmpty(): if self.openLP1FilenameEdit.text().isEmpty():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
WizardStrings.YouSpecifyFile % UiStrings.OLPV1) WizardStrings.YouSpecifyFile % UiStrings().OLPV1)
self.openLP1BrowseButton.setFocus() self.openLP1BrowseButton.setFocus()
return False return False
elif source_format == SongFormat.OpenLyrics: elif source_format == SongFormat.OpenLyrics:
if self.openLyricsFileListWidget.count() == 0: if self.openLyricsFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.OL) WizardStrings.YouSpecifyFile % WizardStrings.OL)
self.openLyricsAddButton.setFocus() self.openLyricsAddButton.setFocus()
return False return False
elif source_format == SongFormat.OpenSong: elif source_format == SongFormat.OpenSong:
if self.openSongFileListWidget.count() == 0: if self.openSongFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.OS) WizardStrings.YouSpecifyFile % WizardStrings.OS)
self.openSongAddButton.setFocus() self.openSongAddButton.setFocus()
return False return False
elif source_format == SongFormat.WordsOfWorship: elif source_format == SongFormat.WordsOfWorship:
if self.wordsOfWorshipFileListWidget.count() == 0: if self.wordsOfWorshipFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.WoW) WizardStrings.YouSpecifyFile % WizardStrings.WoW)
self.wordsOfWorshipAddButton.setFocus() self.wordsOfWorshipAddButton.setFocus()
return False return False
elif source_format == SongFormat.CCLI: elif source_format == SongFormat.CCLI:
if self.ccliFileListWidget.count() == 0: if self.ccliFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.CCLI) WizardStrings.YouSpecifyFile % WizardStrings.CCLI)
self.ccliAddButton.setFocus() self.ccliAddButton.setFocus()
return False return False
elif source_format == SongFormat.SongsOfFellowship: elif source_format == SongFormat.SongsOfFellowship:
if self.songsOfFellowshipFileListWidget.count() == 0: if self.songsOfFellowshipFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.SoF) WizardStrings.YouSpecifyFile % WizardStrings.SoF)
self.songsOfFellowshipAddButton.setFocus() self.songsOfFellowshipAddButton.setFocus()
return False return False
elif source_format == SongFormat.Generic: elif source_format == SongFormat.Generic:
if self.genericFileListWidget.count() == 0: if self.genericFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
translate('SongsPlugin.ImportWizardForm', translate('SongsPlugin.ImportWizardForm',
'You need to specify at least one document or ' 'You need to specify at least one document or '
'presentation file to import from.')) 'presentation file to import from.'))
@ -396,31 +402,31 @@ class SongImportForm(OpenLPWizard):
return False return False
elif source_format == SongFormat.EasiSlides: elif source_format == SongFormat.EasiSlides:
if self.easiSlidesFilenameEdit.text().isEmpty(): if self.easiSlidesFilenameEdit.text().isEmpty():
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.ES) WizardStrings.YouSpecifyFile % WizardStrings.ES)
self.easiSlidesBrowseButton.setFocus() self.easiSlidesBrowseButton.setFocus()
return False return False
elif source_format == SongFormat.EasyWorship: elif source_format == SongFormat.EasyWorship:
if self.ewFilenameEdit.text().isEmpty(): if self.ewFilenameEdit.text().isEmpty():
critical_error_message_box(UiStrings.NFSs, critical_error_message_box(UiStrings().NFSs,
WizardStrings.YouSpecifyFile % WizardStrings.EW) WizardStrings.YouSpecifyFile % WizardStrings.EW)
self.ewBrowseButton.setFocus() self.ewBrowseButton.setFocus()
return False return False
elif source_format == SongFormat.SongBeamer: elif source_format == SongFormat.SongBeamer:
if self.songBeamerFileListWidget.count() == 0: if self.songBeamerFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.SB) WizardStrings.YouSpecifyFile % WizardStrings.SB)
self.songBeamerAddButton.setFocus() self.songBeamerAddButton.setFocus()
return False return False
elif source_format == SongFormat.SongShowPlus: elif source_format == SongFormat.SongShowPlus:
if self.songShowPlusFileListWidget.count() == 0: if self.songShowPlusFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.SSP) WizardStrings.YouSpecifyFile % WizardStrings.SSP)
self.wordsOfWorshipAddButton.setFocus() self.wordsOfWorshipAddButton.setFocus()
return False return False
elif source_format == SongFormat.FoilPresenter: elif source_format == SongFormat.FoilPresenter:
if self.foilPresenterFileListWidget.count() == 0: if self.foilPresenterFileListWidget.count() == 0:
critical_error_message_box(UiStrings.NFSp, critical_error_message_box(UiStrings().NFSp,
WizardStrings.YouSpecifyFile % WizardStrings.FP) WizardStrings.YouSpecifyFile % WizardStrings.FP)
self.foilPresenterAddButton.setFocus() self.foilPresenterAddButton.setFocus()
return False return False
@ -446,7 +452,7 @@ class SongImportForm(OpenLPWizard):
""" """
if filters: if filters:
filters += u';;' filters += u';;'
filters += u'%s (*)' % UiStrings.AllFiles filters += u'%s (*)' % UiStrings().AllFiles
filenames = QtGui.QFileDialog.getOpenFileNames(self, title, filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
SettingsManager.get_last_dir(self.plugin.settingsSection, 1), SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
filters) filters)
@ -459,10 +465,7 @@ class SongImportForm(OpenLPWizard):
""" """
Return a list of file from the listbox Return a list of file from the listbox
""" """
files = [] return [unicode(listbox.item(i).text()) for i in range(listbox.count())]
for row in range(0, listbox.count()):
files.append(unicode(listbox.item(row).text()))
return files
def removeSelectedItems(self, listbox): def removeSelectedItems(self, listbox):
""" """
@ -476,7 +479,7 @@ class SongImportForm(OpenLPWizard):
""" """
Get OpenLP v2 song database file Get OpenLP v2 song database file
""" """
self.getFileName(WizardStrings.OpenTypeFile % UiStrings.OLPV2, self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV2,
self.openLP2FilenameEdit, u'%s (*.sqlite)' self.openLP2FilenameEdit, u'%s (*.sqlite)'
% (translate('SongsPlugin.ImportWizardForm', % (translate('SongsPlugin.ImportWizardForm',
'OpenLP 2.0 Databases')) 'OpenLP 2.0 Databases'))
@ -486,7 +489,7 @@ class SongImportForm(OpenLPWizard):
""" """
Get OpenLP v1 song database file Get OpenLP v1 song database file
""" """
self.getFileName(WizardStrings.OpenTypeFile % UiStrings.OLPV1, self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV1,
self.openLP1FilenameEdit, u'%s (*.olp)' self.openLP1FilenameEdit, u'%s (*.olp)'
% translate('SongsPlugin.ImportWizardForm', % translate('SongsPlugin.ImportWizardForm',
'openlp.org v1.x Databases') 'openlp.org v1.x Databases')
@ -659,6 +662,10 @@ class SongImportForm(OpenLPWizard):
self.songShowPlusFileListWidget.clear() self.songShowPlusFileListWidget.clear()
self.foilPresenterFileListWidget.clear() self.foilPresenterFileListWidget.clear()
#self.csvFilenameEdit.setText(u'') #self.csvFilenameEdit.setText(u'')
self.errorReportTextEdit.clear()
self.errorReportTextEdit.setHidden(True)
self.errorCopyToButton.setHidden(True)
self.errorSaveToButton.setHidden(True)
def preWizard(self): def preWizard(self):
""" """
@ -743,12 +750,30 @@ class SongImportForm(OpenLPWizard):
importer = self.plugin.importSongs(SongFormat.FoilPresenter, importer = self.plugin.importSongs(SongFormat.FoilPresenter,
filenames=self.getListOfFiles(self.foilPresenterFileListWidget) filenames=self.getListOfFiles(self.foilPresenterFileListWidget)
) )
if importer.do_import(): importer.do_import()
self.progressLabel.setText(WizardStrings.FinishedImport) if importer.error_log:
self.progressLabel.setText(translate(
'SongsPlugin.SongImportForm', 'Your song import failed.'))
else: else:
self.progressLabel.setText( self.progressLabel.setText(WizardStrings.FinishedImport)
translate('SongsPlugin.SongImportForm',
'Your song import failed.')) def onErrorCopyToButtonClicked(self):
"""
Copy the error report to the clipboard.
"""
self.clipboard.setText(self.errorReportTextEdit.toPlainText())
def onErrorSaveToButtonClicked(self):
"""
Save the error report to a file.
"""
filename = QtGui.QFileDialog.getSaveFileName(self,
SettingsManager.get_last_dir(self.plugin.settingsSection, 1))
if not filename:
return
file = codecs.open(filename, u'w', u'utf-8')
file.write(self.errorReportTextEdit.toPlainText())
file.close()
def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False, def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False,
single_select=False): single_select=False):

View File

@ -149,17 +149,17 @@ class Ui_SongMaintenanceDialog(object):
self.listItemAuthors.setText(SongStrings.Authors) self.listItemAuthors.setText(SongStrings.Authors)
self.listItemTopics.setText(SongStrings.Topics) self.listItemTopics.setText(SongStrings.Topics)
self.listItemBooks.setText(SongStrings.SongBooks) self.listItemBooks.setText(SongStrings.SongBooks)
self.authorsAddButton.setText(UiStrings.Add) self.authorsAddButton.setText(UiStrings().Add)
self.authorsEditButton.setText(UiStrings.Edit) self.authorsEditButton.setText(UiStrings().Edit)
self.authorsDeleteButton.setText(UiStrings.Delete) self.authorsDeleteButton.setText(UiStrings().Delete)
self.topicsAddButton.setText(UiStrings.Add) self.topicsAddButton.setText(UiStrings().Add)
self.topicsEditButton.setText(UiStrings.Edit) self.topicsEditButton.setText(UiStrings().Edit)
self.topicsDeleteButton.setText(UiStrings.Delete) self.topicsDeleteButton.setText(UiStrings().Delete)
self.booksAddButton.setText(UiStrings.Add) self.booksAddButton.setText(UiStrings().Add)
self.booksEditButton.setText(UiStrings.Edit) self.booksEditButton.setText(UiStrings().Edit)
self.booksDeleteButton.setText(UiStrings.Delete) self.booksDeleteButton.setText(UiStrings().Delete)
typeListWidth = max(self.fontMetrics().width(SongStrings.Authors), typeListWidth = max(self.fontMetrics().width(SongStrings.Authors),
self.fontMetrics().width(SongStrings.Topics), self.fontMetrics().width(SongStrings.Topics),
self.fontMetrics().width(SongStrings.SongBooks)) self.fontMetrics().width(SongStrings.SongBooks))
self.typeListWidget.setFixedWidth(typeListWidth + self.typeListWidget.setFixedWidth(typeListWidth +
self.typeListWidget.iconSize().width() + 32) self.typeListWidget.iconSize().width() + 32)

View File

@ -115,7 +115,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
else: else:
critical_error_message_box(dlg_title, err_text) critical_error_message_box(dlg_title, err_text)
else: else:
critical_error_message_box(dlg_title, UiStrings.NISs) critical_error_message_box(dlg_title, UiStrings().NISs)
def resetAuthors(self): def resetAuthors(self):
""" """
@ -386,7 +386,8 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
existing_author = self.manager.get_object_filtered(Author, existing_author = self.manager.get_object_filtered(Author,
and_(Author.first_name == old_author.first_name, and_(Author.first_name == old_author.first_name,
Author.last_name == old_author.last_name, Author.last_name == old_author.last_name,
Author.display_name == old_author.display_name)) Author.display_name == old_author.display_name,
Author.id != old_author.id))
# Find the songs, which have the old_author as author. # Find the songs, which have the old_author as author.
songs = self.manager.get_all_objects(Song, songs = self.manager.get_all_objects(Song,
Song.authors.contains(old_author)) Song.authors.contains(old_author))
@ -408,7 +409,7 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
""" """
# Find the duplicate. # Find the duplicate.
existing_topic = self.manager.get_object_filtered(Topic, existing_topic = self.manager.get_object_filtered(Topic,
Topic.name == old_topic.name) and_(Topic.name == old_topic.name, Topic.id != old_topic.id))
# Find the songs, which have the old_topic as topic. # Find the songs, which have the old_topic as topic.
songs = self.manager.get_all_objects(Song, songs = self.manager.get_all_objects(Song,
Song.topics.contains(old_topic)) Song.topics.contains(old_topic))
@ -431,7 +432,8 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
# Find the duplicate. # Find the duplicate.
existing_book = self.manager.get_object_filtered(Book, existing_book = self.manager.get_object_filtered(Book,
and_(Book.name == old_book.name, and_(Book.name == old_book.name,
Book.publisher == old_book.publisher)) Book.publisher == old_book.publisher,
Book.id != old_book.id))
# Find the songs, which have the old_book as book. # Find the songs, which have the old_book as book.
songs = self.manager.get_all_objects(Song, songs = self.manager.get_all_objects(Song,
Song.song_book_id == old_book.id) Song.song_book_id == old_book.id)
@ -504,3 +506,4 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog):
else: else:
deleteButton.setEnabled(True) deleteButton.setEnabled(True)
editButton.setEnabled(True) editButton.setEnabled(True)

View File

@ -257,7 +257,7 @@ def clean_song(manager, song):
``song`` ``song``
The song object. The song object.
""" """
song.title = song.title.strip() if song.title else u'' song.title = song.title.rstrip() if song.title else u''
if song.alternate_title is None: if song.alternate_title is None:
song.alternate_title = u'' song.alternate_title = u''
song.alternate_title = song.alternate_title.strip() song.alternate_title = song.alternate_title.strip()
@ -278,24 +278,32 @@ def clean_song(manager, song):
# List for later comparison. # List for later comparison.
compare_order = [] compare_order = []
for verse in verses: for verse in verses:
type = VerseType.Tags[VerseType.from_loose_input(verse[0][u'type'])] verse_type = VerseType.Tags[VerseType.from_loose_input(
verse[0][u'type'])]
sxml.add_verse_to_lyrics( sxml.add_verse_to_lyrics(
type, verse_type,
verse[0][u'label'], verse[0][u'label'],
verse[1], verse[1],
verse[0][u'lang'] if verse[0].has_key(u'lang') else None verse[0][u'lang'] if verse[0].has_key(u'lang') else None
) )
compare_order.append((u'%s%s' % (type, verse[0][u'label'])).upper()) compare_order.append((u'%s%s' % (verse_type, verse[0][u'label'])
).upper())
if verse[0][u'label'] == u'1':
compare_order.append(verse_type.upper())
song.lyrics = unicode(sxml.extract_xml(), u'utf-8') song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
# Rebuild the verse order, to convert translated verse tags, which might # Rebuild the verse order, to convert translated verse tags, which might
# have been added prior to 1.9.5. # have been added prior to 1.9.5.
order = song.verse_order.strip().split() if song.verse_order:
order = song.verse_order.strip().split()
else:
order = []
new_order = [] new_order = []
for verse_def in order: for verse_def in order:
new_order.append((u'%s%s' % ( verse_type = VerseType.Tags[VerseType.from_loose_input(verse_def[0])]
VerseType.Tags[VerseType.from_loose_input(verse_def[0])], if len(verse_def) > 1:
verse_def[1:])).upper() new_order.append((u'%s%s' % (verse_type, verse_def[1:])).upper())
) else:
new_order.append(verse_type.upper())
song.verse_order = u' '.join(new_order) song.verse_order = u' '.join(new_order)
# Check if the verse order contains tags for verses which do not exist. # Check if the verse order contains tags for verses which do not exist.
for order in new_order: for order in new_order:

View File

@ -59,16 +59,10 @@ class CCLIFileImport(SongImport):
Import either a ``.usr`` or a ``.txt`` SongSelect file. Import either a ``.usr`` or a ``.txt`` SongSelect file.
""" """
log.debug(u'Starting CCLI File Import') log.debug(u'Starting CCLI File Import')
song_total = len(self.import_source) self.import_wizard.progressBar.setMaximum(len(self.import_source))
self.import_wizard.progressBar.setMaximum(song_total)
song_count = 1
for filename in self.import_source: for filename in self.import_source:
self.import_wizard.incrementProgressBar(unicode(translate(
'SongsPlugin.CCLIFileImport', 'Importing song %d of %d')) %
(song_count, song_total))
filename = unicode(filename) filename = unicode(filename)
log.debug(u'Importing CCLI File: %s', filename) log.debug(u'Importing CCLI File: %s', filename)
self.set_defaults()
lines = [] lines = []
if os.path.isfile(filename): if os.path.isfile(filename):
detect_file = open(filename, u'r') detect_file = open(filename, u'r')
@ -81,19 +75,23 @@ class CCLIFileImport(SongImport):
detect_file.close() detect_file.close()
infile = codecs.open(filename, u'r', details['encoding']) infile = codecs.open(filename, u'r', details['encoding'])
lines = infile.readlines() lines = infile.readlines()
infile.close()
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.usr': if ext.lower() == u'.usr':
log.info(u'SongSelect .usr format file found: %s', filename) log.info(u'SongSelect .usr format file found: %s', filename)
self.do_import_usr_file(lines) if not self.do_import_usr_file(lines):
self.log_error(filename)
elif ext.lower() == u'.txt': elif ext.lower() == u'.txt':
log.info(u'SongSelect .txt format file found: %s', filename) log.info(u'SongSelect .txt format file found: %s', filename)
self.do_import_txt_file(lines) if not self.do_import_txt_file(lines):
self.log_error(filename)
else: else:
self.log_error(filename,
translate('SongsPlugin.CCLIFileImport',
'The file does not have a valid extension.'))
log.info(u'Extension %s is not valid', filename) log.info(u'Extension %s is not valid', filename)
song_count += 1
if self.stop_import_flag: if self.stop_import_flag:
return False return
return True
def do_import_usr_file(self, textList): def do_import_usr_file(self, textList):
""" """
@ -218,7 +216,7 @@ class CCLIFileImport(SongImport):
else: else:
self.add_author(author) self.add_author(author)
self.topics = [topic.strip() for topic in song_topics.split(u'/t')] self.topics = [topic.strip() for topic in song_topics.split(u'/t')]
self.finish() return self.finish()
def do_import_txt_file(self, textList): def do_import_txt_file(self, textList):
""" """
@ -334,6 +332,5 @@ class CCLIFileImport(SongImport):
if len(author_list) < 2: if len(author_list) < 2:
author_list = song_author.split(u'|') author_list = song_author.split(u'|')
# Clean spaces before and after author names. # Clean spaces before and after author names.
for author_name in author_list: [self.add_author(author_name.strip()) for author_name in author_list]
self.add_author(author_name.strip()) return self.finish()
self.finish()

View File

@ -26,11 +26,13 @@
import logging import logging
import os import os
from lxml import etree, objectify
import re import re
from lxml import etree, objectify
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -56,26 +58,16 @@ class EasiSlidesImport(SongImport):
multiple opensong files. If `self.commit` is set False, the multiple opensong files. If `self.commit` is set False, the
import will not be committed to the database (useful for test scripts). import will not be committed to the database (useful for test scripts).
""" """
self.import_wizard.progressBar.setMaximum(1)
log.info(u'Importing EasiSlides XML file %s', self.import_source) log.info(u'Importing EasiSlides XML file %s', self.import_source)
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
file = etree.parse(self.import_source, parser) file = etree.parse(self.import_source, parser)
xml = unicode(etree.tostring(file)) xml = unicode(etree.tostring(file))
song_xml = objectify.fromstring(xml) song_xml = objectify.fromstring(xml)
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.split(self.import_source)[-1])
self.import_wizard.progressBar.setMaximum(len(song_xml.Item)) self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
for song in song_xml.Item: for song in song_xml.Item:
self.import_wizard.incrementProgressBar( if self.stop_import_flag:
unicode(translate('SongsPlugin.ImportWizardForm', return
u'Importing %s, song %s...')) % self._parse_song(song)
(os.path.split(self.import_source)[-1], song.Title1))
success = self._parse_song(song)
if not success or self.stop_import_flag:
return False
elif self.commit:
self.finish()
return True
def _parse_song(self, song): def _parse_song(self, song):
self._success = True self._success = True
@ -90,7 +82,11 @@ class EasiSlidesImport(SongImport):
self._add_copyright(song.LicenceAdmin2) self._add_copyright(song.LicenceAdmin2)
self._add_unicode_attribute(u'song_book_name', song.BookReference) self._add_unicode_attribute(u'song_book_name', song.BookReference)
self._parse_and_add_lyrics(song) self._parse_and_add_lyrics(song)
return self._success if self._success:
if not self.finish():
self.log_error(song.Title1 if song.Title1 else u'')
else:
self.set_defaults()
def _add_unicode_attribute(self, self_attribute, import_attribute, def _add_unicode_attribute(self, self_attribute, import_attribute,
mandatory=False): mandatory=False):
@ -122,10 +118,8 @@ class EasiSlidesImport(SongImport):
def _add_authors(self, song): def _add_authors(self, song):
try: try:
authors = unicode(song.Writer).split(u',') authors = unicode(song.Writer).split(u',')
for author in authors: self.authors = \
author = author.strip() [author.strip() for author in authors if author.strip()]
if len(author):
self.authors.append(author)
except UnicodeDecodeError: except UnicodeDecodeError:
log.exception(u'Unicode decode error while decoding Writer') log.exception(u'Unicode decode error while decoding Writer')
self._success = False self._success = False
@ -188,12 +182,13 @@ class EasiSlidesImport(SongImport):
# if the regions are inside verses # if the regions are inside verses
regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1) regionsInVerses = (regions and regionlines[regionlines.keys()[0]] > 1)
MarkTypes = { MarkTypes = {
u'CHORUS': u'C', u'CHORUS': VerseType.Tags[VerseType.Chorus],
u'VERSE': u'V', u'VERSE': VerseType.Tags[VerseType.Verse],
u'INTRO': u'I', u'INTRO': VerseType.Tags[VerseType.Intro],
u'ENDING': u'E', u'ENDING': VerseType.Tags[VerseType.Ending],
u'BRIDGE': u'B', u'BRIDGE': VerseType.Tags[VerseType.Bridge],
u'PRECHORUS': u'P'} u'PRECHORUS': VerseType.Tags[VerseType.PreChorus]
}
verses = {} verses = {}
# list as [region, versetype, versenum, instance] # list as [region, versetype, versenum, instance]
our_verse_order = [] our_verse_order = []

View File

@ -33,6 +33,7 @@ import struct
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib import retrieve_windows_encoding from openlp.plugins.songs.lib import retrieve_windows_encoding
from songimport import SongImport from songimport import SongImport
@ -142,12 +143,12 @@ class EasyWorshipSongImport(SongImport):
# Open the DB and MB files if they exist # Open the DB and MB files if they exist
import_source_mb = self.import_source.replace('.DB', '.MB') import_source_mb = self.import_source.replace('.DB', '.MB')
if not os.path.isfile(self.import_source): if not os.path.isfile(self.import_source):
return False return
if not os.path.isfile(import_source_mb): if not os.path.isfile(import_source_mb):
return False return
db_size = os.path.getsize(self.import_source) db_size = os.path.getsize(self.import_source)
if db_size < 0x800: if db_size < 0x800:
return False return
db_file = open(self.import_source, 'rb') db_file = open(self.import_source, 'rb')
self.memo_file = open(import_source_mb, 'rb') self.memo_file = open(import_source_mb, 'rb')
# Don't accept files that are clearly not paradox files # Don't accept files that are clearly not paradox files
@ -156,7 +157,7 @@ class EasyWorshipSongImport(SongImport):
if header_size != 0x800 or block_size < 1 or block_size > 4: if header_size != 0x800 or block_size < 1 or block_size > 4:
db_file.close() db_file.close()
self.memo_file.close() self.memo_file.close()
return False return
# Take a stab at how text is encoded # Take a stab at how text is encoded
self.encoding = u'cp1252' self.encoding = u'cp1252'
db_file.seek(106) db_file.seek(106)
@ -183,7 +184,7 @@ class EasyWorshipSongImport(SongImport):
self.encoding = u'cp874' self.encoding = u'cp874'
self.encoding = retrieve_windows_encoding(self.encoding) self.encoding = retrieve_windows_encoding(self.encoding)
if not self.encoding: if not self.encoding:
return False return
# There does not appear to be a _reliable_ way of getting the number # There does not appear to be a _reliable_ way of getting the number
# of songs/records, so let's use file blocks for measuring progress. # of songs/records, so let's use file blocks for measuring progress.
total_blocks = (db_size - header_size) / (block_size * 1024) total_blocks = (db_size - header_size) / (block_size * 1024)
@ -203,8 +204,8 @@ class EasyWorshipSongImport(SongImport):
field_size)) field_size))
self.set_record_struct(field_descs) self.set_record_struct(field_descs)
# Pick out the field description indexes we will need # Pick out the field description indexes we will need
success = True
try: try:
success = True
fi_title = self.find_field(u'Title') fi_title = self.find_field(u'Title')
fi_author = self.find_field(u'Author') fi_author = self.find_field(u'Author')
fi_copy = self.find_field(u'Copyright') fi_copy = self.find_field(u'Copyright')
@ -223,31 +224,25 @@ class EasyWorshipSongImport(SongImport):
# Loop through each record within the current block # Loop through each record within the current block
for i in range(rec_count): for i in range(rec_count):
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
raw_record = db_file.read(record_size) raw_record = db_file.read(record_size)
self.fields = self.record_struct.unpack(raw_record) self.fields = self.record_struct.unpack(raw_record)
self.set_defaults() self.set_defaults()
# Get title and update progress bar message self.title = self.get_field(fi_title)
title = self.get_field(fi_title) # Get remaining fields.
if title:
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % title, 0)
self.title = title
# Get remaining fields
copy = self.get_field(fi_copy) copy = self.get_field(fi_copy)
admin = self.get_field(fi_admin) admin = self.get_field(fi_admin)
ccli = self.get_field(fi_ccli) ccli = self.get_field(fi_ccli)
authors = self.get_field(fi_author) authors = self.get_field(fi_author)
words = self.get_field(fi_words) words = self.get_field(fi_words)
# Set the SongImport object members # Set the SongImport object members.
if copy: if copy:
self.copyright = copy self.copyright = copy
if admin: if admin:
if copy: if copy:
self.copyright += u', ' self.copyright += u', '
self.copyright += \ self.copyright += \
unicode(translate('SongsPlugin.ImportWizardForm', unicode(translate('SongsPlugin.EasyWorshipSongImport',
'Administered by %s')) % admin 'Administered by %s')) % admin
if ccli: if ccli:
self.ccli_number = ccli self.ccli_number = ccli
@ -264,19 +259,17 @@ class EasyWorshipSongImport(SongImport):
# Format the lyrics # Format the lyrics
words = strip_rtf(words, self.encoding) words = strip_rtf(words, self.encoding)
for verse in words.split(u'\n\n'): for verse in words.split(u'\n\n'):
self.add_verse(verse.strip(), u'V') self.add_verse(
verse.strip(), VerseType.Tags[VerseType.Verse])
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
self.finish() if not self.finish():
if not self.stop_import_flag: self.log_error(self.import_source)
self.import_wizard.incrementProgressBar(u'')
db_file.close() db_file.close()
self.memo_file.close() self.memo_file.close()
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):

View File

@ -97,6 +97,7 @@ from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib import clean_song, VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
from openlp.plugins.songs.lib.ui import SongStrings
from openlp.plugins.songs.lib.xml import SongXML from openlp.plugins.songs.lib.xml import SongXML
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -121,17 +122,16 @@ class FoilPresenterImport(SongImport):
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
for file_path in self.import_source: for file_path in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
return False return
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.basename(file_path)) WizardStrings.ImportingType % os.path.basename(file_path))
try: try:
parsed_file = etree.parse(file_path, parser) parsed_file = etree.parse(file_path, parser)
xml = unicode(etree.tostring(parsed_file)) xml = unicode(etree.tostring(parsed_file))
if self.FoilPresenter.xml_to_song(xml) is None: self.FoilPresenter.xml_to_song(xml)
log.debug(u'File could not be imported: %s' % file_path)
except etree.XMLSyntaxError: except etree.XMLSyntaxError:
self.log_error(file_path, SongStrings.XMLSyntaxError)
log.exception(u'XML syntax error in file %s' % file_path) log.exception(u'XML syntax error in file %s' % file_path)
return True
class FoilPresenter(object): class FoilPresenter(object):
@ -211,7 +211,7 @@ class FoilPresenter(object):
""" """
# No xml get out of here. # No xml get out of here.
if not xml: if not xml:
return None return
if xml[:5] == u'<?xml': if xml[:5] == u'<?xml':
xml = xml[38:] xml = xml[38:]
song = Song() song = Song()
@ -235,7 +235,6 @@ class FoilPresenter(object):
self._process_topics(foilpresenterfolie, song) self._process_topics(foilpresenterfolie, song)
clean_song(self.manager, song) clean_song(self.manager, song)
self.manager.save_object(song) self.manager.save_object(song)
return song.id
def _child(self, element): def _child(self, element):
""" """
@ -305,9 +304,8 @@ class FoilPresenter(object):
for marker in markers: for marker in markers:
copyright = re.compile(marker).sub(u'<marker>', copyright, re.U) copyright = re.compile(marker).sub(u'<marker>', copyright, re.U)
copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright) copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright)
i = 0
x = 0 x = 0
while i != 1: while True:
if copyright.find(u'<marker>') != -1: if copyright.find(u'<marker>') != -1:
temp = copyright.partition(u'<marker>') temp = copyright.partition(u'<marker>')
if temp[0].strip() and x > 0: if temp[0].strip() and x > 0:
@ -316,9 +314,9 @@ class FoilPresenter(object):
x += 1 x += 1
elif x > 0: elif x > 0:
strings.append(copyright) strings.append(copyright)
i = 1 break
else: else:
i = 1 break
author_temp = [] author_temp = []
for author in strings: for author in strings:
temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);', temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);',
@ -349,8 +347,8 @@ class FoilPresenter(object):
if author is None: if author is None:
# We need to create a new author, as the author does not exist. # We need to create a new author, as the author does not exist.
author = Author.populate(display_name=display_name, author = Author.populate(display_name=display_name,
last_name = display_name.split(u' ')[-1], last_name=display_name.split(u' ')[-1],
first_name = u' '.join(display_name.split(u' ')[:-1])) first_name=u' '.join(display_name.split(u' ')[:-1]))
self.manager.save_object(author) self.manager.save_object(author)
song.authors.append(author) song.authors.append(author)
@ -414,8 +412,15 @@ class FoilPresenter(object):
temp_verse_order_backup = [] temp_verse_order_backup = []
temp_sortnr_backup = 1 temp_sortnr_backup = 1
temp_sortnr_liste = [] temp_sortnr_liste = []
versenumber = {u'V': 1, u'C': 1, u'B': 1, u'E': 1, u'O': 1, u'I': 1, versenumber = {
u'P': 1} VerseType.Tags[VerseType.Verse]: 1,
VerseType.Tags[VerseType.Chorus]: 1,
VerseType.Tags[VerseType.Bridge]: 1,
VerseType.Tags[VerseType.Ending]: 1,
VerseType.Tags[VerseType.Other]: 1,
VerseType.Tags[VerseType.Intro]: 1,
VerseType.Tags[VerseType.PreChorus]: 1
}
for strophe in foilpresenterfolie.strophen.strophe: for strophe in foilpresenterfolie.strophen.strophe:
text = self._child(strophe.text_) text = self._child(strophe.text_)
verse_name = self._child(strophe.key) verse_name = self._child(strophe.key)
@ -434,25 +439,25 @@ class FoilPresenter(object):
temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name) temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name)
temp_verse_name = temp_verse_name[:3].lower() temp_verse_name = temp_verse_name[:3].lower()
if temp_verse_name == u'ref': if temp_verse_name == u'ref':
verse_type = u'C' verse_type = VerseType.Tags[VerseType.Chorus]
elif temp_verse_name == u'r': elif temp_verse_name == u'r':
verse_type = u'C' verse_type = VerseType.Tags[VerseType.Chorus]
elif temp_verse_name == u'': elif temp_verse_name == u'':
verse_type = u'V' verse_type = VerseType.Tags[VerseType.Verse]
elif temp_verse_name == u'v': elif temp_verse_name == u'v':
verse_type = u'V' verse_type = VerseType.Tags[VerseType.Verse]
elif temp_verse_name == u'bri': elif temp_verse_name == u'bri':
verse_type = u'B' verse_type = VerseType.Tags[VerseType.Bridge]
elif temp_verse_name == u'cod': elif temp_verse_name == u'cod':
verse_type = u'E' verse_type = VerseType.Tags[VerseType.Ending]
elif temp_verse_name == u'sch': elif temp_verse_name == u'sch':
verse_type = u'E' verse_type = VerseType.Tags[VerseType.Ending]
elif temp_verse_name == u'pre': elif temp_verse_name == u'pre':
verse_type = u'P' verse_type = VerseType.Tags[VerseType.PreChorus]
elif temp_verse_name == u'int': elif temp_verse_name == u'int':
verse_type = u'I' verse_type = VerseType.Tags[VerseType.Intro]
else: else:
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name) verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name)
# Foilpresenter allows e. g. "C", but we need "C1". # Foilpresenter allows e. g. "C", but we need "C1".
if not verse_number: if not verse_number:
@ -466,8 +471,8 @@ class FoilPresenter(object):
verse_number = unicode(int(verse_number) + 1) verse_number = unicode(int(verse_number) + 1)
verse_type_index = VerseType.from_tag(verse_type[0]) verse_type_index = VerseType.from_tag(verse_type[0])
verse_type = VerseType.Names[verse_type_index] verse_type = VerseType.Names[verse_type_index]
temp_verse_order[verse_sortnr] = (u''.join((verse_type[0], temp_verse_order[verse_sortnr] = u''.join((verse_type[0],
verse_number))) verse_number))
temp_verse_order_backup.append(u''.join((verse_type[0], temp_verse_order_backup.append(u''.join((verse_type[0],
verse_number))) verse_number)))
sxml.add_verse_to_lyrics(verse_type, verse_number, text) sxml.add_verse_to_lyrics(verse_type, verse_number, text)

View File

@ -137,8 +137,8 @@ class SongMediaItem(MediaManagerItem):
QtCore.QVariant(u'True')).toBool() QtCore.QVariant(u'True')).toBool()
def retranslateUi(self): def retranslateUi(self):
self.searchTextLabel.setText(u'%s:' % UiStrings.Search) self.searchTextLabel.setText(u'%s:' % UiStrings().Search)
self.searchTextButton.setText(UiStrings.Search) self.searchTextButton.setText(UiStrings().Search)
self.maintenanceAction.setText(SongStrings.SongMaintenance) self.maintenanceAction.setText(SongStrings.SongMaintenance)
self.maintenanceAction.setToolTip(translate('SongsPlugin.MediaItem', self.maintenanceAction.setToolTip(translate('SongsPlugin.MediaItem',
'Maintain the lists of authors, topics and books')) 'Maintain the lists of authors, topics and books'))
@ -153,7 +153,7 @@ class SongMediaItem(MediaManagerItem):
translate('SongsPlugin.MediaItem', 'Lyrics')), translate('SongsPlugin.MediaItem', 'Lyrics')),
(SongSearch.Authors, u':/songs/song_search_author.png', (SongSearch.Authors, u':/songs/song_search_author.png',
SongStrings.Authors), SongStrings.Authors),
(SongSearch.Themes, u':/slides/slide_theme.png', UiStrings.Themes) (SongSearch.Themes, u':/slides/slide_theme.png', UiStrings().Themes)
]) ])
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value( self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value(
u'%s/last search type' % self.settingsSection, u'%s/last search type' % self.settingsSection,
@ -312,7 +312,7 @@ class SongMediaItem(MediaManagerItem):
Edit a song Edit a song
""" """
log.debug(u'onEditClick') log.debug(u'onEditClick')
if check_item_selected(self.listView, UiStrings.SelectEdit): if check_item_selected(self.listView, UiStrings().SelectEdit):
self.editItem = self.listView.currentItem() self.editItem = self.listView.currentItem()
item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
self.edit_song_form.loadSong(item_id, False) self.edit_song_form.loadSong(item_id, False)
@ -323,7 +323,7 @@ class SongMediaItem(MediaManagerItem):
""" """
Remove a song from the list and database Remove a song from the list and database
""" """
if check_item_selected(self.listView, UiStrings.SelectDelete): if check_item_selected(self.listView, UiStrings().SelectDelete):
items = self.listView.selectedIndexes() items = self.listView.selectedIndexes()
if QtGui.QMessageBox.question(self, if QtGui.QMessageBox.question(self,
translate('SongsPlugin.MediaItem', 'Delete Song(s)?'), translate('SongsPlugin.MediaItem', 'Delete Song(s)?'),
@ -347,6 +347,7 @@ class SongMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.AllowsLoop) service_item.add_capability(ItemCapabilities.AllowsLoop)
service_item.add_capability(ItemCapabilities.OnLoadUpdate) service_item.add_capability(ItemCapabilities.OnLoadUpdate)
service_item.add_capability(ItemCapabilities.AddIfNewItem) service_item.add_capability(ItemCapabilities.AddIfNewItem)
service_item.add_capability(ItemCapabilities.AllowsVirtualSplit)
song = self.parent.manager.get_object(Song, item_id) song = self.parent.manager.get_object(Song, item_id)
service_item.theme = song.theme_name service_item.theme = song.theme_name
service_item.edit_id = item_id service_item.edit_id = item_id
@ -472,4 +473,4 @@ class SongMediaItem(MediaManagerItem):
Locale aware collation of song titles Locale aware collation of song titles
""" """
return locale.strcoll(unicode(song_1.title.lower()), return locale.strcoll(unicode(song_1.title.lower()),
unicode(song_2.title.lower())) unicode(song_2.title.lower()))

View File

@ -32,7 +32,7 @@ import logging
from chardet.universaldetector import UniversalDetector from chardet.universaldetector import UniversalDetector
import sqlite import sqlite
from openlp.core.ui.wizard import WizardStrings from openlp.core.lib import translate
from openlp.plugins.songs.lib import retrieve_windows_encoding from openlp.plugins.songs.lib import retrieve_windows_encoding
from songimport import SongImport from songimport import SongImport
@ -61,10 +61,15 @@ class OpenLP1SongImport(SongImport):
""" """
Run the import for an openlp.org 1.x song database. Run the import for an openlp.org 1.x song database.
""" """
# Connect to the database if not self.import_source.endswith(u'.olp'):
self.log_error(self.import_source,
translate('SongsPlugin.OpenLP1SongImport',
'Not a valid openlp.org 1.x song database.'))
return
encoding = self.get_encoding() encoding = self.get_encoding()
if not encoding: if not encoding:
return False return
# Connect to the database
connection = sqlite.connect(self.import_source, mode=0444, connection = sqlite.connect(self.import_source, mode=0444,
encoding=(encoding, 'replace')) encoding=(encoding, 'replace'))
cursor = connection.cursor() cursor = connection.cursor()
@ -72,12 +77,6 @@ class OpenLP1SongImport(SongImport):
cursor.execute(u'SELECT name FROM sqlite_master ' cursor.execute(u'SELECT name FROM sqlite_master '
u'WHERE type = \'table\' AND name = \'tracks\'') u'WHERE type = \'table\' AND name = \'tracks\'')
new_db = len(cursor.fetchall()) > 0 new_db = len(cursor.fetchall()) > 0
# Count the number of records we need to import, for the progress bar
cursor.execute(u'-- types int')
cursor.execute(u'SELECT COUNT(songid) FROM songs')
count = cursor.fetchone()[0]
success = True
self.import_wizard.progressBar.setMaximum(count)
# "cache" our list of authors # "cache" our list of authors
cursor.execute(u'-- types int, unicode') cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT authorid, authorname FROM authors') cursor.execute(u'SELECT authorid, authorname FROM authors')
@ -92,37 +91,29 @@ class OpenLP1SongImport(SongImport):
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, ' cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
u'copyrightinfo FROM songs') u'copyrightinfo FROM songs')
songs = cursor.fetchall() songs = cursor.fetchall()
self.import_wizard.progressBar.setMaximum(len(songs))
for song in songs: for song in songs:
self.set_defaults() self.set_defaults()
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
song_id = song[0] song_id = song[0]
title = song[1] self.title = song[1]
lyrics = song[2].replace(u'\r\n', u'\n') lyrics = song[2].replace(u'\r\n', u'\n')
copyright = song[3] self.add_copyright(song[3])
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % title)
self.title = title
verses = lyrics.split(u'\n\n') verses = lyrics.split(u'\n\n')
for verse in verses: [self.add_verse(verse.strip()) for verse in verses if verse.strip()]
if verse.strip() != u'':
self.add_verse(verse.strip())
self.add_copyright(copyright)
cursor.execute(u'-- types int') cursor.execute(u'-- types int')
cursor.execute(u'SELECT authorid FROM songauthors ' cursor.execute(u'SELECT authorid FROM songauthors '
u'WHERE songid = %s' % song_id) u'WHERE songid = %s' % song_id)
author_ids = cursor.fetchall() author_ids = cursor.fetchall()
for author_id in author_ids: for author_id in author_ids:
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
for author in authors: for author in authors:
if author[0] == author_id[0]: if author[0] == author_id[0]:
self.parse_author(author[1]) self.parse_author(author[1])
break break
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
if new_db: if new_db:
cursor.execute(u'-- types int') cursor.execute(u'-- types int')
@ -131,17 +122,15 @@ class OpenLP1SongImport(SongImport):
track_ids = cursor.fetchall() track_ids = cursor.fetchall()
for track_id in track_ids: for track_id in track_ids:
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
for track in tracks: for track in tracks:
if track[0] == track_id[0]: if track[0] == track_id[0]:
self.add_media_file(track[1]) self.add_media_file(track[1])
break break
if self.stop_import_flag: if self.stop_import_flag:
success = False
break break
self.finish() if not self.finish():
return success self.log_error(self.import_source)
def get_encoding(self): def get_encoding(self):
""" """

View File

@ -36,6 +36,7 @@ from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.db import BaseModel from openlp.core.lib.db import BaseModel
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import clean_song from openlp.plugins.songs.lib import clean_song
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile
from songimport import SongImport from songimport import SongImport
@ -93,13 +94,18 @@ class OpenLPSongImport(SongImport):
The database providing the data to import. The database providing the data to import.
""" """
SongImport.__init__(self, manager, **kwargs) SongImport.__init__(self, manager, **kwargs)
self.import_source = u'sqlite:///%s' % self.import_source
self.source_session = None self.source_session = None
def do_import(self): def do_import(self):
""" """
Run the import for an OpenLP version 2 song database. Run the import for an OpenLP version 2 song database.
""" """
if not self.import_source.endswith(u'.sqlite'):
self.log_error(self.import_source,
translate('SongsPlugin.OpenLPSongImport',
'Not a valid OpenLP 2.0 song database.'))
return
self.import_source = u'sqlite:///%s' % self.import_source
engine = create_engine(self.import_source) engine = create_engine(self.import_source)
source_meta = MetaData() source_meta = MetaData()
source_meta.reflect(engine) source_meta.reflect(engine)
@ -124,10 +130,10 @@ class OpenLPSongImport(SongImport):
mapper(OldMediaFile, source_media_files_table) mapper(OldMediaFile, source_media_files_table)
song_props = { song_props = {
'authors': relation(OldAuthor, backref='songs', 'authors': relation(OldAuthor, backref='songs',
secondary=source_authors_songs_table), secondary=source_authors_songs_table),
'book': relation(OldBook, backref='songs'), 'book': relation(OldBook, backref='songs'),
'topics': relation(OldTopic, backref='songs', 'topics': relation(OldTopic, backref='songs',
secondary=source_songs_topics_table) secondary=source_songs_topics_table)
} }
if has_media_files: if has_media_files:
song_props['media_files'] = relation(OldMediaFile, backref='songs', song_props['media_files'] = relation(OldMediaFile, backref='songs',
@ -150,15 +156,9 @@ class OpenLPSongImport(SongImport):
mapper(OldTopic, source_topics_table) mapper(OldTopic, source_topics_table)
source_songs = self.source_session.query(OldSong).all() source_songs = self.source_session.query(OldSong).all()
song_total = len(source_songs)
if self.import_wizard: if self.import_wizard:
self.import_wizard.progressBar.setMaximum(song_total) self.import_wizard.progressBar.setMaximum(len(source_songs))
song_count = 1
for song in source_songs: for song in source_songs:
if self.import_wizard:
self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.OpenLPSongImport',
'Importing song %d of %d.')) % (song_count, song_total))
new_song = Song() new_song = Song()
new_song.title = song.title new_song.title = song.title
if has_media_files and hasattr(song, 'alternate_title'): if has_media_files and hasattr(song, 'alternate_title'):
@ -213,8 +213,9 @@ class OpenLPSongImport(SongImport):
# file_name=media_file.file_name)) # file_name=media_file.file_name))
clean_song(self.manager, new_song) clean_song(self.manager, new_song)
self.manager.save_object(new_song) self.manager.save_object(new_song)
song_count += 1 if self.import_wizard:
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % new_song.title)
if self.stop_import_flag: if self.stop_import_flag:
return False break
engine.dispose() engine.dispose()
return True

View File

@ -56,13 +56,11 @@ class OooImport(SongImport):
self.process_started = False self.process_started = False
def do_import(self): def do_import(self):
self.stop_import_flag = False
self.import_wizard.progressBar.setMaximum(0)
self.start_ooo() self.start_ooo()
self.import_wizard.progressBar.setMaximum(len(self.import_source))
for filename in self.import_source: for filename in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
self.import_wizard.incrementProgressBar(u'Import cancelled', 0) break
return
filename = unicode(filename) filename = unicode(filename)
if os.path.isfile(filename): if os.path.isfile(filename):
self.open_ooo_file(filename) self.open_ooo_file(filename)
@ -70,9 +68,6 @@ class OooImport(SongImport):
self.process_ooo_document() self.process_ooo_document()
self.close_ooo_file() self.close_ooo_file()
self.close_ooo() self.close_ooo()
self.import_wizard.progressBar.setMaximum(1)
self.import_wizard.incrementProgressBar(u'', 1)
return True
def process_ooo_document(self): def process_ooo_document(self):
""" """

View File

@ -35,6 +35,7 @@ from lxml import etree
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
from openlp.plugins.songs.lib.ui import SongStrings
from openlp.plugins.songs.lib import OpenLyrics from openlp.plugins.songs.lib import OpenLyrics
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -59,7 +60,7 @@ class OpenLyricsImport(SongImport):
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
for file_path in self.import_source: for file_path in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
return False return
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.basename(file_path)) WizardStrings.ImportingType % os.path.basename(file_path))
try: try:
@ -67,8 +68,7 @@ class OpenLyricsImport(SongImport):
# special characters in the path (see lp:757673 and lp:744337). # special characters in the path (see lp:757673 and lp:744337).
parsed_file = etree.parse(open(file_path, u'r'), parser) parsed_file = etree.parse(open(file_path, u'r'), parser)
xml = unicode(etree.tostring(parsed_file)) xml = unicode(etree.tostring(parsed_file))
if self.openLyrics.xml_to_song(xml) is None: self.openLyrics.xml_to_song(xml)
log.debug(u'File could not be imported: %s' % file_path)
except etree.XMLSyntaxError: except etree.XMLSyntaxError:
log.exception(u'XML syntax error in file %s' % file_path) log.exception(u'XML syntax error in file %s' % file_path)
return True self.log_error(file_path, SongStrings.XMLSyntaxError)

View File

@ -26,13 +26,15 @@
import logging import logging
import os import os
import re
from zipfile import ZipFile from zipfile import ZipFile
from lxml import objectify from lxml import objectify
from lxml.etree import Error, LxmlError from lxml.etree import Error, LxmlError
import re
from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
from openlp.plugins.songs.lib.ui import SongStrings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -105,77 +107,62 @@ class OpenSongImport(SongImport):
Initialise the class. Initialise the class.
""" """
SongImport.__init__(self, manager, **kwargs) SongImport.__init__(self, manager, **kwargs)
self.commit = True
def do_import(self): def do_import(self):
""" """
Import either each of the files in self.import_source - each element of Import either each of the files in self.import_source - each element of
which can be either a single opensong file, or a zipfile containing which can be either a single opensong file, or a zipfile containing
multiple opensong files. If `self.commit` is set False, the multiple opensong files.
import will not be committed to the database (useful for test scripts).
""" """
success = True
numfiles = 0 numfiles = 0
for filename in self.import_source: for filename in self.import_source:
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.zip': if ext.lower() == u'.zip':
z = ZipFile(filename, u'r') z = ZipFile(filename, u'r')
numfiles += len(z.infolist()) numfiles += len(z.infolist())
z.close()
else: else:
numfiles += 1 numfiles += 1
log.debug(u'Total number of files: %d', numfiles) log.debug(u'Total number of files: %d', numfiles)
self.import_wizard.progressBar.setMaximum(numfiles) self.import_wizard.progressBar.setMaximum(numfiles)
for filename in self.import_source: for filename in self.import_source:
if self.stop_import_flag: if self.stop_import_flag:
success = False return
break
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.zip': if ext.lower() == u'.zip':
log.debug(u'Zipfile found %s', filename) log.debug(u'Zipfile found %s', filename)
z = ZipFile(filename, u'r') z = ZipFile(filename, u'r')
for song in z.infolist(): for song in z.infolist():
if self.stop_import_flag: if self.stop_import_flag:
success = False z.close()
break return
parts = os.path.split(song.filename) parts = os.path.split(song.filename)
if parts[-1] == u'': if parts[-1] == u'':
#No final part => directory # No final part => directory
continue continue
log.info(u'Zip importing %s', parts[-1]) log.info(u'Zip importing %s', parts[-1])
self.import_wizard.incrementProgressBar( song_file = z.open(song)
WizardStrings.ImportingType % parts[-1]) self.do_import_file(song_file)
songfile = z.open(song) song_file.close()
if self.do_import_file(songfile) and self.commit and \ z.close()
not self.stop_import_flag:
self.finish()
else:
success = False
break
else: else:
# not a zipfile # not a zipfile
log.info(u'Direct import %s', filename) log.info(u'Direct import %s', filename)
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % os.path.split(filename)[-1])
song_file = open(filename) song_file = open(filename)
if self.do_import_file(song_file) and self.commit and \ self.do_import_file(song_file)
not self.stop_import_flag: song_file.close()
self.finish()
else:
success = False
break
return success
def do_import_file(self, file): def do_import_file(self, file):
""" """
Process the OpenSong file - pass in a file-like object, Process the OpenSong file - pass in a file-like object, not a file path.
not a filename
""" """
self.set_defaults() self.set_defaults()
try: try:
tree = objectify.parse(file) tree = objectify.parse(file)
except (Error, LxmlError): except (Error, LxmlError):
self.log_error(file.name, SongStrings.XMLSyntaxError)
log.exception(u'Error parsing XML') log.exception(u'Error parsing XML')
return False return
root = tree.getroot() root = tree.getroot()
fields = dir(root) fields = dir(root)
decode = { decode = {
@ -193,9 +180,6 @@ class OpenSongImport(SongImport):
setattr(self, fn_or_string, ustring) setattr(self, fn_or_string, ustring)
else: else:
fn_or_string(ustring) fn_or_string(ustring)
if not len(self.title):
# to prevent creation of empty songs from wrong files
return False
if u'theme' in fields and unicode(root.theme) not in self.topics: if u'theme' in fields and unicode(root.theme) not in self.topics:
self.topics.append(unicode(root.theme)) self.topics.append(unicode(root.theme))
if u'alttheme' in fields and unicode(root.alttheme) not in self.topics: if u'alttheme' in fields and unicode(root.alttheme) not in self.topics:
@ -205,11 +189,14 @@ class OpenSongImport(SongImport):
# keep track of verses appearance order # keep track of verses appearance order
our_verse_order = [] our_verse_order = []
# default verse # default verse
verse_tag = u'v' verse_tag = VerseType.Tags[VerseType.Verse]
verse_num = u'1' verse_num = u'1'
# for the case where song has several sections with same marker # for the case where song has several sections with same marker
inst = 1 inst = 1
lyrics = unicode(root.lyrics) if u'lyrics' in fields:
lyrics = unicode(root.lyrics)
else:
lyrics = u''
for this_line in lyrics.split(u'\n'): for this_line in lyrics.split(u'\n'):
# remove comments # remove comments
semicolon = this_line.find(u';') semicolon = this_line.find(u';')
@ -230,7 +217,7 @@ class OpenSongImport(SongImport):
# have we got any digits? # have we got any digits?
# If so, verse number is everything from the digits # If so, verse number is everything from the digits
# to the end (even if there are some alpha chars on the end) # to the end (even if there are some alpha chars on the end)
match = re.match(u'(.*)(\d+.*)', content) match = re.match(u'(\D*)(\d+.*)', content)
if match is not None: if match is not None:
verse_tag = match.group(1) verse_tag = match.group(1)
verse_num = match.group(2) verse_num = match.group(2)
@ -239,12 +226,13 @@ class OpenSongImport(SongImport):
# the verse tag # the verse tag
verse_tag = content verse_tag = content
verse_num = u'1' verse_num = u'1'
verse_index = VerseType.from_loose_input(verse_tag)
verse_tag = VerseType.Tags[verse_index]
inst = 1 inst = 1
if [verse_tag, verse_num, inst] in our_verse_order \ if [verse_tag, verse_num, inst] in our_verse_order \
and verses.has_key(verse_tag) \ and verses.has_key(verse_tag) \
and verses[verse_tag].has_key(verse_num): and verses[verse_tag].has_key(verse_num):
inst = len(verses[verse_tag][verse_num])+1 inst = len(verses[verse_tag][verse_num]) + 1
our_verse_order.append([verse_tag, verse_num, inst])
continue continue
# number at start of line.. it's verse number # number at start of line.. it's verse number
if this_line[0].isdigit(): if this_line[0].isdigit():
@ -257,6 +245,7 @@ class OpenSongImport(SongImport):
verses[verse_tag][verse_num] = {} verses[verse_tag][verse_num] = {}
if not verses[verse_tag][verse_num].has_key(inst): if not verses[verse_tag][verse_num].has_key(inst):
verses[verse_tag][verse_num][inst] = [] verses[verse_tag][verse_num][inst] = []
our_verse_order.append([verse_tag, verse_num, inst])
# Tidy text and remove the ____s from extended words # Tidy text and remove the ____s from extended words
this_line = self.tidy_text(this_line) this_line = self.tidy_text(this_line)
this_line = this_line.replace(u'_', u'') this_line = this_line.replace(u'_', u'')
@ -268,28 +257,31 @@ class OpenSongImport(SongImport):
verse_def = u'%s%s' % (verse_tag, verse_num) verse_def = u'%s%s' % (verse_tag, verse_num)
lines = u'\n'.join(verses[verse_tag][verse_num][inst]) lines = u'\n'.join(verses[verse_tag][verse_num][inst])
self.add_verse(lines, verse_def) self.add_verse(lines, verse_def)
if not self.verses:
self.add_verse('')
# figure out the presentation order, if present # figure out the presentation order, if present
if u'presentation' in fields and root.presentation != u'': if u'presentation' in fields and root.presentation:
order = unicode(root.presentation) order = unicode(root.presentation)
# We make all the tags in the lyrics lower case, so match that here # We make all the tags in the lyrics lower case, so match that here
# and then split into a list on the whitespace # and then split into a list on the whitespace
order = order.lower().split() order = order.lower().split()
for verse_def in order: for verse_def in order:
match = re.match(u'(.*)(\d+.*)', verse_def) match = re.match(u'(\D*)(\d+.*)', verse_def)
if match is not None: if match is not None:
verse_tag = match.group(1) verse_tag = match.group(1)
verse_num = match.group(2) verse_num = match.group(2)
if not len(verse_tag): if not len(verse_tag):
verse_tag = u'v' verse_tag = VerseType.Tags[VerseType.Verse]
else: else:
# Assume it's no.1 if there are no digits # Assume it's no.1 if there are no digits
verse_tag = verse_def verse_tag = verse_def
verse_num = u'1' verse_num = u'1'
verse_def = u'%s%s' % (verse_tag, verse_num) verse_def = u'%s%s' % (verse_tag, verse_num)
if verses.has_key(verse_tag) \ if verses.has_key(verse_tag) and \
and verses[verse_tag].has_key(verse_num): verses[verse_tag].has_key(verse_num):
self.verse_order_list.append(verse_def) self.verse_order_list.append(verse_def)
else: else:
log.info(u'Got order %s but not in verse tags, dropping' log.info(u'Got order %s but not in verse tags, dropping'
u'this item from presentation order', verse_def) u'this item from presentation order', verse_def)
return True if not self.finish():
self.log_error(file.name)

View File

@ -88,7 +88,6 @@ class SofImport(OooImport):
paragraphs = self.document.getText().createEnumeration() paragraphs = self.document.getText().createEnumeration()
while paragraphs.hasMoreElements(): while paragraphs.hasMoreElements():
if self.stop_import_flag: if self.stop_import_flag:
self.import_wizard.incrementProgressBar(u'Import cancelled', 0)
return return
paragraph = paragraphs.nextElement() paragraph = paragraphs.nextElement()
if paragraph.supportsService("com.sun.star.text.Paragraph"): if paragraph.supportsService("com.sun.star.text.Paragraph"):

View File

@ -33,9 +33,9 @@ import logging
import os import os
import re import re
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
from openlp.plugins.songs.lib.ui import SongStrings
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -78,58 +78,55 @@ class SongBeamerImport(SongImport):
""" """
Receive a single file or a list of files to import. Receive a single file or a list of files to import.
""" """
if isinstance(self.import_source, list): self.import_wizard.progressBar.setMaximum(len(self.import_source))
self.import_wizard.progressBar.setMaximum( if not isinstance(self.import_source, list):
len(self.import_source)) return
for file in self.import_source: for file in self.import_source:
# TODO: check that it is a valid SongBeamer file # TODO: check that it is a valid SongBeamer file
self.set_defaults() if self.stop_import_flag:
self.current_verse = u'' return
self.current_verse_type = VerseType.Tags[VerseType.Verse] self.set_defaults()
read_verses = False self.current_verse = u''
file_name = os.path.split(file)[1] self.current_verse_type = VerseType.Tags[VerseType.Verse]
self.import_wizard.incrementProgressBar( read_verses = False
WizardStrings.ImportingType % file_name, 0) file_name = os.path.split(file)[1]
if os.path.isfile(file): if os.path.isfile(file):
detect_file = open(file, u'r') detect_file = open(file, u'r')
details = chardet.detect(detect_file.read(2048)) details = chardet.detect(detect_file.read(2048))
detect_file.close() detect_file.close()
infile = codecs.open(file, u'r', details['encoding']) infile = codecs.open(file, u'r', details['encoding'])
songData = infile.readlines() songData = infile.readlines()
infile.close() infile.close()
else: else:
return False continue
self.title = file_name.split('.sng')[0] self.title = file_name.split('.sng')[0]
read_verses = False read_verses = False
for line in songData: for line in songData:
# Just make sure that the line is of the type 'Unicode'. # Just make sure that the line is of the type 'Unicode'.
line = unicode(line).strip() line = unicode(line).strip()
if line.startswith(u'#') and not read_verses: if line.startswith(u'#') and not read_verses:
self.parse_tags(line) self.parse_tags(line)
elif line.startswith(u'---'): elif line.startswith(u'---'):
if self.current_verse: if self.current_verse:
self.replace_html_tags() self.replace_html_tags()
self.add_verse(self.current_verse, self.add_verse(self.current_verse,
self.current_verse_type) self.current_verse_type)
self.current_verse = u'' self.current_verse = u''
self.current_verse_type = VerseType.Tags[VerseType.Verse] self.current_verse_type = VerseType.Tags[VerseType.Verse]
read_verses = True read_verses = True
verse_start = True verse_start = True
elif read_verses: elif read_verses:
if verse_start: if verse_start:
verse_start = False verse_start = False
if not self.check_verse_marks(line): if not self.check_verse_marks(line):
self.current_verse = line + u'\n' self.current_verse = line + u'\n'
else: else:
self.current_verse += line + u'\n' self.current_verse += line + u'\n'
if self.current_verse: if self.current_verse:
self.replace_html_tags() self.replace_html_tags()
self.add_verse(self.current_verse, self.current_verse_type) self.add_verse(self.current_verse, self.current_verse_type)
if self.check_complete(): if not self.finish():
self.finish() self.log_error(file)
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % file_name)
return True
def replace_html_tags(self): def replace_html_tags(self):
""" """
@ -189,7 +186,7 @@ class SongBeamerImport(SongImport):
elif tag_val[0] == u'#Bible': elif tag_val[0] == u'#Bible':
pass pass
elif tag_val[0] == u'#Categories': elif tag_val[0] == u'#Categories':
self.topics = line.split(',') self.topics = tag_val[1].split(',')
elif tag_val[0] == u'#CCLI': elif tag_val[0] == u'#CCLI':
self.ccli_number = tag_val[1] self.ccli_number = tag_val[1]
elif tag_val[0] == u'#Chords': elif tag_val[0] == u'#Chords':
@ -236,11 +233,12 @@ class SongBeamerImport(SongImport):
pass pass
elif tag_val[0] == u'#Rights': elif tag_val[0] == u'#Rights':
song_book_pub = tag_val[1] song_book_pub = tag_val[1]
elif tag_val[0] == u'#Songbook': elif tag_val[0] == u'#Songbook' or tag_val[0] == u'#SongBook':
book_num = tag_val[1].split(' / ') book_data = tag_val[1].split(u'/')
self.song_book_name = book_num[0] self.song_book_name = book_data[0].strip()
if len(book_num) == book_num[1]: if len(book_data) == 2:
self.song_number = u'' number = book_data[1].strip()
self.song_number = number if number.isdigit() else u''
elif tag_val[0] == u'#Speed': elif tag_val[0] == u'#Speed':
pass pass
elif tag_val[0] == u'Tempo': elif tag_val[0] == u'Tempo':
@ -287,5 +285,4 @@ class SongBeamerImport(SongImport):
if marks[1].isdigit(): if marks[1].isdigit():
self.current_verse_type += marks[1] self.current_verse_type += marks[1]
return True return True
else: return False
return False

View File

@ -23,12 +23,14 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 # # with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
import logging import logging
import re import re
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate from openlp.core.lib import Receiver, translate, check_directory_exists
from openlp.core.ui.wizard import WizardStrings
from openlp.core.utils import AppLocation
from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib import clean_song, VerseType
from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile from openlp.plugins.songs.lib.db import Song, Author, Topic, Book, MediaFile
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings
@ -66,6 +68,7 @@ class SongImport(QtCore.QObject):
self.song = None self.song = None
self.stop_import_flag = False self.stop_import_flag = False
self.set_defaults() self.set_defaults()
self.error_log = []
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
@ -94,6 +97,32 @@ class SongImport(QtCore.QObject):
self.copyright_string = unicode(translate( self.copyright_string = unicode(translate(
'SongsPlugin.SongImport', 'copyright')) 'SongsPlugin.SongImport', 'copyright'))
def log_error(self, filepath, reason=SongStrings.SongIncomplete):
"""
This should be called, when a song could not be imported.
``filepath``
This should be the file path if ``self.import_source`` is a list
with different files. If it is not a list, but a single file (for
instance a database), then this should be the song's title.
``reason``
The reason, why the import failed. The string should be as
informative as possible.
"""
self.set_defaults()
if self.import_wizard is None:
return
if self.import_wizard.errorReportTextEdit.isHidden():
self.import_wizard.errorReportTextEdit.setText(
translate('SongsPlugin.SongImport',
'The following songs could not be imported:'))
self.import_wizard.errorReportTextEdit.setVisible(True)
self.import_wizard.errorCopyToButton.setVisible(True)
self.import_wizard.errorSaveToButton.setVisible(True)
self.import_wizard.errorReportTextEdit.append(
u'- %s (%s)' % (filepath, reason))
def stop_import(self): def stop_import(self):
""" """
Sets the flag for importers to stop their import Sets the flag for importers to stop their import
@ -240,7 +269,7 @@ class SongImport(QtCore.QObject):
Author not checked here, if no author then "Author unknown" is Author not checked here, if no author then "Author unknown" is
automatically added automatically added
""" """
if self.title == u'' or len(self.verses) == 0: if not self.title or not len(self.verses):
return False return False
else: else:
return True return True
@ -249,9 +278,15 @@ class SongImport(QtCore.QObject):
""" """
All fields have been set to this song. Write the song to disk. All fields have been set to this song. Write the song to disk.
""" """
if not self.check_complete():
self.set_defaults()
return False
log.info(u'committing song %s to database', self.title) log.info(u'committing song %s to database', self.title)
song = Song() song = Song()
song.title = self.title song.title = self.title
if self.import_wizard is not None:
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % song.title)
song.alternate_title = self.alternate_title song.alternate_title = self.alternate_title
# Values will be set when cleaning the song. # Values will be set when cleaning the song.
song.search_title = u'' song.search_title = u''
@ -308,7 +343,7 @@ class SongImport(QtCore.QObject):
publisher=self.song_book_pub) publisher=self.song_book_pub)
song.book = song_book song.book = song_book
for topictext in self.topics: for topictext in self.topics:
if len(topictext) == 0: if not topictext:
continue continue
topic = self.manager.get_object_filtered(Topic, topic = self.manager.get_object_filtered(Topic,
Topic.name == topictext) Topic.name == topictext)
@ -318,6 +353,7 @@ class SongImport(QtCore.QObject):
clean_song(self.manager, song) clean_song(self.manager, song)
self.manager.save_object(song) self.manager.save_object(song)
self.set_defaults() self.set_defaults()
return True
def print_song(self): def print_song(self):
""" """

View File

@ -32,6 +32,7 @@ import logging
import struct import struct
from openlp.core.ui.wizard import WizardStrings from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib import VerseType
from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib.songimport import SongImport
TITLE = 1 TITLE = 1
@ -97,83 +98,81 @@ class SongShowPlusImport(SongImport):
Receive a single file or a list of files to import. Receive a single file or a list of files to import.
""" """
if isinstance(self.import_source, list): if isinstance(self.import_source, list):
self.import_wizard.progressBar.setMaximum(len(self.import_source)) return
for file in self.import_source: self.import_wizard.progressBar.setMaximum(len(self.import_source))
author = u'' for file in self.import_source:
self.sspVerseOrderList = [] self.sspVerseOrderList = []
otherCount = 0 otherCount = 0
otherList = {} otherList = {}
file_name = os.path.split(file)[1] file_name = os.path.split(file)[1]
self.import_wizard.incrementProgressBar( self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % file_name, 0) WizardStrings.ImportingType % file_name, 0)
songData = open(file, 'rb') songData = open(file, 'rb')
while (1): while True:
blockKey, = struct.unpack("I", songData.read(4)) blockKey, = struct.unpack("I", songData.read(4))
# The file ends with 4 NUL's # The file ends with 4 NUL's
if blockKey == 0: if blockKey == 0:
break break
nextBlockStarts, = struct.unpack("I", songData.read(4)) nextBlockStarts, = struct.unpack("I", songData.read(4))
if blockKey == VERSE or blockKey == CHORUS: if blockKey == VERSE or blockKey == CHORUS:
null, verseNo, = struct.unpack("BB", songData.read(2)) null, verseNo, = struct.unpack("BB", songData.read(2))
elif blockKey == CUSTOM_VERSE: elif blockKey == CUSTOM_VERSE:
null, verseNameLength, = struct.unpack("BB", null, verseNameLength, = struct.unpack("BB",
songData.read(2)) songData.read(2))
verseName = songData.read(verseNameLength) verseName = songData.read(verseNameLength)
lengthDescriptorSize, = struct.unpack("B", songData.read(1)) lengthDescriptorSize, = struct.unpack("B", songData.read(1))
# Detect if/how long the length descriptor is # Detect if/how long the length descriptor is
if lengthDescriptorSize == 12: if lengthDescriptorSize == 12:
lengthDescriptor, = struct.unpack("I", songData.read(4)) lengthDescriptor, = struct.unpack("I", songData.read(4))
elif lengthDescriptorSize == 2: elif lengthDescriptorSize == 2:
lengthDescriptor = 1 lengthDescriptor = 1
elif lengthDescriptorSize == 9: elif lengthDescriptorSize == 9:
lengthDescriptor = 0 lengthDescriptor = 0
else: else:
lengthDescriptor, = struct.unpack("B", songData.read(1)) lengthDescriptor, = struct.unpack("B", songData.read(1))
data = songData.read(lengthDescriptor) data = songData.read(lengthDescriptor)
if blockKey == TITLE: if blockKey == TITLE:
self.title = unicode(data, u'cp1252') self.title = unicode(data, u'cp1252')
elif blockKey == AUTHOR: elif blockKey == AUTHOR:
authors = data.split(" / ") authors = data.split(" / ")
for author in authors: for author in authors:
if author.find(",") !=-1: if author.find(",") !=-1:
authorParts = author.split(", ") authorParts = author.split(", ")
author = authorParts[1] + " " + authorParts[0] author = authorParts[1] + " " + authorParts[0]
self.parse_author(unicode(author, u'cp1252')) self.parse_author(unicode(author, u'cp1252'))
elif blockKey == COPYRIGHT: elif blockKey == COPYRIGHT:
self.add_copyright(unicode(data, u'cp1252')) self.add_copyright(unicode(data, u'cp1252'))
elif blockKey == CCLI_NO: elif blockKey == CCLI_NO:
self.ccli_number = int(data) self.ccli_number = int(data)
elif blockKey == VERSE: elif blockKey == VERSE:
self.add_verse(unicode(data, u'cp1252'), self.add_verse(unicode(data, u'cp1252'),
"V%s" % verseNo) "V%s" % verseNo)
elif blockKey == CHORUS: elif blockKey == CHORUS:
self.add_verse(unicode(data, u'cp1252'), self.add_verse(unicode(data, u'cp1252'),
"C%s" % verseNo) "C%s" % verseNo)
elif blockKey == TOPIC: elif blockKey == TOPIC:
self.topics.append(unicode(data, u'cp1252')) self.topics.append(unicode(data, u'cp1252'))
elif blockKey == COMMENTS: elif blockKey == COMMENTS:
self.comments = unicode(data, u'cp1252') self.comments = unicode(data, u'cp1252')
elif blockKey == VERSE_ORDER: elif blockKey == VERSE_ORDER:
verseTag = self.toOpenLPVerseTag(data, True) verseTag = self.toOpenLPVerseTag(data, True)
if verseTag: if verseTag:
self.sspVerseOrderList.append(unicode(verseTag, self.sspVerseOrderList.append(unicode(verseTag,
u'cp1252')) u'cp1252'))
elif blockKey == SONG_BOOK: elif blockKey == SONG_BOOK:
self.song_book_name = unicode(data, u'cp1252') self.song_book_name = unicode(data, u'cp1252')
elif blockKey == SONG_NUMBER: elif blockKey == SONG_NUMBER:
self.song_number = ord(data) self.song_number = ord(data)
elif blockKey == CUSTOM_VERSE: elif blockKey == CUSTOM_VERSE:
verseTag = self.toOpenLPVerseTag(verseName) verseTag = self.toOpenLPVerseTag(verseName)
self.add_verse(unicode(data, u'cp1252'), verseTag) self.add_verse(unicode(data, u'cp1252'), verseTag)
else: else:
log.debug("Unrecognised blockKey: %s, data: %s" log.debug("Unrecognised blockKey: %s, data: %s"
%(blockKey, data)) % (blockKey, data))
self.verse_order_list = self.sspVerseOrderList self.verse_order_list = self.sspVerseOrderList
songData.close() songData.close()
self.finish() if not self.finish():
self.import_wizard.incrementProgressBar( self.log_error(file)
WizardStrings.ImportingType % file_name)
return True
def toOpenLPVerseTag(self, verseName, ignoreUnique=False): def toOpenLPVerseTag(self, verseName, ignoreUnique=False):
if verseName.find(" ") != -1: if verseName.find(" ") != -1:
@ -185,22 +184,19 @@ class SongShowPlusImport(SongImport):
verseNumber = "1" verseNumber = "1"
verseType = verseType.lower() verseType = verseType.lower()
if verseType == "verse": if verseType == "verse":
verseTag = "V" verseTag = VerseType.Tags[VerseType.Verse]
elif verseType == "chorus": elif verseType == "chorus":
verseTag = "C" verseTag = VerseType.Tags[VerseType.Chorus]
elif verseType == "bridge": elif verseType == "bridge":
verseTag = "B" verseTag = VerseType.Tags[VerseType.Bridge]
elif verseType == "pre-chorus": elif verseType == "pre-chorus":
verseTag = "P" verseTag = VerseType.Tags[VerseType.PreChorus]
elif verseType == "bridge":
verseTag = "B"
else: else:
if not self.otherList.has_key(verseName): if not self.otherList.has_key(verseName):
if ignoreUnique: if ignoreUnique:
return None return None
self.otherCount = self.otherCount + 1 self.otherCount = self.otherCount + 1
self.otherList[verseName] = str(self.otherCount) self.otherList[verseName] = str(self.otherCount)
verseTag = "O" verseTag = VerseType.Tags[VerseType.Other]
verseNumber = self.otherList[verseName] verseNumber = self.otherList[verseName]
verseTag = verseTag + verseNumber return verseTag + verseNumber
return verseTag

View File

@ -40,6 +40,8 @@ class SongStrings(object):
CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.') CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.')
SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular') SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular')
SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural') SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural')
SongIncomplete = translate('OpenLP.Ui','Title and/or verses not found')
SongMaintenance = translate('OpenLP.Ui', 'Song Maintenance') SongMaintenance = translate('OpenLP.Ui', 'Song Maintenance')
Topic = translate('OpenLP.Ui', 'Topic', 'Singular') Topic = translate('OpenLP.Ui', 'Topic', 'Singular')
Topics = translate('OpenLP.Ui', 'Topics', 'Plural') Topics = translate('OpenLP.Ui', 'Topics', 'Plural')
XMLSyntaxError = translate('OpenLP.Ui', 'XML syntax error')

View File

@ -105,11 +105,7 @@ class WowImport(SongImport):
if isinstance(self.import_source, list): if isinstance(self.import_source, list):
self.import_wizard.progressBar.setMaximum(len(self.import_source)) self.import_wizard.progressBar.setMaximum(len(self.import_source))
for file in self.import_source: for file in self.import_source:
author = u''
copyright = u''
file_name = os.path.split(file)[1] file_name = os.path.split(file)[1]
self.import_wizard.incrementProgressBar(
WizardStrings.ImportingType % file_name, 0)
# Get the song title # Get the song title
self.title = file_name.rpartition(u'.')[0] self.title = file_name.rpartition(u'.')[0]
songData = open(file, 'rb') songData = open(file, 'rb')
@ -129,7 +125,7 @@ class WowImport(SongImport):
self.line_text = unicode( self.line_text = unicode(
songData.read(ord(songData.read(1))), u'cp1252') songData.read(ord(songData.read(1))), u'cp1252')
songData.seek(1, os.SEEK_CUR) songData.seek(1, os.SEEK_CUR)
if block_text != u'': if block_text:
block_text += u'\n' block_text += u'\n'
block_text += self.line_text block_text += self.line_text
self.lines_to_read -= 1 self.lines_to_read -= 1
@ -138,22 +134,19 @@ class WowImport(SongImport):
songData.seek(3, os.SEEK_CUR) songData.seek(3, os.SEEK_CUR)
# Blocks are seperated by 2 bytes, skip them, but not if # Blocks are seperated by 2 bytes, skip them, but not if
# this is the last block! # this is the last block!
if (block + 1) < no_of_blocks: if block + 1 < no_of_blocks:
songData.seek(2, os.SEEK_CUR) songData.seek(2, os.SEEK_CUR)
self.add_verse(block_text, block_type) self.add_verse(block_text, block_type)
# Now to extract the author # Now to extract the author
author_length = ord(songData.read(1)) author_length = ord(songData.read(1))
if author_length != 0: if author_length:
author = unicode(songData.read(author_length), u'cp1252') self.parse_author(
unicode(songData.read(author_length), u'cp1252'))
# Finally the copyright # Finally the copyright
copyright_length = ord(songData.read(1)) copyright_length = ord(songData.read(1))
if copyright_length != 0: if copyright_length:
copyright = unicode( self.add_copyright(unicode(
songData.read(copyright_length), u'cp1252') songData.read(copyright_length), u'cp1252'))
self.parse_author(author)
self.add_copyright(copyright)
songData.close() songData.close()
self.finish() if not self.finish():
self.import_wizard.incrementProgressBar( self.log_error(file)
WizardStrings.ImportingType % file_name)
return True

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