diff --git a/LICENSE b/LICENSE index d511905c1..fd94e166f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. - NO WARRANTY + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it diff --git a/README.txt b/README.txt new file mode 100644 index 000000000..0b26d74fc --- /dev/null +++ b/README.txt @@ -0,0 +1,21 @@ +OpenLP 2.0 +========== + +You're probably reading this because you've just downloaded the source code for +OpenLP 2.0. If you are looking for the installer file, please go to the download +page on the web site:: + + http://openlp.org/en/download.html + +If you're looking for how to contribute to OpenLP, then please look at the +contribution page on the web site:: + + http://openlp.org/en/documentation/introduction/contributing.html + +If you've looked at that page, and are wanting to help develop, test or +translate OpenLP, have a look at the OpenLP wiki:: + + http://wiki.openlp.org/ + +Thanks for downloading OpenLP 2.0! + diff --git a/copyright.txt b/copyright.txt index c99a64287..0e405e6e9 100644 --- a/copyright.txt +++ b/copyright.txt @@ -4,11 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/documentation/api/source/core/lib.rst b/documentation/api/source/core/lib.rst index 6ca952d7d..6be95de5f 100644 --- a/documentation/api/source/core/lib.rst +++ b/documentation/api/source/core/lib.rst @@ -6,18 +6,18 @@ Object Library .. automodule:: openlp.core.lib :members: -:mod:`BaseListWithDnD` ----------------------- - -.. autoclass:: openlp.core.lib.baselistwithdnd.BaseListWithDnD - :members: - :mod:`EventReceiver` -------------------- .. autoclass:: openlp.core.lib.eventreceiver.EventReceiver :members: +:mod:`ListWidgetWithDnD` +------------------------ + +.. autoclass:: openlp.core.lib.listwidgetwithdnd.ListWidgetWithDnD + :members: + :mod:`MediaManagerItem` ----------------------- diff --git a/documentation/api/source/core/theme.rst b/documentation/api/source/core/theme.rst index 3dbc7a6ec..3621c6581 100644 --- a/documentation/api/source/core/theme.rst +++ b/documentation/api/source/core/theme.rst @@ -1,8 +1,10 @@ .. _core-theme: -:mod:`theme` Module -=================== +Theme Function Library +====================== .. automodule:: openlp.core.theme :members: +.. autoclass:: openlp.core.theme.theme.Theme + :members: diff --git a/documentation/api/source/openlp.rst b/documentation/api/source/openlp.rst deleted file mode 100644 index 76a1a2098..000000000 --- a/documentation/api/source/openlp.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. _openlp: - -:mod:`openlp` Module -==================== - -.. automodule:: openlp - :members: diff --git a/documentation/api/source/plugins/bibles.rst b/documentation/api/source/plugins/bibles.rst index 67162d414..c89f9c6ae 100644 --- a/documentation/api/source/plugins/bibles.rst +++ b/documentation/api/source/plugins/bibles.rst @@ -18,7 +18,7 @@ Forms .. automodule:: openlp.plugins.bibles.forms :members: -.. autoclass:: openlp.plugins.bibles.forms.importwizardform.ImportWizardForm +.. autoclass:: openlp.plugins.bibles.forms.bibleimportform.BibleImportForm :members: Helper Classes & Functions diff --git a/documentation/api/source/plugins/songs.rst b/documentation/api/source/plugins/songs.rst index 1e86ce020..a9a3a8219 100644 --- a/documentation/api/source/plugins/songs.rst +++ b/documentation/api/source/plugins/songs.rst @@ -54,9 +54,6 @@ Helper Classes & Functions .. automodule:: openlp.plugins.songs.lib.mediaitem :members: -.. autoclass:: openlp.plugins.songs.lib.mediaitem.SongListView - :members: - .. automodule:: openlp.plugins.songs.lib.songimport :members: diff --git a/documentation/manual/source/conf.py b/documentation/manual/source/conf.py index 517fc2f44..f0d918c11 100644 --- a/documentation/manual/source/conf.py +++ b/documentation/manual/source/conf.py @@ -48,7 +48,7 @@ copyright = u'2004-2010 Raoul Snyman' # The short X.Y version. version = '2.0' # The full version, including alpha/beta/rc tags. -release = '1.9.3' +release = '1.9.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -92,22 +92,24 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. +#html_theme = 'openlp_qthelp' html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -html_theme_options = { - 'sidebarbgcolor': '#3a60a9', - 'relbarbgcolor': '#203b6f', - 'footerbgcolor': '#26437c', - 'headtextcolor': '#203b6f', - 'linkcolor': '#26437c', - 'sidebarlinkcolor': '#ceceff' -} +if html_theme == 'default': + html_theme_options = { + 'sidebarbgcolor': '#3a60a9', + 'relbarbgcolor': '#203b6f', + 'footerbgcolor': '#26437c', + 'headtextcolor': '#203b6f', + 'linkcolor': '#26437c', + 'sidebarlinkcolor': '#ceceff' + } # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +html_theme_path = [u'../themes'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". diff --git a/documentation/manual/source/dualmonitors.rst b/documentation/manual/source/dualmonitors.rst index 7e5fdc19b..ee4bc90a2 100644 --- a/documentation/manual/source/dualmonitors.rst +++ b/documentation/manual/source/dualmonitors.rst @@ -149,15 +149,15 @@ Or, as root:: root@linux: # nividia-settings If you do not want to write the changes to your ``xorg.conf`` file simply run -the nVidia Settings program (``nvidia-settings``) from your desktop's menu, -usually in an administration or system menu, or from the terminal as a normal -user run:: +the nVidia Settings program (:command:`nvidia-settings`) from your desktop's +menu, usually in an administration or system menu, or from the terminal as a +normal user run:: user@linux:~ $ nvidia-settings -Once you have opened nVidia Settings, click on -:guilabel:`X Server Display Configuration`. Then select the monitor you are -wanting to use as your second monitor and click :guilabel:`Configure`. +Once you have opened nVidia Settings, click on :guilabel:`X Server Display +Configuration`. Then select the monitor you are wanting to use as your second +monitor and click :guilabel:`Configure`. .. image:: pics/nvlinux1.png diff --git a/documentation/manual/source/index.rst b/documentation/manual/source/index.rst index 5786af1ae..378cfe2a0 100644 --- a/documentation/manual/source/index.rst +++ b/documentation/manual/source/index.rst @@ -17,10 +17,3 @@ Contents: mediamanager songs -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/documentation/manual/themes/openlp_qthelp/layout.html b/documentation/manual/themes/openlp_qthelp/layout.html new file mode 100644 index 000000000..d16116773 --- /dev/null +++ b/documentation/manual/themes/openlp_qthelp/layout.html @@ -0,0 +1,68 @@ +{# + openlp_qthelp/layout.html + ~~~~~~~~~~~~~~~~~ + + Sphinx layout template for the openlp_qthelp theme. + + :copyright: Copyright 2004-2010 Raoul Snyman. + :license: GPL +#} +{% extends "basic/layout.html" %} +{% set script_files = script_files + ['_static/theme_extras.js'] %} +{% set css_files = css_files + ['_static/print.css'] %} + +{# do not display relbars #} +{% block relbar1 %}{% endblock %} +{% block relbar2 %}{% endblock %} + +{% macro nav() %} +

+ {%- block openlp_qthelprel1 %} + {%- endblock %} + {%- if prev %} + «  {{ prev.title }} +   ::   + {%- endif %} + {{ _('Contents') }} + {%- if next %} +   ::   + {{ next.title }}  » + {%- endif %} + {%- block openlp_qthelprel2 %} + {%- endblock %} +

+{% endmacro %} + +{% block content %} + +
+ {{ nav() }} +
+
+ {#{%- if display_toc %} +
+

Table Of Contents

+ {{ toc }} +
+ {%- endif %}#} + {% block body %}{% endblock %} +
+
+ {{ nav() }} +
+{% endblock %} diff --git a/documentation/manual/themes/openlp_qthelp/static/alert_info_32.png b/documentation/manual/themes/openlp_qthelp/static/alert_info_32.png new file mode 100644 index 000000000..05b4fe898 Binary files /dev/null and b/documentation/manual/themes/openlp_qthelp/static/alert_info_32.png differ diff --git a/documentation/manual/themes/openlp_qthelp/static/alert_warning_32.png b/documentation/manual/themes/openlp_qthelp/static/alert_warning_32.png new file mode 100644 index 000000000..f13611cde Binary files /dev/null and b/documentation/manual/themes/openlp_qthelp/static/alert_warning_32.png differ diff --git a/documentation/manual/themes/openlp_qthelp/static/bg-page.png b/documentation/manual/themes/openlp_qthelp/static/bg-page.png new file mode 100644 index 000000000..c6f3bc477 Binary files /dev/null and b/documentation/manual/themes/openlp_qthelp/static/bg-page.png differ diff --git a/documentation/manual/themes/openlp_qthelp/static/bullet_orange.png b/documentation/manual/themes/openlp_qthelp/static/bullet_orange.png new file mode 100644 index 000000000..ad5d02f34 Binary files /dev/null and b/documentation/manual/themes/openlp_qthelp/static/bullet_orange.png differ diff --git a/documentation/manual/themes/openlp_qthelp/static/openlp_qthelp.css_t b/documentation/manual/themes/openlp_qthelp/static/openlp_qthelp.css_t new file mode 100644 index 000000000..918ed661b --- /dev/null +++ b/documentation/manual/themes/openlp_qthelp/static/openlp_qthelp.css_t @@ -0,0 +1,372 @@ +/* + * openlp_qthelp.css_t + * ~~~~~~~~~~~ + * + * Sphinx stylesheet -- openlp_qthelp theme. + * + * Adapted from http://openlp_qthelp-os.org/docs/Haiku-doc.css. + * Original copyright message: + * + * Copyright 2008-2009, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Francois Revol + * Stephan Assmus + * Braden Ewing + * Humdinger + * + * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +html { + margin: 0px; + padding: 0px; + background-color: #fff; + background-image: none; +} + +body { + line-height: 1.5; + margin: auto; + padding: 0px; + font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; + min-width: 59em; + max-width: 70em; + color: {{ theme_textcolor }}; +} + +div.footer { + padding: 8px; + font-size: 11px; + text-align: center; + letter-spacing: 0.5px; +} + +/* link colors and text decoration */ + +a:link { + font-weight: bold; + text-decoration: none; + color: {{ theme_linkcolor }}; +} + +a:visited { + font-weight: bold; + text-decoration: none; + color: {{ theme_visitedlinkcolor }}; +} + +a:hover, a:active { + text-decoration: underline; + color: {{ theme_hoverlinkcolor }}; +} + +/* Some headers act as anchors, don't give them a hover effect */ + +h1 a:hover, a:active { + text-decoration: none; + color: {{ theme_headingcolor }}; +} + +h2 a:hover, a:active { + text-decoration: none; + color: {{ theme_headingcolor }}; +} + +h3 a:hover, a:active { + text-decoration: none; + color: {{ theme_headingcolor }}; +} + +h4 a:hover, a:active { + text-decoration: none; + color: {{ theme_headingcolor }}; +} + +a.headerlink { + color: #a7ce38; + padding-left: 5px; +} + +a.headerlink:hover { + color: #a7ce38; +} + +/* basic text elements */ + +div.content { + margin-top: 20px; + margin-left: 40px; + margin-right: 40px; + margin-bottom: 50px; + font-size: 0.9em; +} + +/* heading and navigation */ + +div.header { + position: relative; + left: 0px; + top: 0px; + height: 85px; + /* background: #eeeeee; */ + padding: 0 40px; +} +div.header h1 { + font-size: 1.6em; + font-weight: normal; + letter-spacing: 1px; + color: {{ theme_headingcolor }}; + border: 0; + margin: 0; + padding-top: 15px; +} +div.header h1 a { + font-weight: normal; + color: {{ theme_headingcolor }}; +} +div.header h2 { + font-size: 1.3em; + font-weight: normal; + letter-spacing: 1px; + text-transform: uppercase; + color: #aaa; + border: 0; + margin-top: -3px; + padding: 0; +} + +div.header img.rightlogo { + float: right; +} + + +div.title { + font-size: 1.3em; + font-weight: bold; + color: {{ theme_headingcolor }}; + border-bottom: dotted thin #e0e0e0; + margin-bottom: 25px; +} +div.topnav { + /* background: #e0e0e0; */ +} +div.topnav p { + margin-top: 0; + margin-left: 40px; + margin-right: 40px; + margin-bottom: 0px; + text-align: right; + font-size: 0.8em; +} +div.bottomnav { + background: #eeeeee; +} +div.bottomnav p { + margin-right: 40px; + text-align: right; + font-size: 0.8em; +} + +a.uplink { + font-weight: normal; +} + + +/* contents box */ + +table.index { + margin: 0px 0px 30px 30px; + padding: 1px; + border-width: 1px; + border-style: dotted; + border-color: #e0e0e0; +} +table.index tr.heading { + background-color: #e0e0e0; + text-align: center; + font-weight: bold; + font-size: 1.1em; +} +table.index tr.index { + background-color: #eeeeee; +} +table.index td { + padding: 5px 20px; +} + +table.index a:link, table.index a:visited { + font-weight: normal; + text-decoration: none; + color: {{ theme_linkcolor }}; +} +table.index a:hover, table.index a:active { + text-decoration: underline; + color: {{ theme_hoverlinkcolor }}; +} + + +/* Haiku User Guide styles and layout */ + +/* Rounded corner boxes */ +/* Common declarations */ +div.admonition { + -webkit-border-radius: 10px; + -khtml-border-radius: 10px; + -moz-border-radius: 10px; + border-radius: 10px; + border-style: dotted; + border-width: thin; + border-color: #dcdcdc; + padding: 10px 15px 10px 15px; + margin-bottom: 15px; + margin-top: 15px; +} +div.note { + padding: 10px 15px 10px 80px; + background: #e4ffde url(alert_info_32.png) 15px 15px no-repeat; + min-height: 42px; +} +div.warning { + padding: 10px 15px 10px 80px; + background: #fffbc6 url(alert_warning_32.png) 15px 15px no-repeat; + min-height: 42px; +} +div.seealso { + background: #e4ffde; +} + +/* More layout and styles */ +h1 { + font-size: 1.3em; + font-weight: bold; + color: {{ theme_headingcolor }}; + border-bottom: dotted thin #e0e0e0; + margin-top: 30px; +} + +h2 { + font-size: 1.2em; + font-weight: normal; + color: {{ theme_headingcolor }}; + border-bottom: dotted thin #e0e0e0; + margin-top: 30px; +} + +h3 { + font-size: 1.1em; + font-weight: normal; + color: {{ theme_headingcolor }}; + margin-top: 30px; +} + +h4 { + font-size: 1.0em; + font-weight: normal; + color: {{ theme_headingcolor }}; + margin-top: 30px; +} + +p { + text-align: justify; +} + +p.last { + margin-bottom: 0; +} + +ol { + padding-left: 20px; +} + +ul { + padding-left: 5px; + margin-top: 3px; +} + +li { + line-height: 1.3; +} + +div.content ul > li { + -moz-background-clip:border; + -moz-background-inline-policy:continuous; + -moz-background-origin:padding; + background: transparent url(bullet_orange.png) no-repeat scroll left 0.45em; + list-style-image: none; + list-style-type: none; + padding: 0 0 0 1.666em; + margin-bottom: 3px; +} + +td { + vertical-align: top; +} + +tt { + background-color: #e2e2e2; + font-size: 1.0em; + font-family: monospace; +} + +pre { + border-color: #0c3762; + border-style: dotted; + border-width: thin; + margin: 0 0 12px 0; + padding: 0.8em; + background-color: #f0f0f0; +} + +hr { + border-top: 1px solid #ccc; + border-bottom: 0; + border-right: 0; + border-left: 0; + margin-bottom: 10px; + margin-top: 20px; +} + +/* printer only pretty stuff */ +@media print { + .noprint { + display: none; + } + /* for acronyms we want their definitions inlined at print time */ + acronym[title]:after { + font-size: small; + content: " (" attr(title) ")"; + font-style: italic; + } + /* and not have mozilla dotted underline */ + acronym { + border: none; + } + div.topnav, div.bottomnav, div.header, table.index { + display: none; + } + div.content { + margin: 0px; + padding: 0px; + } + html { + background: #FFF; + } +} + +.viewcode-back { + font-family: "DejaVu Sans", Arial, Helvetica, sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; + margin: -1px -12px; + padding: 0 12px; +} diff --git a/documentation/manual/themes/openlp_qthelp/theme.conf b/documentation/manual/themes/openlp_qthelp/theme.conf new file mode 100644 index 000000000..0d44b0faa --- /dev/null +++ b/documentation/manual/themes/openlp_qthelp/theme.conf @@ -0,0 +1,12 @@ +[theme] +inherit = basic +stylesheet = openlp_qthelp.css +pygments_style = autumn + +[options] +full_logo = false +textcolor = #333333 +headingcolor = #203b6f +linkcolor = #26437c +visitedlinkcolor = #26437c +hoverlinkcolor = #26437c diff --git a/openlp.pyw b/openlp.pyw index 100c3336f..85ba81fba 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -7,9 +7,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -188,7 +188,8 @@ class OpenLP(QtGui.QApplication): u'primary': (self.desktop().primaryScreen() == screen)}) log.info(u'Screen %d found with resolution %s', screen, size) # start the main app window - self.mainWindow = MainWindow(screens, app_version) + self.appClipboard = self.clipboard() + self.mainWindow = MainWindow(screens, app_version, self.appClipboard) self.mainWindow.show() if show_splash: # now kill the splashscreen diff --git a/openlp/__init__.py b/openlp/__init__.py index b88547df6..9c22aab8b 100644 --- a/openlp/__init__.py +++ b/openlp/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### """ The :mod:`openlp` module contains all the project produced OpenLP functionality -""" \ No newline at end of file +""" diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 17db85184..00d8b78c0 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,4 +28,4 @@ The :mod:`core` module provides all core application functions All the core functions of the OpenLP application including the GUI, settings, logging and a plugin framework are contained within the openlp.core module. -""" \ No newline at end of file +""" diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 33280f83b..dc60a5a65 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -106,8 +106,8 @@ def translate(context, text, comment=None, def get_text_file_string(text_file): """ - Open a file and return its content as unicode string. If the supplied file - name is not a file then the function returns False. If there is an error + Open a file and return its content as unicode string. If the supplied file + name is not a file then the function returns False. If there is an error loading the file or the content can't be decoded then the function will return None. @@ -239,7 +239,8 @@ def resize_image(image, width, height, background=QtCore.Qt.black): Resize an image to fit on the current screen. ``image`` - The image to resize. + The image to resize. It has to be either a ``QImage`` instance or the + path to the image. ``width`` The new image width. @@ -319,8 +320,7 @@ def check_directory_exists(dir): if not os.path.exists(dir): os.makedirs(dir) -from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \ - BackgroundType, HorizontalType, VerticalType +from listwidgetwithdnd import ListWidgetWithDnD from displaytags import DisplayTags from spelltextedit import SpellTextEdit from eventreceiver import Receiver @@ -339,4 +339,3 @@ from dockwidget import OpenLPDockWidget from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from baselistwithdnd import BaseListWithDnD diff --git a/openlp/core/lib/db.py b/openlp/core/lib/db.py index 3171730ea..c92f992c8 100644 --- a/openlp/core/lib/db.py +++ b/openlp/core/lib/db.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -65,7 +65,7 @@ def delete_database(plugin_name, db_file_name=None): The name of the plugin to remove the database for ``db_file_name`` - The database file name. Defaults to None resulting in the + The database file name. Defaults to None resulting in the plugin_name being used. """ db_file_path = None @@ -86,10 +86,11 @@ class BaseModel(object): """ Creates an instance of a class and populates it, returning the instance """ - me = cls() + instance = cls() for key in kwargs: - me.__setattr__(key, kwargs[key]) - return me + instance.__setattr__(key, kwargs[key]) + return instance + class Manager(object): """ @@ -107,7 +108,7 @@ class Manager(object): The init_schema function for this database ``db_file_name`` - The file name to use for this database. Defaults to None resulting + The file name to use for this database. Defaults to None resulting in the plugin_name being used. """ settings = QtCore.QSettings() @@ -211,11 +212,11 @@ class Manager(object): The type of objects to return ``filter_clause`` - The filter governing selection of objects to return. Defaults to + The filter governing selection of objects to return. Defaults to None. ``order_by_ref`` - Any parameters to order the returned objects by. Defaults to None. + Any parameters to order the returned objects by. Defaults to None. """ query = self.session.query(object_class) if filter_clause is not None: @@ -232,7 +233,7 @@ class Manager(object): The type of objects to return. ``filter_clause`` - The filter governing selection of objects to return. Defaults to + The filter governing selection of objects to return. Defaults to None. """ query = self.session.query(object_class) diff --git a/openlp/core/lib/displaytags.py b/openlp/core/lib/displaytags.py index dd7276a7d..fc36bc090 100644 --- a/openlp/core/lib/displaytags.py +++ b/openlp/core/lib/displaytags.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -60,8 +60,8 @@ class DisplayTags(object): DisplayTags.html_expands.append(tag) @staticmethod - def remove_html_tag(id): + def remove_html_tag(tag_id): """ - Removes amd individual html_expands list. + Removes an individual html_expands tag. """ - DisplayTags.html_expands.pop(id) + DisplayTags.html_expands.pop(tag_id) diff --git a/openlp/core/lib/dockwidget.py b/openlp/core/lib/dockwidget.py index 32d6ce765..efc0a3066 100644 --- a/openlp/core/lib/dockwidget.py +++ b/openlp/core/lib/dockwidget.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index 6fa8e624a..78b0c6324 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index ea830855c..4faf47ddc 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,7 +28,8 @@ import logging from PyQt4 import QtWebKit -from openlp.core.lib import BackgroundType, BackgroundGradientType +from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, \ + VerticalType, HorizontalType log = logging.getLogger(__name__) @@ -530,18 +531,8 @@ def build_lyrics_format_css(theme, width, height): Height of the lyrics block """ - if theme.display_horizontal_align == 2: - align = u'center' - elif theme.display_horizontal_align == 1: - align = u'right' - else: - align = u'left' - if theme.display_vertical_align == 2: - valign = u'bottom' - elif theme.display_vertical_align == 1: - valign = u'middle' - else: - valign = u'top' + align = HorizontalType.Names[theme.display_horizontal_align] + valign = VerticalType.Names[theme.display_vertical_align] if theme.font_main_outline: left_margin = int(theme.font_main_outline_size) * 2 else: @@ -634,13 +625,7 @@ def build_alert_css(alertTab, width): """ if not alertTab: return u'' - align = u'' - if alertTab.location == 2: - align = u'bottom' - elif alertTab.location == 1: - align = u'middle' - else: - align = u'top' + align = VerticalType.Names[alertTab.location] alert = style % (width, align, alertTab.font_face, alertTab.font_size, alertTab.font_color, alertTab.bg_color) return alert diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index 02d7010be..31b41dc0f 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -61,14 +61,15 @@ class Image(object): image = None image_bytes = None + class ImageManager(QtCore.QObject): """ Image Manager handles the conversion and sizing of images. - """ log.info(u'Image Manager loaded') def __init__(self): + QtCore.QObject.__init__(self) self._cache = {} self._thread_running = False self._cache_dirty = False @@ -85,8 +86,7 @@ class ImageManager(QtCore.QObject): for key in self._cache.keys(): image = self._cache[key] image.dirty = True - image.image = resize_image(image.path, - self.width, self.height) + image.image = resize_image(image.path, self.width, self.height) self._cache_dirty = True # only one thread please if not self._thread_running: @@ -128,8 +128,7 @@ class ImageManager(QtCore.QObject): image = Image() image.name = name image.path = path - image.image = resize_image(path, - self.width, self.height) + image.image = resize_image(path, self.width, self.height) self._cache[name] = image else: log.debug(u'Image in cache %s:%s' % (name, path)) diff --git a/openlp/core/lib/baselistwithdnd.py b/openlp/core/lib/listwidgetwithdnd.py similarity index 82% rename from openlp/core/lib/baselistwithdnd.py rename to openlp/core/lib/listwidgetwithdnd.py index 86535f6e7..5cd8cf9e2 100644 --- a/openlp/core/lib/baselistwithdnd.py +++ b/openlp/core/lib/listwidgetwithdnd.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,17 +28,17 @@ Extend QListWidget to handle drag and drop functionality """ from PyQt4 import QtCore, QtGui -class BaseListWithDnD(QtGui.QListWidget): +class ListWidgetWithDnD(QtGui.QListWidget): """ Provide a list widget to store objects and handle drag and drop events """ - def __init__(self, parent=None): + def __init__(self, parent=None, name=u''): """ Initialise the list widget """ QtGui.QListWidget.__init__(self, parent) - # this must be set by the class which is inheriting - assert(self.PluginName) + self.mimeDataText = name + assert(self.mimeDataText) def mouseMoveEvent(self, event): """ @@ -47,9 +47,10 @@ class BaseListWithDnD(QtGui.QListWidget): just tell it what plugin to call """ if event.buttons() != QtCore.Qt.LeftButton: + event.ignore() return drag = QtGui.QDrag(self) mimeData = QtCore.QMimeData() drag.setMimeData(mimeData) - mimeData.setText(self.PluginName) - drag.start(QtCore.Qt.CopyAction) \ No newline at end of file + mimeData.setText(self.mimeDataText) + drag.start(QtCore.Qt.CopyAction) diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 683459825..c44b89534 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,7 +33,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import context_menu_action, context_menu_separator, \ SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, \ - translate, Receiver + translate, Receiver, ListWidgetWithDnD +from openlp.core.lib.ui import UiStrings log = logging.getLogger(__name__) @@ -65,19 +66,15 @@ class MediaManagerItem(QtGui.QWidget): When creating a descendant class from this class for your plugin, the following member variables should be set. - ``self.OnNewPrompt`` + ``self.onNewPrompt`` + Defaults to *'Select Image(s)'*. - ``self.OnNewFileMasks`` + ``self.onNewFileMasks`` Defaults to *'Images (*.jpg *jpeg *.gif *.png *.bmp)'*. This assumes that the new action is to load a file. If not, you need to override the ``OnNew`` method. - ``self.ListViewWithDnD_class`` - This must be a **class**, not an object, descended from - ``openlp.core.lib.BaseListWithDnD`` that is not used in any - other part of OpenLP. - ``self.PreviewFunction`` This must be a method which returns a QImage to represent the item (usually a preview). No scaling is required, that is @@ -158,7 +155,7 @@ class MediaManagerItem(QtGui.QWidget): ``icon`` The icon of the button. This can be an instance of QIcon, or a - string cotaining either the absolute path to the image, or an + string containing either the absolute path to the image, or an internal resource path starting with ':/'. ``slot`` @@ -202,68 +199,50 @@ class MediaManagerItem(QtGui.QWidget): """ Create buttons for the media item toolbar """ + toolbar_actions = [] ## Import Button ## if self.hasImportIcon: - import_string = self.plugin.getString(StringContent.Import) - self.addToolbarButton( - import_string[u'title'], - import_string[u'tooltip'], - u':/general/general_import.png', self.onImportClick) + toolbar_actions.append([StringContent.Import, + u':/general/general_import.png', self.onImportClick]) ## Load Button ## if self.hasFileIcon: - load_string = self.plugin.getString(StringContent.Load) - self.addToolbarButton( - load_string[u'title'], - load_string[u'tooltip'], - u':/general/general_open.png', self.onFileClick) + toolbar_actions.append([StringContent.Load, + u':/general/general_open.png', self.onFileClick]) ## New Button ## if self.hasNewIcon: - new_string = self.plugin.getString(StringContent.New) - self.addToolbarButton( - new_string[u'title'], - new_string[u'tooltip'], - u':/general/general_new.png', self.onNewClick) + toolbar_actions.append([StringContent.New, + u':/general/general_new.png', self.onNewClick]) ## Edit Button ## if self.hasEditIcon: - edit_string = self.plugin.getString(StringContent.Edit) - self.addToolbarButton( - edit_string[u'title'], - edit_string[u'tooltip'], - u':/general/general_edit.png', self.onEditClick) + toolbar_actions.append([StringContent.Edit, + u':/general/general_edit.png', self.onEditClick]) ## Delete Button ## if self.hasDeleteIcon: - delete_string = self.plugin.getString(StringContent.Delete) - self.addToolbarButton( - delete_string[u'title'], - delete_string[u'tooltip'], - u':/general/general_delete.png', self.onDeleteClick) + toolbar_actions.append([StringContent.Delete, + u':/general/general_delete.png', self.onDeleteClick]) ## Separator Line ## self.addToolbarSeparator() ## Preview ## - preview_string = self.plugin.getString(StringContent.Preview) - self.addToolbarButton( - preview_string[u'title'], - preview_string[u'tooltip'], - u':/general/general_preview.png', self.onPreviewClick) + toolbar_actions.append([StringContent.Preview, + u':/general/general_preview.png', self.onPreviewClick]) ## Live Button ## - live_string = self.plugin.getString(StringContent.Live) - self.addToolbarButton( - live_string[u'title'], - live_string[u'tooltip'], - u':/general/general_live.png', self.onLiveClick) + toolbar_actions.append([StringContent.Live, + u':/general/general_live.png', self.onLiveClick]) ## Add to service Button ## - service_string = self.plugin.getString(StringContent.Service) - self.addToolbarButton( - service_string[u'title'], - service_string[u'tooltip'], - u':/general/general_add.png', self.onAddClick) + toolbar_actions.append([StringContent.Service, + u':/general/general_add.png', self.onAddClick]) + for action in toolbar_actions: + self.addToolbarButton( + self.plugin.getString(action[0])[u'title'], + self.plugin.getString(action[0])[u'tooltip'], + action[1], action[2]) def addListViewToToolBar(self): """ Creates the main widget for listing items the media item is tracking """ # Add the List widget - self.listView = self.ListViewWithDnD_class(self) + self.listView = ListWidgetWithDnD(self, self.plugin.name) self.listView.uniformItemSizes = True self.listView.setSpacing(1) self.listView.setSelectionMode( @@ -275,7 +254,6 @@ class MediaManagerItem(QtGui.QWidget): self.pageLayout.addWidget(self.listView) # define and add the context menu self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - name_string = self.plugin.getString(StringContent.Name) if self.hasEditIcon: self.listView.addAction( context_menu_action( @@ -340,9 +318,9 @@ class MediaManagerItem(QtGui.QWidget): Add a file to the list widget to make it available for showing """ files = QtGui.QFileDialog.getOpenFileNames( - self, self.OnNewPrompt, + self, self.onNewPrompt, SettingsManager.get_last_dir(self.settingsSection), - self.OnNewFileMasks) + self.onNewFileMasks) log.info(u'New files(s) %s', unicode(files)) if files: Receiver.send_message(u'cursor_busy') @@ -439,8 +417,7 @@ class MediaManagerItem(QtGui.QWidget): item to the preview slide controller. """ if not self.listView.selectedIndexes() and not self.remoteTriggered: - QtGui.QMessageBox.information(self, - translate('OpenLP.MediaManagerItem', 'No Items Selected'), + QtGui.QMessageBox.information(self, UiStrings.NISp, translate('OpenLP.MediaManagerItem', 'You must select one or more items to preview.')) else: @@ -456,8 +433,7 @@ class MediaManagerItem(QtGui.QWidget): item to the live slide controller. """ if not self.listView.selectedIndexes(): - QtGui.QMessageBox.information(self, - translate('OpenLP.MediaManagerItem', 'No Items Selected'), + QtGui.QMessageBox.information(self, UiStrings.NISp, translate('OpenLP.MediaManagerItem', 'You must select one or more items to send live.')) else: @@ -472,8 +448,7 @@ class MediaManagerItem(QtGui.QWidget): Add a selected item to the current service """ if not self.listView.selectedIndexes() and not self.remoteTriggered: - QtGui.QMessageBox.information(self, - translate('OpenLP.MediaManagerItem', 'No Items Selected'), + QtGui.QMessageBox.information(self, UiStrings.NISp, translate('OpenLP.MediaManagerItem', 'You must select one or more items.')) else: @@ -499,17 +474,14 @@ class MediaManagerItem(QtGui.QWidget): Add a selected item to an existing item in the current service. """ if not self.listView.selectedIndexes() and not self.remoteTriggered: - QtGui.QMessageBox.information(self, - translate('OpenLP.MediaManagerItem', 'No items selected'), + QtGui.QMessageBox.information(self, UiStrings.NISp, translate('OpenLP.MediaManagerItem', - 'You must select one or more items')) + 'You must select one or more items.')) else: log.debug(u'%s Add requested', self.plugin.name) serviceItem = self.parent.serviceManager.getServiceItem() if not serviceItem: - QtGui.QMessageBox.information(self, - translate('OpenLP.MediaManagerItem', - 'No Service Item Selected'), + QtGui.QMessageBox.information(self, UiStrings.NISs, translate('OpenLP.MediaManagerItem', 'You must select an existing service item to add to.')) elif self.plugin.name.lower() == serviceItem.name.lower(): diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index fb31006b5..c1ff30281 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -31,6 +31,7 @@ import logging from PyQt4 import QtCore from openlp.core.lib import Receiver +from openlp.core.lib.ui import UiStrings log = logging.getLogger(__name__) @@ -44,6 +45,9 @@ class PluginStatus(object): class StringContent(object): + """ + Provide standard strings for objects to use. + """ Name = u'name' Import = u'import' Load = u'load' @@ -110,7 +114,8 @@ class Plugin(QtCore.QObject): """ log.info(u'loaded') - def __init__(self, name, version=None, pluginHelpers=None): + def __init__(self, name, version=None, pluginHelpers=None, + mediaItemClass=None, settingsTabClass=None): """ This is the constructor for the plugin object. This provides an easy way for descendent plugins to populate common data. This method *must* @@ -128,15 +133,24 @@ class Plugin(QtCore.QObject): ``pluginHelpers`` Defaults to *None*. A list of helper objects. + + ``mediaItemClass`` + The class name of the plugin's media item. + + ``settingsTabClass`` + The class name of the plugin's settings tab. """ QtCore.QObject.__init__(self) self.name = name self.textStrings = {} self.setPluginTextStrings() + self.nameStrings = self.textStrings[StringContent.Name] if version: self.version = version self.settingsSection = self.name.lower() self.icon = None + self.mediaItemClass = mediaItemClass + self.settingsTabClass = settingsTabClass self.weight = 0 self.status = PluginStatus.Inactive # Set up logging @@ -195,7 +209,9 @@ class Plugin(QtCore.QObject): Construct a MediaManagerItem object with all the buttons and things you need, and return it for integration into openlp.org. """ - pass + if self.mediaItemClass: + return self.mediaItemClass(self, self, self.icon) + return None def addImportMenuItem(self, importMenu): """ @@ -226,9 +242,13 @@ class Plugin(QtCore.QObject): def getSettingsTab(self): """ - Create a tab for the settings window. + Create a tab for the settings window to display the configurable + options for this plugin to the user. """ - pass + if self.settingsTabClass: + return self.settingsTabClass(self.name, + self.getString(StringContent.VisibleName)[u'title']) + return None def addToMenu(self, menubar): """ @@ -316,8 +336,39 @@ class Plugin(QtCore.QObject): """ return self.textStrings[name] - def setPluginTextStrings(self): + def setPluginUiTextStrings(self, tooltips): """ Called to define all translatable texts of the plugin """ - pass + ## Load Action ## + self.__setNameTextString(StringContent.Load, + UiStrings.Load, tooltips[u'load']) + ## Import Action ## + self.__setNameTextString(StringContent.Import, + UiStrings.Import, tooltips[u'import']) + ## New Action ## + self.__setNameTextString(StringContent.New, + UiStrings.Add, tooltips[u'new']) + ## Edit Action ## + self.__setNameTextString(StringContent.Edit, + UiStrings.Edit, tooltips[u'edit']) + ## Delete Action ## + self.__setNameTextString(StringContent.Delete, + UiStrings.Delete, tooltips[u'delete']) + ## Preview Action ## + self.__setNameTextString(StringContent.Preview, + UiStrings.Preview, tooltips[u'preview']) + ## Send Live Action ## + self.__setNameTextString(StringContent.Live, + UiStrings.Live, tooltips[u'live']) + ## Add to Service Action ## + self.__setNameTextString(StringContent.Service, + UiStrings.Service, tooltips[u'service']) + + def __setNameTextString(self, name, title, tooltip): + """ + Utility method for creating a plugin's textStrings. This method makes + use of the singular name of the plugin object so must only be called + after this has been set. + """ + self.textStrings[name] = {u'title': title, u'tooltip': tooltip} diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index 8081cbf71..d2b05ab7c 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -221,4 +221,4 @@ class PluginManager(object): for plugin in self.plugins: if plugin.isActive(): plugin.finalise() - log.info(u'Finalisation Complete for %s ' % plugin.name) \ No newline at end of file + log.info(u'Finalisation Complete for %s ' % plugin.name) diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index fe118b76b..4df87a4df 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -144,4 +144,4 @@ class Renderer(object): html_text = html_text[:len(html_text)-4] formatted.append(html_text) log.debug(u'format_slide - End') - return formatted \ No newline at end of file + return formatted diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index 5896ca4e6..eaf628a34 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,11 +28,21 @@ import logging from PyQt4 import QtCore -from openlp.core.lib import Renderer, ThemeLevel, ServiceItem, ImageManager +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 @@ -68,7 +78,6 @@ class RenderManager(object): self.theme_level = u'' self.override_background = None self.theme_data = None - self.alertTab = None self.force_page = False def update_display(self): @@ -174,14 +183,13 @@ class RenderManager(object): main_rect = None footer_rect = None if not theme.font_main_override: - main_rect = QtCore.QRect(10, 0, - self.width - 20, self.footer_start) + 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) + 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, @@ -203,28 +211,17 @@ class RenderManager(object): self.force_page = force_page # set the default image size for previews self.calculate_default(self.screens.preview[u'size']) - 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' - # make big page for theme edit dialog to get line count - if self.force_page: - verse = verse + verse + verse - else: - self.image_manager.del_image(theme_data.theme_name) - footer = [] - footer.append(u'Arky Arky (Unknown)' ) - footer.append(u'Public Domain') - footer.append(u'CCLI 123456') # build a service item to generate preview serviceItem = ServiceItem() serviceItem.theme = theme_data - serviceItem.add_from_text(u'', verse, footer) + 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.raw_footer = FOOTER serviceItem.render(True) if not self.force_page: self.display.buildHtml(serviceItem) @@ -259,6 +256,6 @@ class RenderManager(object): 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 ) + self.width, self.height, self.screen_ratio) # 90% is start of footer - self.footer_start = int(self.height * 0.90) \ No newline at end of file + self.footer_start = int(self.height * 0.90) diff --git a/openlp/core/lib/searchedit.py b/openlp/core/lib/searchedit.py index 5e12dcefd..d2424d00e 100644 --- a/openlp/core/lib/searchedit.py +++ b/openlp/core/lib/searchedit.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index c74b89144..de4f2fd81 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,11 +28,13 @@ The :mod:`serviceitem` provides the service item functionality including the type and capability of an item. """ +import datetime import logging import os import uuid from openlp.core.lib import build_icon, clean_tags, expand_tags +from openlp.core.lib.ui import UiStrings log = logging.getLogger(__name__) @@ -60,6 +62,7 @@ class ItemCapabilities(object): AddIfNewItem = 9 ProvidesOwnDisplay = 10 AllowsDetailedTitleDisplay = 11 + AllowsVarableStartTime = 12 class ServiceItem(object): @@ -105,6 +108,8 @@ class ServiceItem(object): self.data_string = u'' self.edit_id = None self.xml_version = None + self.start_time = 0 + self.media_length = 0 self._new_item() def _new_item(self): @@ -257,7 +262,9 @@ class ServiceItem(object): u'capabilities': self.capabilities, u'search': self.search_string, u'data': self.data_string, - u'xml_version': self.xml_version + u'xml_version': self.xml_version, + u'start_time': self.start_time, + u'media_length': self.media_length } service_data = [] if self.service_item_type == ServiceItemType.Text: @@ -301,6 +308,10 @@ class ServiceItem(object): self.data_string = header[u'data'] if u'xml_version' in header: self.xml_version = header[u'xml_version'] + if u'start_time' in header: + self.start_time = header[u'start_time'] + if u'media_length' in header: + self.media_length = header[u'media_length'] if self.service_item_type == ServiceItemType.Text: for slide in serviceitem[u'serviceitem'][u'data']: self._raw_frames.append(slide) @@ -312,7 +323,7 @@ class ServiceItem(object): for text_image in serviceitem[u'serviceitem'][u'data']: filename = os.path.join(path, text_image[u'title']) self.add_from_command( - path, text_image[u'title'], text_image[u'image'] ) + path, text_image[u'title'], text_image[u'image']) self._new_item() def get_display_title(self): @@ -420,3 +431,24 @@ class ServiceItem(object): return self._raw_frames[row][u'path'] except IndexError: return u'' + + def get_media_time(self): + """ + Returns the start and finish time for a media item + """ + start = None + end = None + if self.start_time != 0: + start = UiStrings.StartTimeCode % \ + unicode(datetime.timedelta(seconds=self.start_time)) + if self.media_length != 0: + end = UiStrings.LengthTime % \ + unicode(datetime.timedelta(seconds=self.media_length)) + if not start and not end: + return None + elif start and not end: + return start + elif not start and end: + return end + else: + return u'%s : %s' % (start, end) diff --git a/openlp/core/lib/settingsmanager.py b/openlp/core/lib/settingsmanager.py index 89d56cea2..d09497540 100644 --- a/openlp/core/lib/settingsmanager.py +++ b/openlp/core/lib/settingsmanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -64,7 +64,7 @@ class SettingsManager(object): Read the last directory used for plugin. ``section`` - The section of code calling the method. This is used in the + The section of code calling the method. This is used in the settings key. ``num`` @@ -84,7 +84,7 @@ class SettingsManager(object): Save the last directory used for plugin. ``section`` - The section of code calling the method. This is used in the + The section of code calling the method. This is used in the settings key. ``directory`` @@ -160,11 +160,11 @@ class SettingsManager(object): Get a list of files from the data files path. ``section`` - Defaults to *None*. The section of code getting the files - used + Defaults to *None*. The section of code getting the files - used to load from a section's data subdirectory. ``extension`` - Defaults to *None*. The extension to search for. + Defaults to *None*. The extension to search for. """ path = AppLocation.get_data_path() if section: @@ -178,4 +178,4 @@ class SettingsManager(object): if extension == os.path.splitext(filename)[1]] else: # no filtering required - return files \ No newline at end of file + return files diff --git a/openlp/core/lib/settingstab.py b/openlp/core/lib/settingstab.py index 297185127..4f3748c8d 100644 --- a/openlp/core/lib/settingstab.py +++ b/openlp/core/lib/settingstab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 44180a25c..493781ccc 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index d119f19ff..ef26ca842 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,7 +33,8 @@ import logging from xml.dom.minidom import Document from lxml import etree, objectify -from openlp.core.lib import str_to_bool +from openlp.core.lib import str_to_bool, translate +from openlp.core.lib.ui import UiStrings log = logging.getLogger(__name__) @@ -90,6 +91,7 @@ class ThemeLevel(object): Service = 2 Song = 3 + class BackgroundType(object): """ Type enumeration for backgrounds. @@ -122,6 +124,7 @@ class BackgroundType(object): elif type_string == u'image': return BackgroundType.Image + class BackgroundGradientType(object): """ Type enumeration for background gradients. @@ -164,13 +167,21 @@ class BackgroundGradientType(object): elif type_string == u'leftBottom': return BackgroundGradientType.LeftBottom + class HorizontalType(object): """ Type enumeration for horizontal alignment. """ Left = 0 - Center = 1 - Right = 2 + Right = 1 + Center = 2 + + Names = [u'left', u'right', u'center'] + TranslatedNames = [ + translate('OpenLP.ThemeWizard', 'Left'), + translate('OpenLP.ThemeWizard', 'Right'), + translate('OpenLP.ThemeWizard', 'Center')] + class VerticalType(object): """ @@ -180,6 +191,10 @@ class VerticalType(object): Middle = 1 Bottom = 2 + Names = [u'top', u'middle', u'bottom'] + TranslatedNames = [UiStrings.Top, UiStrings.Middle, UiStrings.Bottom] + + BOOLEAN_LIST = [u'bold', u'italics', u'override', u'outline', u'shadow', u'slide_transition'] @@ -187,6 +202,7 @@ INTEGER_LIST = [u'size', u'line_adjustment', u'x', u'height', u'y', u'width', u'shadow_size', u'outline_size', u'horizontal_align', u'vertical_align', u'wrap_style'] + class ThemeXML(object): """ A class to encapsulate the Theme XML. @@ -583,8 +599,7 @@ class ThemeXML(object): self.background_end_color, self.background_direction) else: - filename = \ - os.path.split(self.background_filename)[1] + filename = os.path.split(self.background_filename)[1] self.add_background_image(filename) self.add_font(self.font_main_name, self.font_main_color, diff --git a/openlp/core/lib/toolbar.py b/openlp/core/lib/toolbar.py index b1aa3d96f..37fb67d52 100644 --- a/openlp/core/lib/toolbar.py +++ b/openlp/core/lib/toolbar.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -61,7 +61,7 @@ class OpenLPToolbar(QtGui.QToolBar): ``icon`` The icon of the button. This can be an instance of QIcon, or a - string cotaining either the absolute path to the image, or an + string containing either the absolute path to the image, or an internal resource path starting with ':/'. ``tooltip`` diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index 4a346b3e1..eae4f60ca 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -34,6 +34,66 @@ from openlp.core.lib import build_icon, Receiver, translate log = logging.getLogger(__name__) +class UiStrings(object): + """ + Provide standard strings for objects to use. + """ + # These strings should need a good reason to be retranslated elsewhere. + # Should some/more/less of these have an & attached? + About = translate('OpenLP.Ui', 'About') + Add = translate('OpenLP.Ui', '&Add') + Advanced = translate('OpenLP.Ui', 'Advanced') + AllFiles = translate('OpenLP.Ui', 'All Files') + Bottom = translate('OpenLP.Ui', 'Bottom') + Browse = translate('OpenLP.Ui', 'Browse...') + Cancel = translate('OpenLP.Ui', 'Cancel') + CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:') + CreateService = translate('OpenLP.Ui', 'Create a new service.') + Delete = translate('OpenLP.Ui', '&Delete') + Edit = translate('OpenLP.Ui', '&Edit') + EmptyField = translate('OpenLP.Ui', 'Empty Field') + Error = translate('OpenLP.Ui', 'Error') + Export = translate('OpenLP.Ui', 'Export') + FontSizePtUnit = translate('OpenLP.Ui', 'pt', + 'Abbreviated font pointsize unit') + Image = translate('OpenLP.Ui', 'Image') + Import = translate('OpenLP.Ui', 'Import') + LengthTime = unicode(translate('OpenLP.Ui', 'Length %s')) + Live = translate('OpenLP.Ui', 'Live') + LiveBGError = translate('OpenLP.Ui', 'Live Background Error') + LivePanel = translate('OpenLP.Ui', 'Live Panel') + Load = translate('OpenLP.Ui', 'Load') + Middle = translate('OpenLP.Ui', 'Middle') + New = translate('OpenLP.Ui', 'New') + NewService = translate('OpenLP.Ui', 'New Service') + NewTheme = translate('OpenLP.Ui', 'New Theme') + NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular') + NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural') + NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular') + NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural') + OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x') + OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0') + OpenService = translate('OpenLP.Ui', 'Open Service') + Preview = translate('OpenLP.Ui', 'Preview') + PreviewPanel = translate('OpenLP.Ui', 'Preview Panel') + PrintServiceOrder = translate('OpenLP.Ui', 'Print Service Order') + ReplaceBG = translate('OpenLP.Ui', 'Replace Background') + ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background') + ResetBG = translate('OpenLP.Ui', 'Reset Background') + ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background') + S = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds') + SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview') + Search = translate('OpenLP.Ui', 'Search') + SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.') + SelectEdit = translate('OpenLP.Ui', 'You must select an item to edit.') + SaveService = translate('OpenLP.Ui', 'Save Service') + Service = translate('OpenLP.Ui', 'Service') + StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s')) + Theme = translate('OpenLP.Ui', 'Theme', 'Singular') + Themes = translate('OpenLP.Ui', 'Themes', 'Plural') + Top = translate('OpenLP.Ui', 'Top') + Version = translate('OpenLP.Ui', 'Version') + def add_welcome_page(parent, image): """ Generate an opening welcome page for a wizard using a provided image. @@ -61,18 +121,25 @@ def add_welcome_page(parent, image): parent.welcomeLayout.addStretch() parent.addPage(parent.welcomePage) -def create_save_cancel_button_box(parent): +def create_accept_reject_button_box(parent, okay=False): """ - Creates a standard dialog button box with save and cancel buttons. The - button box is connected to the parent's ``accept()`` and ``reject()`` + Creates a standard dialog button box with two buttons. The buttons default + to save and cancel but the ``okay`` parameter can be used to make the + buttons okay and cancel instead. + The button box is connected to the parent's ``accept()`` and ``reject()`` methods to handle the default ``accepted()`` and ``rejected()`` signals. ``parent`` - The parent object. This should be a ``QWidget`` descendant. + The parent object. This should be a ``QWidget`` descendant. + + ``okay`` + If true creates an okay/cancel combination instead of save/cancel. """ button_box = QtGui.QDialogButtonBox(parent) - button_box.setStandardButtons( - QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel) + accept_button = QtGui.QDialogButtonBox.Save + if okay: + accept_button = QtGui.QDialogButtonBox.Ok + button_box.setStandardButtons(accept_button | QtGui.QDialogButtonBox.Cancel) button_box.setObjectName(u'%sButtonBox' % parent) QtCore.QObject.connect(button_box, QtCore.SIGNAL(u'accepted()'), parent.accept) @@ -98,13 +165,12 @@ def critical_error_message_box(title=None, message=None, parent=None, ``question`` Should this message box question the user. """ - error = translate('OpenLP.Ui', 'Error') if question: - return QtGui.QMessageBox.critical(parent, error, message, + return QtGui.QMessageBox.critical(parent, UiStrings.Error, message, QtGui.QMessageBox.StandardButtons( QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)) data = {u'message': message} - data[u'title'] = title if title else error + data[u'title'] = title if title else UiStrings.Error return Receiver.send_message(u'openlp_error_message', data) def media_item_combo_box(parent, name): @@ -119,22 +185,22 @@ def media_item_combo_box(parent, name): def create_delete_push_button(parent, icon=None): """ - Creates a standard push button with a delete label and optional icon. The + Creates a standard push button with a delete label and optional icon. The button is connected to the parent's ``onDeleteButtonClicked()`` method to handle the ``clicked()`` signal. ``parent`` - The parent object. This should be a ``QWidget`` descendant. + The parent object. This should be a ``QWidget`` descendant. ``icon`` - An icon to display on the button. This can be either a ``QIcon``, a + An icon to display on the button. This can be either a ``QIcon``, a resource path or a file name. """ delete_button = QtGui.QPushButton(parent) delete_button.setObjectName(u'deleteButton') delete_icon = icon if icon else u':/general/general_delete.png' delete_button.setIcon(build_icon(delete_icon)) - delete_button.setText(translate('OpenLP.Ui', '&Delete')) + delete_button.setText(UiStrings.Delete) delete_button.setToolTip( translate('OpenLP.Ui', 'Delete the selected item.')) QtCore.QObject.connect(delete_button, @@ -144,12 +210,12 @@ def create_delete_push_button(parent, icon=None): def create_up_down_push_button_set(parent): """ Creates a standard set of two push buttons, one for up and the other for - down, for use with lists. The buttons use arrow icons and no text and are + down, for use with lists. The buttons use arrow icons and no text and are connected to the parent's ``onUpButtonClicked()`` and ``onDownButtonClicked()`` to handle their respective ``clicked()`` signals. ``parent`` - The parent object. This should be a ``QWidget`` descendant. + The parent object. This should be a ``QWidget`` descendant. """ up_button = QtGui.QPushButton(parent) up_button.setIcon(build_icon(u':/services/service_up.png')) @@ -219,3 +285,28 @@ def add_widget_completer(cache, widget): completer = QtGui.QCompleter(cache) completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive) widget.setCompleter(completer) + +def create_valign_combo(form, parent, layout): + """ + Creates a standard label and combo box for asking users to select a + vertical alignment. + + ``form`` + The UI screen that the label and combo will appear on. + + ``parent`` + The parent object. This should be a ``QWidget`` descendant. + + ``layout`` + A layout object to add the label and combo widgets to. + """ + verticalLabel = QtGui.QLabel(parent) + verticalLabel.setObjectName(u'VerticalLabel') + verticalLabel.setText(translate('OpenLP.Ui', '&Vertical Align:')) + form.verticalComboBox = QtGui.QComboBox(parent) + form.verticalComboBox.setObjectName(u'VerticalComboBox') + form.verticalComboBox.addItem(UiStrings.Top) + form.verticalComboBox.addItem(UiStrings.Middle) + form.verticalComboBox.addItem(UiStrings.Bottom) + verticalLabel.setBuddy(form.verticalComboBox) + layout.addRow(verticalLabel, form.verticalComboBox) diff --git a/openlp/core/theme/__init__.py b/openlp/core/theme/__init__.py index 350b550a2..52f7120b1 100644 --- a/openlp/core/theme/__init__.py +++ b/openlp/core/theme/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -24,4 +24,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from openlp.core.theme.theme import Theme \ No newline at end of file +from openlp.core.theme.theme import Theme diff --git a/openlp/core/theme/theme.py b/openlp/core/theme/theme.py index e506fc2c2..bb6b25a9e 100644 --- a/openlp/core/theme/theme.py +++ b/openlp/core/theme/theme.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,11 +33,14 @@ processing version 1 themes in OpenLP version 2. from xml.etree.ElementTree import ElementTree, XML from PyQt4 import QtGui -DELPHI_COLORS = {u'clRed': 0xFF0000, - u'clBlue': 0x0000FF, - u'clYellow': 0xFFFF00, - u'clBlack': 0x000000, - u'clWhite': 0xFFFFFF} +DELPHI_COLORS = { + u'clAqua': 0x00FFFF, u'clBlack': 0x000000, u'clBlue': 0x0000FF, + u'clFuchsia': 0xFF00FF, u'clGray': 0x808080, u'clGreen': 0x008000, + u'clLime': 0x00FF00, u'clMaroon': 0x800000, u'clNavy': 0x000080, + u'clOlive': 0x808000, u'clPurple': 0x800080, u'clRed': 0xFF0000, + u'clSilver': 0xC0C0C0, u'clTeal': 0x008080, u'clWhite': 0xFFFFFF, + u'clYellow': 0xFFFF00 +} BLANK_STYLE_XML = \ ''' @@ -68,38 +71,45 @@ class Theme(object): Theme name ``BackgroundMode`` - The behaviour of the background. Valid modes are: - - 0 - Transparent - - 1 - Opaque + The behaviour of the background. Valid modes are: + + * ``0`` - Transparent + * ``1`` - Opaque ``BackgroundType`` - The content of the background. Valid types are: - - 0 - solid color - - 1 - gradient color - - 2 - image + The content of the background. Valid types are: + + * ``0`` - solid color + * ``1`` - gradient color + * ``2`` - image ``BackgroundParameter1`` - Extra information about the background. The contents of this attribute + Extra information about the background. The contents of this attribute depend on the BackgroundType: - - image: image filename - - gradient: start color - - solid: color + + * ``image`` - image filename + * ``gradient`` - start color + * ``solid`` - color ``BackgroundParameter2`` - Extra information about the background. The contents of this attribute + Extra information about the background. The contents of this attribute depend on the BackgroundType: - - image: border color - - gradient: end color - - solid: N/A + + * ``image`` - border color + * ``gradient`` - end color + * ``solid`` - N/A ``BackgroundParameter3`` - Extra information about the background. The contents of this attribute + Extra information about the background. The contents of this attribute depend on the BackgroundType: - - image: N/A - - gradient: The direction of the gradient. Valid entries are: - - 0 -> vertical - - 1 -> horizontal - - solid: N/A + + * ``image`` - N/A + * ``gradient`` - The direction of the gradient. Valid entries are: + + * ``0`` - vertical + * ``1`` - horizontal + + * ``solid`` - N/A ``FontName`` Name of the font to use for the main font. @@ -115,36 +125,41 @@ class Theme(object): ``Shadow`` The shadow type to apply to the main font. - - 0 - no shadow - - non-zero - use shadow + + * ``0`` - no shadow + * non-zero - use shadow ``ShadowColor`` Color for the shadow ``Outline`` The outline to apply to the main font - - 0 - no outline - - non-zero - use outline + + * ``0`` - no outline + * non-zero - use outline ``OutlineColor`` Color for the outline (or None if Outline is 0) ``HorizontalAlign`` - The horizontal alignment to apply to text. Valid alignments are: - - 0 - left align - - 1 - right align - - 2 - centre align + The horizontal alignment to apply to text. Valid alignments are: + + * ``0`` - left align + * ``1`` - right align + * ``2`` - centre align ``VerticalAlign`` The vertical alignment to apply to the text. Valid alignments are: - - 0 - top align - - 1 - bottom align - - 2 - centre align + + * ``0`` - top align + * ``1`` - bottom align + * ``2`` - centre align ``WrapStyle`` - The wrap style to apply to the text. Valid styles are: - - 0 - normal - - 1 - lyrics + The wrap style to apply to the text. Valid styles are: + + * ``0`` - normal + * ``1`` - lyrics """ def __init__(self, xml): """ @@ -184,7 +199,6 @@ class Theme(object): if element.tag != u'Theme': element_text = element.text val = 0 - # easy! if element_text is None: val = element_text # strings need special handling to sort the colours out diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index eb0e89775..158f7f0cd 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,7 +28,7 @@ The :mod:`ui` module provides the core user interface for OpenLP """ from PyQt4 import QtGui -from openlp.core.lib import translate, Receiver +from openlp.core.lib import translate class HideMode(object): """ @@ -53,6 +53,7 @@ class HideMode(object): from themeform import ThemeForm from filerenameform import FileRenameForm +from starttimeform import StartTimeForm from maindisplay import MainDisplay from servicenoteform import ServiceNoteForm from serviceitemeditform import ServiceItemEditForm @@ -62,10 +63,10 @@ from splashscreen import SplashScreen from generaltab import GeneralTab from themestab import ThemesTab from advancedtab import AdvancedTab -from displaytagtab import DisplayTagTab from aboutform import AboutForm from pluginform import PluginForm from settingsform import SettingsForm +from displaytagform import DisplayTagForm from shortcutlistform import ShortcutListForm from mediadockmanager import MediaDockManager from servicemanager import ServiceManager diff --git a/openlp/core/ui/aboutdialog.py b/openlp/core/ui/aboutdialog.py index 597d3fb24..5ba5783ea 100644 --- a/openlp/core/ui/aboutdialog.py +++ b/openlp/core/ui/aboutdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,6 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate +from openlp.core.lib.ui import UiStrings class Ui_AboutDialog(object): def setupUi(self, aboutDialog): @@ -86,8 +87,7 @@ class Ui_AboutDialog(object): QtCore.QMetaObject.connectSlotsByName(aboutDialog) def retranslateUi(self, aboutDialog): - aboutDialog.setWindowTitle(translate('OpenLP.AboutForm', - 'About OpenLP')) + aboutDialog.setWindowTitle(u'%s OpenLP' % UiStrings.About) self.aboutTextEdit.setPlainText(translate('OpenLP.AboutForm', 'OpenLP - Open Source Lyrics ' 'Projection\n' @@ -105,8 +105,7 @@ class Ui_AboutDialog(object): 'consider contributing by using the button below.' )) self.aboutNotebook.setTabText( - self.aboutNotebook.indexOf(self.aboutTab), - translate('OpenLP.AboutForm', 'About')) + self.aboutNotebook.indexOf(self.aboutTab), UiStrings.About) self.creditsTextEdit.setPlainText(translate('OpenLP.AboutForm', 'Project Lead\n' ' Raoul "superfly" Snyman\n' @@ -164,9 +163,10 @@ class Ui_AboutDialog(object): self.licenseTextEdit.setPlainText(translate('OpenLP.AboutForm', 'Copyright \xa9 2004-2011 Raoul Snyman\n' 'Portions copyright \xa9 2004-2011 ' - 'Tim Bentley, Jonathan Corwin, Michael Gorven, Scott Guerrieri, ' - 'Christian Richter, Maikel Stuivenberg, Martin Thompson, Jon ' - 'Tibble, Carsten Tinggaard\n' + 'Tim Bentley, Jonathan Corwin, Michael Gorven, Scott Guerrieri,\n' + 'Meinert Jordan, Andreas Preikschat, Christian Richter, Philip\n' + 'Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Carstenn' + 'Tinggaard, Frode Woldsund\n' '\n' 'This program is free software; you can redistribute it and/or ' 'modify it under the terms of the GNU General Public License as ' diff --git a/openlp/core/ui/aboutform.py b/openlp/core/ui/aboutform.py index f3fcc18a8..a6550b23c 100644 --- a/openlp/core/ui/aboutform.py +++ b/openlp/core/ui/aboutform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -61,4 +61,4 @@ class AboutForm(QtGui.QDialog, Ui_AboutDialog): import webbrowser url = u'http://www.openlp.org/en/documentation/introduction/' \ + u'contributing.html' - webbrowser.open_new(url) \ No newline at end of file + webbrowser.open_new(url) diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index f68131894..a8e8b294e 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,7 +28,9 @@ The :mod:`advancedtab` provides an advanced settings facility. """ from PyQt4 import QtCore, QtGui -from openlp.core.lib import SettingsTab, translate +from openlp.core.lib import SettingsTab, translate, build_icon +from openlp.core.lib.ui import UiStrings +from openlp.core.utils import get_images_filter class AdvancedTab(SettingsTab): """ @@ -40,6 +42,8 @@ class AdvancedTab(SettingsTab): Initialise the settings tab """ SettingsTab.__init__(self, u'Advanced') + self.default_image = u':/graphics/openlp-splash-screen.png' + self.default_color = u'#ffffff' def setupUi(self): """ @@ -80,49 +84,44 @@ class AdvancedTab(SettingsTab): self.hideMouseCheckBox.setObjectName(u'hideMouseCheckBox') self.hideMouseLayout.addWidget(self.hideMouseCheckBox) self.leftLayout.addWidget(self.hideMouseGroupBox) - self.serviceOrderGroupBox = QtGui.QGroupBox(self.leftColumn) - self.serviceOrderGroupBox.setObjectName(u'serviceOrderGroupBox') - self.serviceOrderLayout = QtGui.QVBoxLayout(self.serviceOrderGroupBox) - self.serviceOrderLayout.setObjectName(u'serviceOrderLayout') - self.detailedServicePrintCheckBox = QtGui.QCheckBox( - self.serviceOrderGroupBox) - self.detailedServicePrintCheckBox.setObjectName( - u'detailedServicePrintCheckBox') - self.serviceOrderLayout.addWidget(self.detailedServicePrintCheckBox) - self.leftLayout.addWidget(self.serviceOrderGroupBox) -# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftColumn) -# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox') -# self.sharedDirLayout = QtGui.QFormLayout(self.sharedDirGroupBox) -# self.sharedCheckBox = QtGui.QCheckBox(self.sharedDirGroupBox) -# self.sharedCheckBox.setObjectName(u'sharedCheckBox') -# self.sharedDirLayout.addRow(self.sharedCheckBox) -# self.sharedLabel = QtGui.QLabel(self.sharedDirGroupBox) -# self.sharedLabel.setObjectName(u'sharedLabel') -# self.sharedSubLayout = QtGui.QHBoxLayout() -# self.sharedSubLayout.setObjectName(u'sharedSubLayout') -# self.sharedLineEdit = QtGui.QLineEdit(self.sharedDirGroupBox) -# self.sharedLineEdit.setObjectName(u'sharedLineEdit') -# self.sharedSubLayout.addWidget(self.sharedLineEdit) -# self.sharedPushButton = QtGui.QPushButton(self.sharedDirGroupBox) -# self.sharedPushButton.setObjectName(u'sharedPushButton') -# self.sharedSubLayout.addWidget(self.sharedPushButton) -# self.sharedDirLayout.addRow(self.sharedLabel, self.sharedSubLayout) -# self.leftLayout.addWidget(self.sharedDirGroupBox) self.leftLayout.addStretch() -# self.databaseGroupBox = QtGui.QGroupBox(self.rightColumn) -# self.databaseGroupBox.setObjectName(u'databaseGroupBox') -# self.databaseGroupBox.setEnabled(False) -# self.databaseLayout = QtGui.QVBoxLayout(self.databaseGroupBox) -# self.rightLayout.addWidget(self.databaseGroupBox) + self.defaultImageGroupBox = QtGui.QGroupBox(self.rightColumn) + self.defaultImageGroupBox.setObjectName(u'defaultImageGroupBox') + self.defaultImageLayout = QtGui.QFormLayout(self.defaultImageGroupBox) + self.defaultImageLayout.setObjectName(u'defaultImageLayout') + self.defaultColorLabel = QtGui.QLabel(self.defaultImageGroupBox) + self.defaultColorLabel.setObjectName(u'defaultColorLabel') + self.defaultColorButton = QtGui.QPushButton(self.defaultImageGroupBox) + self.defaultColorButton.setObjectName(u'defaultColorButton') + self.defaultImageLayout.addRow(self.defaultColorLabel, + self.defaultColorButton) + self.defaultFileLabel = QtGui.QLabel(self.defaultImageGroupBox) + self.defaultFileLabel.setObjectName(u'defaultFileLabel') + self.defaultFileEdit = QtGui.QLineEdit(self.defaultImageGroupBox) + self.defaultFileEdit.setObjectName(u'defaultFileEdit') + self.defaultBrowseButton = QtGui.QToolButton(self.defaultImageGroupBox) + self.defaultBrowseButton.setObjectName(u'defaultBrowseButton') + self.defaultBrowseButton.setIcon( + build_icon(u':/general/general_open.png')) + self.defaultFileLayout = QtGui.QHBoxLayout() + self.defaultFileLayout.setObjectName(u'defaultFileLayout') + self.defaultFileLayout.addWidget(self.defaultFileEdit) + self.defaultFileLayout.addWidget(self.defaultBrowseButton) + self.defaultImageLayout.addRow(self.defaultFileLabel, + self.defaultFileLayout) + self.rightLayout.addWidget(self.defaultImageGroupBox) self.rightLayout.addStretch() -# QtCore.QObject.connect(self.sharedCheckBox, -# QtCore.SIGNAL(u'stateChanged(int)'), self.onSharedCheckBoxChanged) + + QtCore.QObject.connect(self.defaultColorButton, + QtCore.SIGNAL(u'pressed()'), self.onDefaultColorButtonPressed) + QtCore.QObject.connect(self.defaultBrowseButton, + QtCore.SIGNAL(u'pressed()'), self.onDefaultBrowseButtonPressed) def retranslateUi(self): """ Setup the interface translation strings. """ - self.tabTitleVisible = translate('OpenLP.AdvancedTab', 'Advanced') + self.tabTitleVisible = UiStrings.Advanced self.uiGroupBox.setTitle(translate('OpenLP.AdvancedTab', 'UI Settings')) self.recentLabel.setText( translate('OpenLP.AdvancedTab', @@ -138,19 +137,13 @@ class AdvancedTab(SettingsTab): self.hideMouseGroupBox.setTitle(translate('OpenLP.AdvancedTab', 'Mouse Cursor')) self.hideMouseCheckBox.setText(translate('OpenLP.AdvancedTab', - 'Hide the mouse cursor when moved over the display window')) - self.serviceOrderGroupBox.setTitle(translate('OpenLP.AdvancedTab', - 'Service Order Print')) - self.detailedServicePrintCheckBox.setText( - translate('OpenLP.AdvancedTab', - 'Print slide texts and service item notes as well')) -# self.sharedDirGroupBox.setTitle( -# translate('AdvancedTab', 'Central Data Store')) -# self.sharedCheckBox.setText( -# translate('AdvancedTab', 'Enable a shared data location')) -# self.sharedLabel.setText(translate('AdvancedTab', 'Store location:')) -# self.sharedPushButton.setText(translate('AdvancedTab', 'Browse...')) -# self.databaseGroupBox.setTitle(translate('AdvancedTab', 'Databases')) + 'Hide mouse cursor when over display window')) + self.defaultImageGroupBox.setTitle(translate('OpenLP.AdvancedTab', + 'Default Image')) + self.defaultColorLabel.setText(translate('OpenLP.AdvancedTab', + 'Background color:')) + self.defaultFileLabel.setText(translate('OpenLP.AdvancedTab', + 'Image file:')) def load(self): """ @@ -179,9 +172,14 @@ class AdvancedTab(SettingsTab): QtCore.QVariant(True)).toBool()) self.hideMouseCheckBox.setChecked( settings.value(u'hide mouse', QtCore.QVariant(False)).toBool()) - self.detailedServicePrintCheckBox.setChecked(settings.value( - u'detailed service print', QtCore.QVariant(False)).toBool()) + self.default_color = settings.value(u'default color', + QtCore.QVariant(u'#ffffff')).toString() + self.defaultFileEdit.setText(settings.value(u'default image', + QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\ + .toString()) settings.endGroup() + self.defaultColorButton.setStyleSheet( + u'background-color: %s' % self.default_color) def save(self): """ @@ -201,14 +199,24 @@ class AdvancedTab(SettingsTab): QtCore.QVariant(self.enableAutoCloseCheckBox.isChecked())) settings.setValue(u'hide mouse', QtCore.QVariant(self.hideMouseCheckBox.isChecked())) - settings.setValue(u'detailed service print', - QtCore.QVariant(self.detailedServicePrintCheckBox.isChecked())) + settings.setValue(u'default color', self.default_color) + settings.setValue(u'default image', self.defaultFileEdit.text()) settings.endGroup() -# def onSharedCheckBoxChanged(self, checked): -# """ -# Enables the widgets to allow a shared data location -# """ -# self.sharedLabel.setEnabled(checked) -# self.sharedTextEdit.setEnabled(checked) -# self.sharedPushButton.setEnabled(checked) + def onDefaultColorButtonPressed(self): + new_color = QtGui.QColorDialog.getColor( + QtGui.QColor(self.default_color), self) + if new_color.isValid(): + self.default_color = new_color.name() + self.defaultColorButton.setStyleSheet( + u'background-color: %s' % self.default_color) + + def onDefaultBrowseButtonPressed(self): + file_filters = u'%s;;%s (*.*) (*)' % (get_images_filter(), + UiStrings.AllFiles) + filename = QtGui.QFileDialog.getOpenFileName(self, + translate('OpenLP.AdvancedTab', 'Open File'), '', + file_filters) + if filename: + self.defaultFileEdit.setText(filename) + self.defaultFileEdit.setFocus() diff --git a/openlp/core/ui/displaytagdialog.py b/openlp/core/ui/displaytagdialog.py new file mode 100644 index 000000000..2b6441e16 --- /dev/null +++ b/openlp/core/ui/displaytagdialog.py @@ -0,0 +1,154 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import translate +from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box + +class Ui_DisplayTagDialog(object): + + def setupUi(self, displayTagDialog): + displayTagDialog.setObjectName(u'displayTagDialog') + displayTagDialog.resize(725, 548) + self.widget = QtGui.QWidget(displayTagDialog) + self.widget.setGeometry(QtCore.QRect(10, 10, 701, 521)) + self.widget.setObjectName(u'widget') + self.listdataGridLayout = QtGui.QGridLayout(self.widget) + self.listdataGridLayout.setMargin(0) + self.listdataGridLayout.setObjectName(u'listdataGridLayout') + self.tagTableWidget = QtGui.QTableWidget(self.widget) + self.tagTableWidget.setHorizontalScrollBarPolicy( + QtCore.Qt.ScrollBarAlwaysOff) + self.tagTableWidget.setEditTriggers( + QtGui.QAbstractItemView.NoEditTriggers) + self.tagTableWidget.setAlternatingRowColors(True) + self.tagTableWidget.setSelectionMode( + QtGui.QAbstractItemView.SingleSelection) + self.tagTableWidget.setSelectionBehavior( + QtGui.QAbstractItemView.SelectRows) + self.tagTableWidget.setCornerButtonEnabled(False) + self.tagTableWidget.setObjectName(u'tagTableWidget') + self.tagTableWidget.setColumnCount(4) + self.tagTableWidget.setRowCount(0) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(0, item) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(1, item) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(2, item) + item = QtGui.QTableWidgetItem() + self.tagTableWidget.setHorizontalHeaderItem(3, item) + self.listdataGridLayout.addWidget(self.tagTableWidget, 0, 0, 1, 1) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName(u'horizontalLayout') + spacerItem = QtGui.QSpacerItem(40, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.defaultPushButton = QtGui.QPushButton(self.widget) + self.defaultPushButton.setObjectName(u'defaultPushButton') + self.horizontalLayout.addWidget(self.defaultPushButton) + self.deletePushButton = QtGui.QPushButton(self.widget) + self.deletePushButton.setObjectName(u'deletePushButton') + self.horizontalLayout.addWidget(self.deletePushButton) + self.listdataGridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 1) + self.editGroupBox = QtGui.QGroupBox(self.widget) + self.editGroupBox.setObjectName(u'editGroupBox') + self.dataGridLayout = QtGui.QGridLayout(self.editGroupBox) + self.dataGridLayout.setObjectName(u'dataGridLayout') + self.descriptionLabel = QtGui.QLabel(self.editGroupBox) + self.descriptionLabel.setAlignment(QtCore.Qt.AlignCenter) + self.descriptionLabel.setObjectName(u'descriptionLabel') + self.dataGridLayout.addWidget(self.descriptionLabel, 0, 0, 1, 1) + self.descriptionLineEdit = QtGui.QLineEdit(self.editGroupBox) + self.descriptionLineEdit.setObjectName(u'descriptionLineEdit') + self.dataGridLayout.addWidget(self.descriptionLineEdit, 0, 1, 2, 1) + self.newPushButton = QtGui.QPushButton(self.editGroupBox) + self.newPushButton.setObjectName(u'newPushButton') + self.dataGridLayout.addWidget(self.newPushButton, 0, 2, 2, 1) + self.tagLabel = QtGui.QLabel(self.editGroupBox) + self.tagLabel.setAlignment(QtCore.Qt.AlignCenter) + self.tagLabel.setObjectName(u'tagLabel') + self.dataGridLayout.addWidget(self.tagLabel, 2, 0, 1, 1) + self.tagLineEdit = QtGui.QLineEdit(self.editGroupBox) + self.tagLineEdit.setMaximumSize(QtCore.QSize(50, 16777215)) + self.tagLineEdit.setMaxLength(5) + self.tagLineEdit.setObjectName(u'tagLineEdit') + self.dataGridLayout.addWidget(self.tagLineEdit, 2, 1, 1, 1) + self.startTagLabel = QtGui.QLabel(self.editGroupBox) + self.startTagLabel.setAlignment(QtCore.Qt.AlignCenter) + self.startTagLabel.setObjectName(u'startTagLabel') + self.dataGridLayout.addWidget(self.startTagLabel, 3, 0, 1, 1) + self.startTagLineEdit = QtGui.QLineEdit(self.editGroupBox) + self.startTagLineEdit.setObjectName(u'startTagLineEdit') + self.dataGridLayout.addWidget(self.startTagLineEdit, 3, 1, 1, 1) + self.endTagLabel = QtGui.QLabel(self.editGroupBox) + self.endTagLabel.setAlignment(QtCore.Qt.AlignCenter) + self.endTagLabel.setObjectName(u'endTagLabel') + self.dataGridLayout.addWidget(self.endTagLabel, 4, 0, 1, 1) + self.endTagLineEdit = QtGui.QLineEdit(self.editGroupBox) + self.endTagLineEdit.setObjectName(u'endTagLineEdit') + self.dataGridLayout.addWidget(self.endTagLineEdit, 4, 1, 1, 1) + self.updatePushButton = QtGui.QPushButton(self.editGroupBox) + self.updatePushButton.setObjectName(u'updatePushButton') + self.dataGridLayout.addWidget(self.updatePushButton, 4, 2, 1, 1) + self.listdataGridLayout.addWidget(self.editGroupBox, 2, 0, 1, 1) + self.buttonBox = create_accept_reject_button_box(displayTagDialog) + self.listdataGridLayout.addWidget(self.buttonBox, 3, 0, 1, 1) + + self.retranslateUi(displayTagDialog) + QtCore.QMetaObject.connectSlotsByName(displayTagDialog) + + def retranslateUi(self, displayTagDialog): + displayTagDialog.setWindowTitle(translate('OpenLP.displayTagDialog', + 'Configure Display Tags')) + self.editGroupBox.setTitle( + translate('OpenLP.DisplayTagDialog', 'Edit Selection')) + self.updatePushButton.setText( + translate('OpenLP.DisplayTagDialog', 'Update')) + self.descriptionLabel.setText( + translate('OpenLP.DisplayTagDialog', 'Description')) + self.tagLabel.setText(translate('OpenLP.DisplayTagDialog', 'Tag')) + self.startTagLabel.setText( + translate('OpenLP.DisplayTagDialog', 'Start tag')) + self.endTagLabel.setText( + translate('OpenLP.DisplayTagDialog', 'End tag')) + self.deletePushButton.setText(UiStrings.Delete) + self.defaultPushButton.setText( + translate('OpenLP.DisplayTagDialog', 'Default')) + self.newPushButton.setText(UiStrings.New) + self.tagTableWidget.horizontalHeaderItem(0).setText( + translate('OpenLP.DisplayTagDialog', 'Description')) + self.tagTableWidget.horizontalHeaderItem(1).setText( + translate('OpenLP.DisplayTagDialog', 'Tag id')) + self.tagTableWidget.horizontalHeaderItem(2).setText( + translate('OpenLP.DisplayTagDialog', 'Start Html')) + self.tagTableWidget.horizontalHeaderItem(3).setText( + translate('OpenLP.DisplayTagDialog', 'End Html')) + self.tagTableWidget.setColumnWidth(0, 120) + self.tagTableWidget.setColumnWidth(1, 40) + self.tagTableWidget.setColumnWidth(2, 240) + self.tagTableWidget.setColumnWidth(3, 240) diff --git a/openlp/core/ui/displaytagtab.py b/openlp/core/ui/displaytagform.py similarity index 55% rename from openlp/core/ui/displaytagtab.py rename to openlp/core/ui/displaytagform.py index 983bc17a8..e29fe3384 100644 --- a/openlp/core/ui/displaytagtab.py +++ b/openlp/core/ui/displaytagform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -23,165 +23,31 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -''' +""" The :mod:`DisplayTagTab` provides an Tag Edit facility. The Base set are protected and included each time loaded. Custom tags can be defined and saved. The Custom Tag arrays are saved in a pickle so QSettings works on them. Base Tags cannot be changed. - -''' +""" import cPickle + from PyQt4 import QtCore, QtGui -from openlp.core.lib import SettingsTab, translate, DisplayTags +from openlp.core.lib import translate, DisplayTags from openlp.core.lib.ui import critical_error_message_box +from openlp.core.ui.displaytagdialog import Ui_DisplayTagDialog -class DisplayTagTab(SettingsTab): - ''' +class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog): + """ The :class:`DisplayTagTab` manages the settings tab . - ''' - def __init__(self): - ''' - Initialise the settings tab - ''' - SettingsTab.__init__(self, u'Display Tags') - - def resizeEvent(self, event=None): - pass - - def preLoad(self): + """ + def __init__(self, parent): """ - Initialise values before the Load takes place + Constructor """ - # Create initial copy from master - DisplayTags.reset_html_tags() - user_expands = QtCore.QSettings().value(u'displayTags/html_tags', - QtCore.QVariant(u'')).toString() - # cPickle only accepts str not unicode strings - user_expands_string = str(unicode(user_expands).encode(u'utf8')) - if user_expands_string: - user_tags = cPickle.loads(user_expands_string) - # If we have some user ones added them as well - for t in user_tags: - DisplayTags.add_html_tag(t) - self.selected = -1 - - def setupUi(self): - ''' - Configure the UI elements for the tab. - ''' - self.setObjectName(u'DisplayTagTab') - self.tabTitleVisible = \ - translate(u'OpenLP.DisplayTagTab', 'Display Tags') - self.displayTagEdit = QtGui.QWidget(self) - self.editGroupBox = QtGui.QGroupBox(self.displayTagEdit) - self.editGroupBox.setGeometry(QtCore.QRect(10, 220, 650, 181)) - self.editGroupBox.setObjectName(u'editGroupBox') - self.updatePushButton = QtGui.QPushButton(self.editGroupBox) - self.updatePushButton.setGeometry(QtCore.QRect(550, 140, 71, 26)) - self.updatePushButton.setObjectName(u'updatePushButton') - self.layoutWidget = QtGui.QWidget(self.editGroupBox) - self.layoutWidget.setGeometry(QtCore.QRect(5, 20, 571, 114)) - self.layoutWidget.setObjectName(u'layoutWidget') - self.formLayout = QtGui.QFormLayout(self.layoutWidget) - self.formLayout.setObjectName(u'formLayout') - self.descriptionLabel = QtGui.QLabel(self.layoutWidget) - self.descriptionLabel.setAlignment(QtCore.Qt.AlignCenter) - self.descriptionLabel.setObjectName(u'descriptionLabel') - self.formLayout.setWidget(0, QtGui.QFormLayout.LabelRole, - self.descriptionLabel) - self.descriptionLineEdit = QtGui.QLineEdit(self.layoutWidget) - self.descriptionLineEdit.setObjectName(u'descriptionLineEdit') - self.formLayout.setWidget(0, QtGui.QFormLayout.FieldRole, - self.descriptionLineEdit) - self.tagLabel = QtGui.QLabel(self.layoutWidget) - self.tagLabel.setAlignment(QtCore.Qt.AlignCenter) - self.tagLabel.setObjectName(u'tagLabel') - self.formLayout.setWidget(1, QtGui.QFormLayout.LabelRole, self.tagLabel) - self.tagLineEdit = QtGui.QLineEdit(self.layoutWidget) - self.tagLineEdit.setMaximumSize(QtCore.QSize(50, 16777215)) - self.tagLineEdit.setMaxLength(5) - self.tagLineEdit.setObjectName(u'tagLineEdit') - self.formLayout.setWidget(1, QtGui.QFormLayout.FieldRole, - self.tagLineEdit) - self.startTagLabel = QtGui.QLabel(self.layoutWidget) - self.startTagLabel.setAlignment(QtCore.Qt.AlignCenter) - self.startTagLabel.setObjectName(u'startTagLabel') - self.formLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.startTagLabel) - self.startTagLineEdit = QtGui.QLineEdit(self.layoutWidget) - self.startTagLineEdit.setObjectName(u'startTagLineEdit') - self.formLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.startTagLineEdit) - self.endTagLabel = QtGui.QLabel(self.layoutWidget) - self.endTagLabel.setAlignment(QtCore.Qt.AlignCenter) - self.endTagLabel.setObjectName(u'endTagLabel') - self.formLayout.setWidget(3, QtGui.QFormLayout.LabelRole, - self.endTagLabel) - self.endTagLineEdit = QtGui.QLineEdit(self.layoutWidget) - self.endTagLineEdit.setObjectName(u'endTagLineEdit') - self.formLayout.setWidget(3, QtGui.QFormLayout.FieldRole, - self.endTagLineEdit) - self.defaultPushButton = QtGui.QPushButton(self.displayTagEdit) - self.defaultPushButton.setGeometry(QtCore.QRect(430, 188, 71, 26)) - self.defaultPushButton.setObjectName(u'updatePushButton') - self.deletePushButton = QtGui.QPushButton(self.displayTagEdit) - self.deletePushButton.setGeometry(QtCore.QRect(510, 188, 71, 26)) - self.deletePushButton.setObjectName(u'deletePushButton') - self.newPushButton = QtGui.QPushButton(self.displayTagEdit) - self.newPushButton.setGeometry(QtCore.QRect(600, 188, 71, 26)) - self.newPushButton.setObjectName(u'newPushButton') - self.tagTableWidget = QtGui.QTableWidget(self.displayTagEdit) - self.tagTableWidget.setGeometry(QtCore.QRect(10, 10, 650, 171)) - self.tagTableWidget.setHorizontalScrollBarPolicy( - QtCore.Qt.ScrollBarAlwaysOff) - self.tagTableWidget.setEditTriggers( - QtGui.QAbstractItemView.NoEditTriggers) - self.tagTableWidget.setAlternatingRowColors(True) - self.tagTableWidget.setSelectionMode( - QtGui.QAbstractItemView.SingleSelection) - self.tagTableWidget.setSelectionBehavior( - QtGui.QAbstractItemView.SelectRows) - self.tagTableWidget.setCornerButtonEnabled(False) - self.tagTableWidget.setObjectName(u'tagTableWidget') - self.tagTableWidget.setColumnCount(4) - self.tagTableWidget.setRowCount(0) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(0, item) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(1, item) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(2, item) - item = QtGui.QTableWidgetItem() - self.tagTableWidget.setHorizontalHeaderItem(3, item) - self.editGroupBox.setTitle( - translate('OpenLP.DisplayTagTab', 'Edit Selection')) - self.updatePushButton.setText( - translate('OpenLP.DisplayTagTab', 'Update')) - self.descriptionLabel.setText( - translate('OpenLP.DisplayTagTab', 'Description')) - self.tagLabel.setText(translate('OpenLP.DisplayTagTab', 'Tag')) - self.startTagLabel.setText( - translate('OpenLP.DisplayTagTab', 'Start tag')) - self.endTagLabel.setText(translate('OpenLP.DisplayTagTab', 'End tag')) - self.deletePushButton.setText( - translate('OpenLP.DisplayTagTab', 'Delete')) - self.defaultPushButton.setText( - translate('OpenLP.DisplayTagTab', 'Default')) - self.newPushButton.setText(translate('OpenLP.DisplayTagTab', 'New')) - self.tagTableWidget.horizontalHeaderItem(0)\ - .setText(translate('OpenLP.DisplayTagTab', 'Description')) - self.tagTableWidget.horizontalHeaderItem(1)\ - .setText(translate('OpenLP.DisplayTagTab', 'Tag id')) - self.tagTableWidget.horizontalHeaderItem(2)\ - .setText(translate('OpenLP.DisplayTagTab', 'Start Html')) - self.tagTableWidget.horizontalHeaderItem(3)\ - .setText(translate('OpenLP.DisplayTagTab', 'End Html')) - QtCore.QMetaObject.connectSlotsByName(self.displayTagEdit) - self.tagTableWidget.setColumnWidth(0, 120) - self.tagTableWidget.setColumnWidth(1, 40) - self.tagTableWidget.setColumnWidth(2, 240) - self.tagTableWidget.setColumnWidth(3, 200) + QtGui.QDialog.__init__(self, parent) + self.setupUi(self) + self.preLoad() QtCore.QObject.connect(self.tagTableWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected) QtCore.QObject.connect(self.defaultPushButton, @@ -193,35 +59,35 @@ class DisplayTagTab(SettingsTab): QtCore.QObject.connect(self.deletePushButton, QtCore.SIGNAL(u'pressed()'), self.onDeletePushed) - def load(self): + def exec_(self): """ Load Display and set field state. """ - self.newPushButton.setEnabled(True) - self.updatePushButton.setEnabled(False) - self.deletePushButton.setEnabled(False) - for linenumber, html in enumerate(DisplayTags.get_html_tags()): - self.tagTableWidget.setRowCount( - self.tagTableWidget.rowCount() + 1) - self.tagTableWidget.setItem(linenumber, 0, - QtGui.QTableWidgetItem(html[u'desc'])) - self.tagTableWidget.setItem(linenumber, 1, - QtGui.QTableWidgetItem(self._strip(html[u'start tag']))) - self.tagTableWidget.setItem(linenumber, 2, - QtGui.QTableWidgetItem(html[u'start html'])) - self.tagTableWidget.setItem(linenumber, 3, - QtGui.QTableWidgetItem(html[u'end html'])) - self.tagTableWidget.resizeRowsToContents() - self.descriptionLineEdit.setText(u'') - self.tagLineEdit.setText(u'') - self.startTagLineEdit.setText(u'') - self.endTagLineEdit.setText(u'') - self.descriptionLineEdit.setEnabled(False) - self.tagLineEdit.setEnabled(False) - self.startTagLineEdit.setEnabled(False) - self.endTagLineEdit.setEnabled(False) + # Create initial copy from master + self.preLoad() + self._resetTable() + self.selected = -1 + return QtGui.QDialog.exec_(self) - def save(self): + def preLoad(self): + """ + Load the Tags from store so can be used in the system or used to + update the display. If Cancel was selected this is needed to reset the + dsiplay to the correct version. + """ + # Initial Load of the Tags + DisplayTags.reset_html_tags() + user_expands = QtCore.QSettings().value(u'displayTags/html_tags', + QtCore.QVariant(u'')).toString() + # cPickle only accepts str not unicode strings + user_expands_string = str(unicode(user_expands).encode(u'utf8')) + if user_expands_string: + user_tags = cPickle.loads(user_expands_string) + # If we have some user ones added them as well + for t in user_tags: + DisplayTags.add_html_tag(t) + + def accept(self): """ Save Custom tags in a pickle . """ @@ -236,13 +102,14 @@ class DisplayTagTab(SettingsTab): else: QtCore.QSettings().setValue(u'displayTags/html_tags', QtCore.QVariant(u'')) + return QtGui.QDialog.accept(self) - def cancel(self): + def reject(self): """ Reset Custom tags from Settings. """ - self.preLoad() self._resetTable() + return QtGui.QDialog.reject(self) def onRowSelected(self): """ @@ -289,6 +156,7 @@ class DisplayTagTab(SettingsTab): self._resetTable() # Highlight new row self.tagTableWidget.selectRow(self.tagTableWidget.rowCount() - 1) + self.onRowSelected() def onDefaultPushed(self): """ @@ -336,7 +204,29 @@ class DisplayTagTab(SettingsTab): """ self.tagTableWidget.clearContents() self.tagTableWidget.setRowCount(0) - self.load() + self.newPushButton.setEnabled(True) + self.updatePushButton.setEnabled(False) + self.deletePushButton.setEnabled(False) + for linenumber, html in enumerate(DisplayTags.get_html_tags()): + self.tagTableWidget.setRowCount( + self.tagTableWidget.rowCount() + 1) + self.tagTableWidget.setItem(linenumber, 0, + QtGui.QTableWidgetItem(html[u'desc'])) + self.tagTableWidget.setItem(linenumber, 1, + QtGui.QTableWidgetItem(self._strip(html[u'start tag']))) + self.tagTableWidget.setItem(linenumber, 2, + QtGui.QTableWidgetItem(html[u'start html'])) + self.tagTableWidget.setItem(linenumber, 3, + QtGui.QTableWidgetItem(html[u'end html'])) + self.tagTableWidget.resizeRowsToContents() + self.descriptionLineEdit.setText(u'') + self.tagLineEdit.setText(u'') + self.startTagLineEdit.setText(u'') + self.endTagLineEdit.setText(u'') + self.descriptionLineEdit.setEnabled(False) + self.tagLineEdit.setEnabled(False) + self.startTagLineEdit.setEnabled(False) + self.endTagLineEdit.setEnabled(False) def _strip(self, tag): """ diff --git a/openlp/core/ui/exceptiondialog.py b/openlp/core/ui/exceptiondialog.py index ba7bab496..770913b01 100644 --- a/openlp/core/ui/exceptiondialog.py +++ b/openlp/core/ui/exceptiondialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/ui/exceptionform.py b/openlp/core/ui/exceptionform.py index 7f9e23c61..6fb2d3f84 100644 --- a/openlp/core/ui/exceptionform.py +++ b/openlp/core/ui/exceptionform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -35,27 +35,28 @@ from PyQt4 import Qt, QtCore, QtGui try: from PyQt4.phonon import Phonon - phonon_version = Phonon.phononVersion() + PHONON_VERSION = Phonon.phononVersion() except ImportError: - phonon_version = u'-' + PHONON_VERSION = u'-' try: import chardet - chardet_version = chardet.__version__ + CHARDET_VERSION = chardet.__version__ except ImportError: - chardet_version = u'-' + CHARDET_VERSION = u'-' try: import enchant - enchant_version = enchant.__version__ + ENCHANT_VERSION = enchant.__version__ except ImportError: - enchant_version = u'-' + ENCHANT_VERSION = u'-' try: import sqlite - sqlite_version = sqlite.version + SQLITE_VERSION = sqlite.version except ImportError: - sqlite_version = u'-' + SQLITE_VERSION = u'-' from openlp.core.lib import translate, SettingsManager from openlp.core.lib.mailto import mailto +from openlp.core.lib.ui import UiStrings from exceptiondialog import Ui_ExceptionDialog @@ -84,14 +85,14 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog): 'Platform: %s\n')) % platform.platform() libraries = u'Python: %s\n' % platform.python_version() + \ u'Qt4: %s\n' % Qt.qVersion() + \ - u'Phonon: %s\n' % phonon_version + \ + u'Phonon: %s\n' % PHONON_VERSION + \ u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \ u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \ u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \ u'lxml: %s\n' % etree.__version__ + \ - u'Chardet: %s\n' % chardet_version + \ - u'PyEnchant: %s\n' % enchant_version + \ - u'PySQLite: %s\n' % sqlite_version + u'Chardet: %s\n' % CHARDET_VERSION + \ + u'PyEnchant: %s\n' % ENCHANT_VERSION + \ + u'PySQLite: %s\n' % SQLITE_VERSION if platform.system() == u'Linux': if os.environ.get(u'KDE_FULL_SESSION') == u'true': system = system + u'Desktop: KDE SC\n' @@ -169,15 +170,14 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog): self.__buttonState(False) self.descriptionWordCount.setText( unicode(translate('OpenLP.ExceptionDialog', - 'Description characters to enter : %s')) % count ) + 'Description characters to enter : %s')) % count) def onAttachFileButtonPressed(self): files = QtGui.QFileDialog.getOpenFileName( self,translate('ImagePlugin.ExceptionDialog', 'Select Attachment'), SettingsManager.get_last_dir(u'exceptions'), - u'%s (*.*) (*)' % - unicode(translate('ImagePlugin.MediaItem', 'All Files'))) + u'%s (*.*) (*)' % UiStrings.AllFiles) log.info(u'New files(s) %s', unicode(files)) if files: self.fileAttachment = unicode(files) diff --git a/openlp/core/ui/filerenamedialog.py b/openlp/core/ui/filerenamedialog.py index c9a8a7633..30c206d2c 100644 --- a/openlp/core/ui/filerenamedialog.py +++ b/openlp/core/ui/filerenamedialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,30 +27,28 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_FileRenameDialog(object): - def setupUi(self, FileRenameDialog): - FileRenameDialog.setObjectName(u'FileRenameDialog') - FileRenameDialog.resize(300, 10) - self.dialogLayout = QtGui.QGridLayout(FileRenameDialog) + def setupUi(self, fileRenameDialog): + fileRenameDialog.setObjectName(u'fileRenameDialog') + fileRenameDialog.resize(300, 10) + self.dialogLayout = QtGui.QGridLayout(fileRenameDialog) self.dialogLayout.setObjectName(u'dialogLayout') - self.fileNameLabel = QtGui.QLabel(FileRenameDialog) + self.fileNameLabel = QtGui.QLabel(fileRenameDialog) self.fileNameLabel.setObjectName(u'fileNameLabel') self.dialogLayout.addWidget(self.fileNameLabel, 0, 0) - self.fileNameEdit = QtGui.QLineEdit(FileRenameDialog) + self.fileNameEdit = QtGui.QLineEdit(fileRenameDialog) self.fileNameEdit.setValidator(QtGui.QRegExpValidator( QtCore.QRegExp(r'[^/\\?*|<>\[\]":<>+%]+'), self)) self.fileNameEdit.setObjectName(u'fileNameEdit') self.dialogLayout.addWidget(self.fileNameEdit, 0, 1) - self.buttonBox = QtGui.QDialogButtonBox(FileRenameDialog) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | - QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName(u'buttonBox') + self.buttonBox = create_accept_reject_button_box(fileRenameDialog, True) self.dialogLayout.addWidget(self.buttonBox, 1, 0, 1, 2) - self.retranslateUi(FileRenameDialog) + self.retranslateUi(fileRenameDialog) self.setMaximumHeight(self.sizeHint().height()) - QtCore.QMetaObject.connectSlotsByName(FileRenameDialog) + QtCore.QMetaObject.connectSlotsByName(fileRenameDialog) - def retranslateUi(self, FileRenameDialog): + def retranslateUi(self, fileRenameDialog): self.fileNameLabel.setText(translate('OpenLP.FileRenameForm', 'New File Name:')) diff --git a/openlp/core/ui/filerenameform.py b/openlp/core/ui/filerenameform.py index 86634e3b1..69a1c3f6a 100644 --- a/openlp/core/ui/filerenameform.py +++ b/openlp/core/ui/filerenameform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -24,7 +24,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from PyQt4 import QtCore, QtGui +from PyQt4 import QtGui from filerenamedialog import Ui_FileRenameDialog @@ -37,10 +37,6 @@ class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): def __init__(self, parent): QtGui.QDialog.__init__(self, parent) self.setupUi(self) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), - self.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'), - self.reject) def exec_(self, copy=False): """ @@ -51,5 +47,5 @@ class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): 'File Copy')) else: self.setWindowTitle(translate('OpenLP.FileRenameForm', - 'File Rename')) + 'File Rename')) return QtGui.QDialog.exec_(self) diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 12353fed8..4eacc5959 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,6 +28,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, Receiver, translate +from openlp.core.lib.ui import UiStrings log = logging.getLogger(__name__) @@ -44,7 +45,7 @@ class ValidEdit(QtGui.QLineEdit): def validText(self): """ - Only return Integers. Space is 0 + Only return Integers. Space is 0 """ if self.text().isEmpty(): return QtCore.QString(u'0') @@ -267,8 +268,7 @@ class GeneralTab(SettingsTab): translate('OpenLP.GeneralTab', ' sec')) self.ccliGroupBox.setTitle( translate('OpenLP.GeneralTab', 'CCLI Details')) - self.numberLabel.setText( - translate('OpenLP.GeneralTab', 'CCLI number:')) + self.numberLabel.setText(UiStrings.CCLINumberLabel) self.usernameLabel.setText( translate('OpenLP.GeneralTab', 'SongSelect username:')) self.passwordLabel.setText( diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 3dfde8640..06de73309 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -72,7 +72,7 @@ class MainDisplay(DisplayWidget): self.setWindowIcon(mainIcon) self.retranslateUi() self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') - self.setWindowFlags(QtCore.Qt.FramelessWindowHint | + self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint) if self.isLive: QtCore.QObject.connect(Receiver.get_receiver(), @@ -106,6 +106,9 @@ class MainDisplay(DisplayWidget): self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject) Phonon.createPath(self.mediaObject, self.videoWidget) Phonon.createPath(self.mediaObject, self.audio) + QtCore.QObject.connect(self.mediaObject, + QtCore.SIGNAL(u'stateChanged(Phonon::State, Phonon::State)'), + self.videoStart) self.webView = QtWebKit.QWebView(self) self.webView.setGeometry(0, 0, self.screen[u'size'].width(), self.screen[u'size'].height()) @@ -129,14 +132,22 @@ class MainDisplay(DisplayWidget): painter_image.begin(self.black) painter_image.fillRect(self.black.rect(), QtCore.Qt.black) # Build the initial frame. + image_file = QtCore.QSettings().value(u'advanced/default image', + QtCore.QVariant(u':/graphics/openlp-splash-screen.png'))\ + .toString() + background_color = QtGui.QColor(QtCore.QSettings().value( + u'advanced/default color', + QtCore.QVariant(u'#ffffff')).toString()) + if not background_color.isValid(): + background_color = QtCore.Qt.white + splash_image = QtGui.QImage(image_file) initialFrame = QtGui.QImage( self.screens.current[u'size'].width(), self.screens.current[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) - splash_image = QtGui.QImage(u':/graphics/openlp-splash-screen.png') painter_image = QtGui.QPainter() painter_image.begin(initialFrame) - painter_image.fillRect(initialFrame.rect(), QtCore.Qt.white) + painter_image.fillRect(initialFrame.rect(), background_color) painter_image.drawImage( (self.screens.current[u'size'].width() - splash_image.width()) / 2, @@ -145,7 +156,7 @@ class MainDisplay(DisplayWidget): serviceItem = ServiceItem() serviceItem.bg_image_bytes = image_to_byte(initialFrame) self.webView.setHtml(build_html(serviceItem, self.screen, - self.parent.alertTab, self.isLive, None)) + self.alertTab, self.isLive, None)) self.initialFrame = True # To display or not to display? if not self.screen[u'primary']: @@ -326,8 +337,7 @@ class MainDisplay(DisplayWidget): vol = float(volume)/float(10) if isBackground or not self.usePhonon: js = u'show_video("init", "%s", %s, true); show_video("play");' % \ - (videoPath.replace(u'\\', u'\\\\'), \ - str(vol)) + (videoPath.replace(u'\\', u'\\\\'), str(vol)) self.frame.evaluateJavaScript(js) else: self.phononActive = True @@ -342,6 +352,13 @@ class MainDisplay(DisplayWidget): Receiver.send_message(u'maindisplay_active') return self.preview() + def videoStart(self, newState, oldState): + """ + Start the video at a predetermined point. + """ + if newState == Phonon.PlayingState: + self.mediaObject.seek(self.serviceItem.start_time * 1000) + def isWebLoaded(self): """ Called by webView event to show display is fully loaded @@ -398,8 +415,7 @@ class MainDisplay(DisplayWidget): if u'video' in self.override: Receiver.send_message(u'video_background_replaced') self.override = {} - elif self.override[u'theme'] != \ - serviceItem.themedata.theme_name: + elif self.override[u'theme'] != serviceItem.themedata.theme_name: Receiver.send_message(u'live_theme_changed') self.override = {} else: @@ -408,7 +424,7 @@ class MainDisplay(DisplayWidget): if self.serviceItem.themedata.background_filename: self.serviceItem.bg_image_bytes = self.imageManager. \ get_image_bytes(self.serviceItem.themedata.theme_name) - html = build_html(self.serviceItem, self.screen, self.parent.alertTab, + html = build_html(self.serviceItem, self.screen, self.alertTab, self.isLive, background) log.debug(u'buildHtml - pre setHtml') self.webView.setHtml(html) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 9af4931fb..b9de8a12e 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -30,10 +30,11 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \ SettingsManager, PluginManager, Receiver, translate -from openlp.core.lib.ui import base_action, checkable_action, icon_action +from openlp.core.lib.ui import UiStrings, base_action, checkable_action, \ + icon_action from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \ - ShortcutListForm + ShortcutListForm, DisplayTagForm from openlp.core.utils import AppLocation, add_actions, LanguageManager, \ ActionList @@ -72,15 +73,15 @@ class Ui_MainWindow(object): # Set up the main container, which contains all the other form widgets. self.MainContent = QtGui.QWidget(mainWindow) self.MainContent.setObjectName(u'MainContent') - self.MainContentLayout = QtGui.QHBoxLayout(self.MainContent) - self.MainContentLayout.setSpacing(0) - self.MainContentLayout.setMargin(0) - self.MainContentLayout.setObjectName(u'MainContentLayout') + self.mainContentLayout = QtGui.QHBoxLayout(self.MainContent) + self.mainContentLayout.setSpacing(0) + self.mainContentLayout.setMargin(0) + self.mainContentLayout.setObjectName(u'mainContentLayout') mainWindow.setCentralWidget(self.MainContent) - self.ControlSplitter = QtGui.QSplitter(self.MainContent) - self.ControlSplitter.setOrientation(QtCore.Qt.Horizontal) - self.ControlSplitter.setObjectName(u'ControlSplitter') - self.MainContentLayout.addWidget(self.ControlSplitter) + self.controlSplitter = QtGui.QSplitter(self.MainContent) + self.controlSplitter.setOrientation(QtCore.Qt.Horizontal) + self.controlSplitter.setObjectName(u'controlSplitter') + self.mainContentLayout.addWidget(self.controlSplitter) # Create slide controllers self.previewController = SlideController(self, self.settingsmanager, self.screens) @@ -102,9 +103,9 @@ class Ui_MainWindow(object): self.FileExportMenu = QtGui.QMenu(self.FileMenu) self.FileExportMenu.setObjectName(u'FileExportMenu') # View Menu - self.ViewMenu = QtGui.QMenu(self.MenuBar) - self.ViewMenu.setObjectName(u'ViewMenu') - self.ViewModeMenu = QtGui.QMenu(self.ViewMenu) + self.viewMenu = QtGui.QMenu(self.MenuBar) + self.viewMenu.setObjectName(u'viewMenu') + self.ViewModeMenu = QtGui.QMenu(self.viewMenu) self.ViewModeMenu.setObjectName(u'ViewModeMenu') # Tools Menu self.ToolsMenu = QtGui.QMenu(self.MenuBar) @@ -125,38 +126,38 @@ class Ui_MainWindow(object): self.DefaultThemeLabel.setObjectName(u'DefaultThemeLabel') self.StatusBar.addPermanentWidget(self.DefaultThemeLabel) # Create the MediaManager - self.MediaManagerDock = OpenLPDockWidget(mainWindow, - u'MediaManagerDock', u':/system/system_mediamanager.png') - self.MediaManagerDock.setStyleSheet(MEDIA_MANAGER_STYLE) - self.MediaManagerDock.setMinimumWidth( + self.mediaManagerDock = OpenLPDockWidget(mainWindow, + u'mediaManagerDock', u':/system/system_mediamanager.png') + self.mediaManagerDock.setStyleSheet(MEDIA_MANAGER_STYLE) + self.mediaManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_left) # Create the media toolbox - self.MediaToolBox = QtGui.QToolBox(self.MediaManagerDock) + self.MediaToolBox = QtGui.QToolBox(self.mediaManagerDock) self.MediaToolBox.setObjectName(u'MediaToolBox') - self.MediaManagerDock.setWidget(self.MediaToolBox) + self.mediaManagerDock.setWidget(self.MediaToolBox) mainWindow.addDockWidget(QtCore.Qt.LeftDockWidgetArea, - self.MediaManagerDock) + self.mediaManagerDock) # Create the service manager - self.ServiceManagerDock = OpenLPDockWidget(mainWindow, - u'ServiceManagerDock', u':/system/system_servicemanager.png') - self.ServiceManagerDock.setMinimumWidth( + self.serviceManagerDock = OpenLPDockWidget(mainWindow, + u'serviceManagerDock', u':/system/system_servicemanager.png') + self.serviceManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) self.ServiceManagerContents = ServiceManager(mainWindow, - self.ServiceManagerDock) - self.ServiceManagerDock.setWidget(self.ServiceManagerContents) + self.serviceManagerDock) + self.serviceManagerDock.setWidget(self.ServiceManagerContents) mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, - self.ServiceManagerDock) + self.serviceManagerDock) # Create the theme manager - self.ThemeManagerDock = OpenLPDockWidget(mainWindow, - u'ThemeManagerDock', u':/system/system_thememanager.png') - self.ThemeManagerDock.setMinimumWidth( + self.themeManagerDock = OpenLPDockWidget(mainWindow, + u'themeManagerDock', u':/system/system_thememanager.png') + self.themeManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ThemeManagerContents = ThemeManager(mainWindow, - self.ThemeManagerDock) - self.ThemeManagerContents.setObjectName(u'ThemeManagerContents') - self.ThemeManagerDock.setWidget(self.ThemeManagerContents) + self.themeManagerContents = ThemeManager(mainWindow, + self.themeManagerDock) + self.themeManagerContents.setObjectName(u'themeManagerContents') + self.themeManagerDock.setWidget(self.themeManagerContents) mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, - self.ThemeManagerDock) + self.themeManagerDock) # Create the menu items self.FileNewItem = icon_action(mainWindow, u'FileNewItem', u':/general/general_new.png') @@ -186,14 +187,14 @@ class Ui_MainWindow(object): mainWindow.actionList.add_action(self.ExportLanguageItem, u'Export') self.ViewMediaManagerItem = icon_action(mainWindow, u'ViewMediaManagerItem', u':/system/system_mediamanager.png', - self.MediaManagerDock.isVisible()) + self.mediaManagerDock.isVisible()) self.ViewThemeManagerItem = icon_action(mainWindow, u'ViewThemeManagerItem', u':/system/system_thememanager.png', - self.ThemeManagerDock.isVisible()) + self.themeManagerDock.isVisible()) mainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View') self.ViewServiceManagerItem = icon_action(mainWindow, u'ViewServiceManagerItem', u':/system/system_servicemanager.png', - self.ServiceManagerDock.isVisible()) + self.serviceManagerDock.isVisible()) mainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View') self.ViewPreviewPanel = checkable_action(mainWindow, u'ViewPreviewPanel', previewVisible) @@ -215,9 +216,12 @@ class Ui_MainWindow(object): self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem', u':/tools/tools_add.png') mainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools') - self.SettingsPluginListItem = icon_action(mainWindow, - u'SettingsPluginListItem', u':/system/settings_plugin_list.png') - mainWindow.actionList.add_action(self.SettingsPluginListItem, + self.ToolsOpenDataFolder = icon_action(mainWindow, + u'ToolsOpenDataFolder', u':/general/general_open.png') + mainWindow.actionList.add_action(self.ToolsOpenDataFolder, u'Tools') + self.settingsPluginListItem = icon_action(mainWindow, + u'settingsPluginListItem', u':/system/settings_plugin_list.png') + mainWindow.actionList.add_action(self.settingsPluginListItem, u'Settings') # i18n Language Items self.AutoLanguageItem = checkable_action(mainWindow, @@ -236,8 +240,10 @@ class Ui_MainWindow(object): languageItem.setChecked(True) add_actions(self.LanguageGroup, [languageItem]) self.SettingsShortcutsItem = icon_action(mainWindow, - u'SettingsShortcutsItem', + u'SettingsShortcutsItem', u':/system/system_configure_shortcuts.png') + self.DisplayTagItem = icon_action(mainWindow, + u'DisplayTagItem', u':/system/tag_editor.png') self.SettingsConfigureItem = icon_action(mainWindow, u'SettingsConfigureItem', u':/system/system_settings.png') mainWindow.actionList.add_action(self.SettingsShortcutsItem, @@ -252,8 +258,8 @@ class Ui_MainWindow(object): self.HelpOnlineHelpItem = base_action(mainWindow, u'HelpOnlineHelpItem') self.HelpOnlineHelpItem.setEnabled(False) mainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help') - self.HelpWebSiteItem = base_action(mainWindow, u'HelpWebSiteItem') - mainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help') + self.helpWebSiteItem = base_action(mainWindow, u'helpWebSiteItem') + mainWindow.actionList.add_action(self.helpWebSiteItem, u'Help') add_actions(self.FileImportMenu, (self.ImportThemeItem, self.ImportLanguageItem)) add_actions(self.FileExportMenu, @@ -264,22 +270,24 @@ class Ui_MainWindow(object): self.FileExportMenu.menuAction(), self.FileExitItem) add_actions(self.ViewModeMenu, (self.ModeDefaultItem, self.ModeSetupItem, self.ModeLiveItem)) - add_actions(self.ViewMenu, (self.ViewModeMenu.menuAction(), + add_actions(self.viewMenu, (self.ViewModeMenu.menuAction(), None, self.ViewMediaManagerItem, self.ViewServiceManagerItem, self.ViewThemeManagerItem, None, self.ViewPreviewPanel, self.ViewLivePanel)) # i18n add Language Actions add_actions(self.SettingsLanguageMenu, (self.AutoLanguageItem, None)) add_actions(self.SettingsLanguageMenu, self.LanguageGroup.actions()) - add_actions(self.SettingsMenu, (self.SettingsPluginListItem, + add_actions(self.SettingsMenu, (self.settingsPluginListItem, self.SettingsLanguageMenu.menuAction(), None, - self.SettingsShortcutsItem, self.SettingsConfigureItem)) + self.DisplayTagItem, self.SettingsShortcutsItem, + self.SettingsConfigureItem)) add_actions(self.ToolsMenu, (self.ToolsAddToolItem, None)) + add_actions(self.ToolsMenu, (self.ToolsOpenDataFolder, None)) add_actions(self.HelpMenu, (self.HelpDocumentationItem, - self.HelpOnlineHelpItem, None, self.HelpWebSiteItem, + self.HelpOnlineHelpItem, None, self.helpWebSiteItem, self.HelpAboutItem)) add_actions(self.MenuBar, (self.FileMenu.menuAction(), - self.ViewMenu.menuAction(), self.ToolsMenu.menuAction(), + self.viewMenu.menuAction(), self.ToolsMenu.menuAction(), self.SettingsMenu.menuAction(), self.HelpMenu.menuAction())) # Initialise the translation self.retranslateUi(mainWindow) @@ -295,39 +303,35 @@ class Ui_MainWindow(object): """ Set up the translation system """ - mainWindow.mainTitle = translate('OpenLP.MainWindow', 'OpenLP 2.0') + mainWindow.mainTitle = UiStrings.OLPV2 mainWindow.setWindowTitle(mainWindow.mainTitle) self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File')) self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import')) self.FileExportMenu.setTitle(translate('OpenLP.MainWindow', '&Export')) - self.ViewMenu.setTitle(translate('OpenLP.MainWindow', '&View')) + self.viewMenu.setTitle(translate('OpenLP.MainWindow', '&View')) self.ViewModeMenu.setTitle(translate('OpenLP.MainWindow', 'M&ode')) self.ToolsMenu.setTitle(translate('OpenLP.MainWindow', '&Tools')) self.SettingsMenu.setTitle(translate('OpenLP.MainWindow', '&Settings')) self.SettingsLanguageMenu.setTitle(translate('OpenLP.MainWindow', '&Language')) self.HelpMenu.setTitle(translate('OpenLP.MainWindow', '&Help')) - self.MediaManagerDock.setWindowTitle( + self.mediaManagerDock.setWindowTitle( translate('OpenLP.MainWindow', 'Media Manager')) - self.ServiceManagerDock.setWindowTitle( + self.serviceManagerDock.setWindowTitle( translate('OpenLP.MainWindow', 'Service Manager')) - self.ThemeManagerDock.setWindowTitle( + self.themeManagerDock.setWindowTitle( translate('OpenLP.MainWindow', 'Theme Manager')) self.FileNewItem.setText(translate('OpenLP.MainWindow', '&New')) - self.FileNewItem.setToolTip( - translate('OpenLP.MainWindow', 'New Service')) - self.FileNewItem.setStatusTip( - translate('OpenLP.MainWindow', 'Create a new service.')) + self.FileNewItem.setToolTip(UiStrings.NewService) + self.FileNewItem.setStatusTip(UiStrings.CreateService) self.FileNewItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+N')) self.FileOpenItem.setText(translate('OpenLP.MainWindow', '&Open')) - self.FileOpenItem.setToolTip( - translate('OpenLP.MainWindow', 'Open Service')) + self.FileOpenItem.setToolTip(UiStrings.OpenService) self.FileOpenItem.setStatusTip( translate('OpenLP.MainWindow', 'Open an existing service.')) self.FileOpenItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+O')) self.FileSaveItem.setText(translate('OpenLP.MainWindow', '&Save')) - self.FileSaveItem.setToolTip( - translate('OpenLP.MainWindow', 'Save Service')) + self.FileSaveItem.setToolTip(UiStrings.SaveService) self.FileSaveItem.setStatusTip( translate('OpenLP.MainWindow', 'Save the current service to disk.')) self.FileSaveItem.setShortcut(translate('OpenLP.MainWindow', 'Ctrl+S')) @@ -339,8 +343,7 @@ class Ui_MainWindow(object): 'Save the current service under a new name.')) self.FileSaveAsItem.setShortcut( translate('OpenLP.MainWindow', 'Ctrl+Shift+S')) - self.printServiceOrderItem.setText( - translate('OpenLP.MainWindow', 'Print Service Order')) + self.printServiceOrderItem.setText(UiStrings.PrintServiceOrder) self.printServiceOrderItem.setStatusTip(translate('OpenLP.MainWindow', 'Print the current Service Order.')) self.printServiceOrderItem.setShortcut( @@ -361,6 +364,8 @@ class Ui_MainWindow(object): translate('OpenLP.MainWindow', '&Language')) self.SettingsShortcutsItem.setText( translate('OpenLP.MainWindow', 'Configure &Shortcuts...')) + self.DisplayTagItem.setText( + translate('OpenLP.MainWindow', '&Configure Display Tags')) self.SettingsConfigureItem.setText( translate('OpenLP.MainWindow', '&Configure OpenLP...')) self.ViewMediaManagerItem.setText( @@ -403,11 +408,11 @@ class Ui_MainWindow(object): 'Toggle the visibility of the live panel.')) self.ViewLivePanel.setShortcut( translate('OpenLP.MainWindow', 'F12')) - self.SettingsPluginListItem.setText(translate('OpenLP.MainWindow', + self.settingsPluginListItem.setText(translate('OpenLP.MainWindow', '&Plugin List')) - self.SettingsPluginListItem.setStatusTip( + self.settingsPluginListItem.setStatusTip( translate('OpenLP.MainWindow', 'List the Plugins')) - self.SettingsPluginListItem.setShortcut( + self.settingsPluginListItem.setShortcut( translate('OpenLP.MainWindow', 'Alt+F7')) self.HelpDocumentationItem.setText( translate('OpenLP.MainWindow', '&User Guide')) @@ -418,7 +423,7 @@ class Ui_MainWindow(object): translate('OpenLP.MainWindow', 'Ctrl+F1')) self.HelpOnlineHelpItem.setText( translate('OpenLP.MainWindow', '&Online Help')) - self.HelpWebSiteItem.setText( + self.helpWebSiteItem.setText( translate('OpenLP.MainWindow', '&Web Site')) self.AutoLanguageItem.setText( translate('OpenLP.MainWindow', '&Auto Detect')) @@ -432,6 +437,10 @@ class Ui_MainWindow(object): translate('OpenLP.MainWindow', 'Add &Tool...')) self.ToolsAddToolItem.setStatusTip(translate('OpenLP.MainWindow', 'Add an application to the list of tools.')) + self.ToolsOpenDataFolder.setText( + translate('OpenLP.MainWindow', 'Open &Data Folder...')) + self.ToolsOpenDataFolder.setStatusTip(translate('OpenLP.MainWindow', + 'Open the folder where songs, bibles and other data resides.')) self.ModeDefaultItem.setText( translate('OpenLP.MainWindow', '&Default')) self.ModeDefaultItem.setStatusTip(translate('OpenLP.MainWindow', @@ -452,7 +461,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): actionList = ActionList() - def __init__(self, screens, applicationVersion): + def __init__(self, screens, applicationVersion, clipboard): """ This constructor sets up the interface, the various managers, and the plugins. @@ -461,6 +470,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.screens = screens self.actionList = ActionList() self.applicationVersion = applicationVersion + self.clipboard = clipboard # Set up settings sections for the main application # (not for use by plugins) self.uiSettingsSection = u'user interface' @@ -471,6 +481,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.settingsmanager = SettingsManager(screens) self.aboutForm = AboutForm(self, applicationVersion) self.settingsForm = SettingsForm(self.screens, self, self) + self.displayTagForm = DisplayTagForm(self) self.shortcutForm = ShortcutListForm(self) self.recentFiles = QtCore.QStringList() # Set up the path with plugins @@ -487,10 +498,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Set up signals and slots QtCore.QObject.connect(self.ImportThemeItem, QtCore.SIGNAL(u'triggered()'), - self.ThemeManagerContents.onImportTheme) + self.themeManagerContents.onImportTheme) QtCore.QObject.connect(self.ExportThemeItem, QtCore.SIGNAL(u'triggered()'), - self.ThemeManagerContents.onExportTheme) + self.themeManagerContents.onExportTheme) QtCore.QObject.connect(self.ViewMediaManagerItem, QtCore.SIGNAL(u'triggered(bool)'), self.toggleMediaManager) QtCore.QObject.connect(self.ViewServiceManagerItem, @@ -501,21 +512,25 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.SIGNAL(u'toggled(bool)'), self.setPreviewPanelVisibility) QtCore.QObject.connect(self.ViewLivePanel, QtCore.SIGNAL(u'toggled(bool)'), self.setLivePanelVisibility) - QtCore.QObject.connect(self.MediaManagerDock, + QtCore.QObject.connect(self.mediaManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'), self.ViewMediaManagerItem.setChecked) - QtCore.QObject.connect(self.ServiceManagerDock, + QtCore.QObject.connect(self.serviceManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'), self.ViewServiceManagerItem.setChecked) - QtCore.QObject.connect(self.ThemeManagerDock, + QtCore.QObject.connect(self.themeManagerDock, QtCore.SIGNAL(u'visibilityChanged(bool)'), self.ViewThemeManagerItem.setChecked) - QtCore.QObject.connect(self.HelpWebSiteItem, + QtCore.QObject.connect(self.helpWebSiteItem, QtCore.SIGNAL(u'triggered()'), self.onHelpWebSiteClicked) QtCore.QObject.connect(self.HelpAboutItem, QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked) - QtCore.QObject.connect(self.SettingsPluginListItem, + QtCore.QObject.connect(self.ToolsOpenDataFolder, + QtCore.SIGNAL(u'triggered()'), self.onToolsOpenDataFolderClicked) + QtCore.QObject.connect(self.settingsPluginListItem, QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked) + QtCore.QObject.connect(self.DisplayTagItem, + QtCore.SIGNAL(u'triggered()'), self.onDisplayTagItemClicked) QtCore.QObject.connect(self.SettingsConfigureItem, QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked) QtCore.QObject.connect(self.SettingsShortcutsItem, @@ -567,7 +582,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # RenderManager needs to call ThemeManager and # ThemeManager needs to call RenderManager self.renderManager = RenderManager( - self.ThemeManagerContents, self.screens) + self.themeManagerContents, self.screens) # Define the media Dock Manager self.mediaDockManager = MediaDockManager(self.MediaToolBox) log.info(u'Load Plugins') @@ -601,7 +616,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.pluginManager.initialise_plugins() # Once all components are initialised load the Themes log.info(u'Load Themes') - self.ThemeManagerContents.loadThemes() + self.themeManagerContents.loadThemes() log.info(u'Load data from Settings') if QtCore.QSettings().value(u'advanced/save current plugin', QtCore.QVariant(False)).toBool(): @@ -702,6 +717,19 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.pluginForm.load() self.pluginForm.exec_() + def onToolsOpenDataFolderClicked(self): + """ + Open data folder + """ + path = AppLocation.get_data_path() + QtGui.QDesktopServices.openUrl(QtCore.QUrl("file:///" + path)) + + def onDisplayTagItemClicked(self): + """ + Show the Settings dialog + """ + self.displayTagForm.exec_() + def onSettingsConfigureItemClicked(self): """ Show the Settings dialog @@ -748,9 +776,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): settings = QtCore.QSettings() settings.setValue(u'%s/view mode' % self.generalSettingsSection, mode) - self.MediaManagerDock.setVisible(media) - self.ServiceManagerDock.setVisible(service) - self.ThemeManagerDock.setVisible(theme) + self.mediaManagerDock.setVisible(media) + self.serviceManagerDock.setVisible(service) + self.themeManagerDock.setVisible(theme) self.setPreviewPanelVisibility(preview) self.setLivePanelVisibility(live) @@ -867,16 +895,16 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): theme) def toggleMediaManager(self, visible): - if self.MediaManagerDock.isVisible() != visible: - self.MediaManagerDock.setVisible(visible) + if self.mediaManagerDock.isVisible() != visible: + self.mediaManagerDock.setVisible(visible) def toggleServiceManager(self, visible): - if self.ServiceManagerDock.isVisible() != visible: - self.ServiceManagerDock.setVisible(visible) + if self.serviceManagerDock.isVisible() != visible: + self.serviceManagerDock.setVisible(visible) def toggleThemeManager(self, visible): - if self.ThemeManagerDock.isVisible() != visible: - self.ThemeManagerDock.setVisible(visible) + if self.themeManagerDock.isVisible() != visible: + self.themeManagerDock.setVisible(visible) def setPreviewPanelVisibility(self, visible): """ diff --git a/openlp/core/ui/mediadockmanager.py b/openlp/core/ui/mediadockmanager.py index ced3850ec..2d388faf4 100644 --- a/openlp/core/ui/mediadockmanager.py +++ b/openlp/core/ui/mediadockmanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -85,4 +85,4 @@ class MediaDockManager(object): if self.media_dock.widget(dock_index).settingsSection == \ media_item.plugin.name.lower(): self.media_dock.widget(dock_index).hide() - self.media_dock.removeItem(dock_index) \ No newline at end of file + self.media_dock.removeItem(dock_index) diff --git a/openlp/core/ui/plugindialog.py b/openlp/core/ui/plugindialog.py index 74b2d36c0..0f6ed9395 100644 --- a/openlp/core/ui/plugindialog.py +++ b/openlp/core/ui/plugindialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,7 +25,9 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate +from openlp.core.lib.ui import UiStrings class Ui_PluginViewDialog(object): def setupUi(self, pluginViewDialog): @@ -76,10 +78,8 @@ class Ui_PluginViewDialog(object): translate('OpenLP.PluginForm', 'Plugin List')) self.pluginInfoGroupBox.setTitle( translate('OpenLP.PluginForm', 'Plugin Details')) - self.versionLabel.setText( - translate('OpenLP.PluginForm', 'Version:')) - self.aboutLabel.setText( - translate('OpenLP.PluginForm', 'About:')) + self.versionLabel.setText(u'%s:' % UiStrings.Version) + self.aboutLabel.setText(u'%s:' % UiStrings.About) self.statusLabel.setText( translate('OpenLP.PluginForm', 'Status:')) self.statusComboBox.setItemText(0, diff --git a/openlp/core/ui/pluginform.py b/openlp/core/ui/pluginform.py index d6ffc69f0..15ac62e42 100644 --- a/openlp/core/ui/pluginform.py +++ b/openlp/core/ui/pluginform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,13 +28,15 @@ import logging from PyQt4 import QtCore, QtGui -from openlp.core.lib import PluginStatus, StringContent, translate +from openlp.core.lib import PluginStatus, Receiver, translate from plugindialog import Ui_PluginViewDialog log = logging.getLogger(__name__) class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): - + """ + The plugin form provides user control over the plugins OpenLP uses. + """ def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.parent = parent @@ -78,15 +80,14 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): # PluginStatus.Inactive status_text = unicode( translate('OpenLP.PluginForm', '%s (Inactive)')) - name_string = plugin.getString(StringContent.Name) - item.setText(status_text % name_string[u'singular']) + item.setText(status_text % plugin.nameStrings[u'singular']) # If the plugin has an icon, set it! if plugin.icon: item.setIcon(plugin.icon) self.pluginListWidget.addItem(item) pluginListWidth = max(pluginListWidth, self.fontMetrics().width( unicode(translate('OpenLP.PluginForm', '%s (Inactive)')) % - name_string[u'singular'])) + plugin.nameStrings[u'singular'])) self.pluginListWidget.setFixedWidth(pluginListWidth + self.pluginListWidget.iconSize().width() + 48) @@ -116,8 +117,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): self.pluginListWidget.currentItem().text().split(u' ')[0] self.activePlugin = None for plugin in self.parent.pluginManager.plugins: - name_string = plugin.getString(StringContent.Name) - if name_string[u'singular'] == plugin_name_singular: + if plugin.nameStrings[u'singular'] == plugin_name_singular: self.activePlugin = plugin break if self.activePlugin: @@ -129,7 +129,9 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): if self.programaticChange: return if status == 0: + Receiver.send_message(u'cursor_busy') self.activePlugin.toggleStatus(PluginStatus.Active) + Receiver.send_message(u'cursor_normal') else: self.activePlugin.toggleStatus(PluginStatus.Inactive) status_text = unicode( @@ -143,6 +145,5 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog): elif self.activePlugin.status == PluginStatus.Disabled: status_text = unicode( translate('OpenLP.PluginForm', '%s (Disabled)')) - name_string = self.activePlugin.getString(StringContent.Name) self.pluginListWidget.currentItem().setText( - status_text % name_string[u'singular']) + status_text % self.activePlugin.nameStrings[u'singular']) diff --git a/openlp/core/ui/printservicedialog.py b/openlp/core/ui/printservicedialog.py new file mode 100644 index 000000000..41101e8ff --- /dev/null +++ b/openlp/core/ui/printservicedialog.py @@ -0,0 +1,165 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import build_icon, translate, SpellTextEdit +from openlp.core.lib.ui import UiStrings + +class ZoomSize(object): + """ + Type enumeration for Combo Box sizes + """ + Page = 0 + Width = 1 + OneHundred = 2 + SeventyFive = 3 + Fifty = 4 + TwentyFive = 5 + + Sizes = [ + translate('OpenLP.PrintServiceDialog', 'Fit Page'), + translate('OpenLP.PrintServiceDialog', 'Fit Width'), + u'100%', u'75%', u'50%', u'25%'] + + +class Ui_PrintServiceDialog(object): + def setupUi(self, printServiceDialog): + printServiceDialog.setObjectName(u'printServiceDialog') + printServiceDialog.resize(664, 594) + self.mainLayout = QtGui.QVBoxLayout(printServiceDialog) + self.mainLayout.setSpacing(0) + self.mainLayout.setMargin(0) + self.mainLayout.setObjectName(u'mainLayout') + self.toolbar = QtGui.QToolBar(printServiceDialog) + self.toolbar.setIconSize(QtCore.QSize(22, 22)) + self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + self.printButton = self.toolbar.addAction( + build_icon(u':/general/general_print.png'), 'Print') + self.optionsButton = QtGui.QToolButton(self.toolbar) + self.optionsButton.setText(translate('OpenLP.PrintServiceForm', + 'Options')) + self.optionsButton.setToolButtonStyle( + QtCore.Qt.ToolButtonTextBesideIcon) + self.optionsButton.setIcon(QtGui.QIcon( + build_icon(u':/system/system_configure.png'))) + self.optionsButton.setCheckable(True) + self.toolbar.addWidget(self.optionsButton) + self.closeButton = self.toolbar.addAction( + build_icon(u':/system/system_close.png'), + translate('OpenLP.PrintServiceForm', 'Close')) + self.toolbar.addSeparator() + self.plainCopy = self.toolbar.addAction( + build_icon(u':/system/system_edit_copy.png'), + translate('OpenLP.PrintServiceForm', 'Copy')) + self.htmlCopy = self.toolbar.addAction( + build_icon(u':/system/system_edit_copy.png'), + translate('OpenLP.PrintServiceForm', 'Copy as HTML')) + self.toolbar.addSeparator() + self.zoomInButton = QtGui.QToolButton(self.toolbar) + self.zoomInButton.setIcon(QtGui.QIcon( + build_icon(u':/general/general_zoom_in.png'))) + self.zoomInButton.setToolTip(translate('OpenLP.PrintServiceForm', + 'Zoom In')) + self.zoomInButton.setObjectName(u'zoomInButton') + self.zoomInButton.setIconSize(QtCore.QSize(22, 22)) + self.toolbar.addWidget(self.zoomInButton) + self.zoomOutButton = QtGui.QToolButton(self.toolbar) + self.zoomOutButton.setIcon(QtGui.QIcon( + build_icon(u':/general/general_zoom_out.png'))) + self.zoomOutButton.setToolTip(translate('OpenLP.PrintServiceForm', + 'Zoom Out')) + self.zoomOutButton.setObjectName(u'zoomOutButton') + self.zoomOutButton.setIconSize(QtCore.QSize(22, 22)) + self.toolbar.addWidget(self.zoomOutButton) + self.zoomOriginalButton = QtGui.QToolButton(self.toolbar) + self.zoomOriginalButton.setIcon(QtGui.QIcon( + build_icon(u':/general/general_zoom_original.png'))) + self.zoomOriginalButton.setToolTip(translate('OpenLP.PrintServiceForm', + 'Zoom Original')) + self.zoomOriginalButton.setObjectName(u'zoomOriginalButton') + self.zoomOriginalButton.setIconSize(QtCore.QSize(22, 22)) + self.toolbar.addWidget(self.zoomOriginalButton) + self.zoomComboBox = QtGui.QComboBox(printServiceDialog) + self.zoomComboBox.setObjectName(u'zoomComboBox') + self.toolbar.addWidget(self.zoomComboBox) + self.mainLayout.addWidget(self.toolbar) + self.previewWidget = QtGui.QPrintPreviewWidget(printServiceDialog) + self.mainLayout.addWidget(self.previewWidget) + self.optionsWidget = QtGui.QWidget(printServiceDialog) + self.optionsWidget.hide() + self.optionsWidget.resize(400, 300) + self.optionsWidget.setAutoFillBackground(True) + self.optionsLayout = QtGui.QVBoxLayout(self.optionsWidget) + self.optionsLayout.setContentsMargins(8, 8, 8, 8) + self.titleLabel = QtGui.QLabel(self.optionsWidget) + self.titleLabel.setObjectName(u'titleLabel') + self.titleLabel.setText(u'Title:') + self.optionsLayout.addWidget(self.titleLabel) + self.titleLineEdit = QtGui.QLineEdit(self.optionsWidget) + self.titleLineEdit.setObjectName(u'titleLineEdit') + self.optionsLayout.addWidget(self.titleLineEdit) + self.footerLabel = QtGui.QLabel(self.optionsWidget) + self.footerLabel.setObjectName(u'footerLabel') + self.footerLabel.setText(u'Custom Footer Text:') + self.optionsLayout.addWidget(self.footerLabel) + self.footerTextEdit = SpellTextEdit(self.optionsWidget) + self.footerTextEdit.setObjectName(u'footerTextEdit') + self.optionsLayout.addWidget(self.footerTextEdit) + self.optionsGroupBox = QtGui.QGroupBox( + translate('OpenLP.PrintServiceForm','Other Options')) + self.groupLayout = QtGui.QVBoxLayout() + self.slideTextCheckBox = QtGui.QCheckBox() + self.groupLayout.addWidget(self.slideTextCheckBox) + self.notesCheckBox = QtGui.QCheckBox() + self.groupLayout.addWidget(self.notesCheckBox) + self.metaDataCheckBox = QtGui.QCheckBox() + self.groupLayout.addWidget(self.metaDataCheckBox) + self.groupLayout.addStretch(1) + self.optionsGroupBox.setLayout(self.groupLayout) + self.optionsLayout.addWidget(self.optionsGroupBox) + + self.retranslateUi(printServiceDialog) + QtCore.QMetaObject.connectSlotsByName(printServiceDialog) + QtCore.QObject.connect(self.optionsButton, + QtCore.SIGNAL(u'toggled(bool)'), self.toggleOptions) + + def retranslateUi(self, printServiceDialog): + printServiceDialog.setWindowTitle(UiStrings.PrintServiceOrder) + self.slideTextCheckBox.setText(translate('OpenLP.PrintServiceForm', + 'Include slide text if available')) + self.notesCheckBox.setText(translate('OpenLP.PrintServiceForm', + 'Include service item notes')) + self.metaDataCheckBox.setText(translate('OpenLP.PrintServiceForm', + 'Include play length of media items')) + self.titleLineEdit.setText(translate('OpenLP.PrintServiceForm', + 'Service Order Sheet')) + self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Page]) + self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Width]) + self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.OneHundred]) + self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.SeventyFive]) + self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Fifty]) + self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.TwentyFive]) diff --git a/openlp/core/ui/printserviceform.py b/openlp/core/ui/printserviceform.py new file mode 100644 index 000000000..713e7c27b --- /dev/null +++ b/openlp/core/ui/printserviceform.py @@ -0,0 +1,244 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +import datetime + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import translate +from openlp.core.lib.ui import UiStrings +from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize + +class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): + + def __init__(self, parent, serviceManager): + """ + Constructor + """ + QtGui.QDialog.__init__(self, parent) + self.parent = parent + self.serviceManager = serviceManager + self.printer = QtGui.QPrinter() + self.printDialog = QtGui.QPrintDialog(self.printer, self) + self.document = QtGui.QTextDocument() + self.zoom = 0 + self.setupUi(self) + # Load the settings for the dialog. + settings = QtCore.QSettings() + settings.beginGroup(u'advanced') + self.slideTextCheckBox.setChecked(settings.value( + u'print slide text', QtCore.QVariant(False)).toBool()) + self.metaDataCheckBox.setChecked(settings.value( + u'print file meta data', QtCore.QVariant(False)).toBool()) + self.notesCheckBox.setChecked(settings.value( + u'print notes', QtCore.QVariant(False)).toBool()) + self.zoomComboBox.setCurrentIndex(settings.value( + u'display size', QtCore.QVariant(0)).toInt()[0]) + settings.endGroup() + # Signals + QtCore.QObject.connect(self.printButton, + QtCore.SIGNAL(u'triggered()'), self.printServiceOrder) + QtCore.QObject.connect(self.closeButton, + QtCore.SIGNAL(u'triggered()'), self.accept) + QtCore.QObject.connect(self.zoomOutButton, + QtCore.SIGNAL(u'clicked()'), self.zoomOut) + QtCore.QObject.connect(self.zoomInButton, + QtCore.SIGNAL(u'clicked()'), self.zoomIn) + QtCore.QObject.connect(self.zoomOriginalButton, + QtCore.SIGNAL(u'clicked()'), self.zoomOriginal) + QtCore.QObject.connect(self.previewWidget, + QtCore.SIGNAL(u'paintRequested(QPrinter *)'), self.paintRequested) + QtCore.QObject.connect(self.zoomComboBox, + QtCore.SIGNAL(u'currentIndexChanged(int)'), self.displaySizeChanged) + QtCore.QObject.connect(self.plainCopy, + QtCore.SIGNAL(u'triggered()'), self.copyText) + QtCore.QObject.connect(self.htmlCopy, + QtCore.SIGNAL(u'triggered()'), self.copyHtmlText) + self.updatePreviewText() + + def toggleOptions(self, checked): + self.optionsWidget.setVisible(checked) + if checked: + left = self.optionsButton.pos().x() + top = self.toolbar.height() + self.optionsWidget.move(left, top) + self.titleLineEdit.setFocus() + else: + self.saveOptions() + self.updatePreviewText() + + def updatePreviewText(self): + """ + Creates the html text and updates the html of *self.document*. + """ + text = u'' + if self.titleLineEdit.text(): + text += u'

%s

' % unicode(self.titleLineEdit.text()) + for item in self.serviceManager.serviceItems: + item = item[u'service_item'] + # Add the title of the service item. + text += u'

%s

' % (item.icon, + item.get_display_title()) + # Add slide text of the service item. + if self.slideTextCheckBox.isChecked(): + if item.is_text(): + # Add the text of the service item. + verse = None + for slide in item.get_frames(): + if not verse: + text += u'

' + slide[u'html'] + verse = slide[u'verseTag'] + elif verse != slide[u'verseTag']: + text += u'<\p>

' + slide[u'html'] + verse = slide[u'verseTag'] + else: + text += u'
' + slide[u'html'] + text += u'

' + elif item.is_image(): + # Add the image names of the service item. + text += u'
    ' + for slide in range(len(item.get_frames())): + text += u'
  1. %s

  2. ' % \ + item.get_frame_title(slide) + text += u'
' + if item.foot_text: + # add footer + text += u'

%s

' % item.foot_text + # Add service items' notes. + if self.notesCheckBox.isChecked(): + if item.notes: + text += u'

%s

%s' % (translate( + 'OpenLP.ServiceManager', 'Notes:'), + item.notes.replace(u'\n', u'
')) + # Add play length of media files. + if item.is_media() and self.metaDataCheckBox.isChecked(): + text += u'

%s %s

' % (translate( + 'OpenLP.ServiceManager', u'Playing time:'), + unicode(datetime.timedelta(seconds=item.media_length))) + if self.footerTextEdit.toPlainText(): + text += u'

%s

%s' % (translate('OpenLP.ServiceManager', + u'Custom Service Notes:'), self.footerTextEdit.toPlainText()) + self.document.setHtml(text) + self.previewWidget.updatePreview() + + def paintRequested(self, printer): + """ + Paint the preview of the *self.document*. + + ``printer`` + A *QPrinter* object. + """ + self.document.print_(printer) + + def displaySizeChanged(self, display): + """ + The Zoom Combo box has changed so set up the size. + """ + if display == ZoomSize.Page: + self.previewWidget.fitInView() + elif display == ZoomSize.Width: + self.previewWidget.fitToWidth() + elif display == ZoomSize.OneHundred: + self.previewWidget.fitToWidth() + self.previewWidget.zoomIn(1) + elif display == ZoomSize.SeventyFive: + self.previewWidget.fitToWidth() + self.previewWidget.zoomIn(0.75) + elif display == ZoomSize.Fifty: + self.previewWidget.fitToWidth() + self.previewWidget.zoomIn(0.5) + elif display == ZoomSize.TwentyFive: + self.previewWidget.fitToWidth() + self.previewWidget.zoomIn(0.25) + settings = QtCore.QSettings() + settings.beginGroup(u'advanced') + settings.setValue(u'display size', QtCore.QVariant(display)) + settings.endGroup() + + def copyText(self): + """ + Copies the display text to the clipboard as plain text + """ + self.parent.clipboard.setText(self.document.toPlainText()) + + def copyHtmlText(self): + """ + Copies the display text to the clipboard as Html + """ + self.parent.clipboard.setText(self.document.toHtml()) + + def printServiceOrder(self): + """ + Called, when the *printButton* is clicked. Opens the *printDialog*. + """ + if not self.printDialog.exec_(): + return + # Print the document. + self.document.print_(self.printer) + + def zoomIn(self): + """ + Called when *zoomInButton* is clicked. + """ + self.previewWidget.zoomIn() + self.zoom -= 0.1 + + def zoomOut(self): + """ + Called when *zoomOutButton* is clicked. + """ + self.previewWidget.zoomOut() + self.zoom += 0.1 + + def zoomOriginal(self): + """ + Called when *zoomOutButton* is clicked. + """ + self.previewWidget.zoomIn(1 + self.zoom) + self.zoom = 0 + + def updateTextFormat(self, value): + """ + Called when html copy check box is selected. + """ + if value == QtCore.Qt.Checked: + self.copyTextButton.setText(UiStrings.CopyToHtml) + else: + self.copyTextButton.setText(UiStrings.CopyToText) + + def saveOptions(self): + """ + Save the settings and close the dialog. + """ + # Save the settings for this dialog. + settings = QtCore.QSettings() + settings.beginGroup(u'advanced') + settings.setValue(u'print slide text', + QtCore.QVariant(self.slideTextCheckBox.isChecked())) + settings.setValue(u'print file meta data', + QtCore.QVariant(self.metaDataCheckBox.isChecked())) + settings.setValue(u'print notes', + QtCore.QVariant(self.notesCheckBox.isChecked())) + settings.endGroup() diff --git a/openlp/core/ui/screen.py b/openlp/core/ui/screen.py index 430426fd5..4530cfd3c 100644 --- a/openlp/core/ui/screen.py +++ b/openlp/core/ui/screen.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -71,7 +71,7 @@ class ScreenList(object): """ Set up the current screen dimensions """ - log.debug(u'set_current_display %s', number, ) + log.debug(u'set_current_display %s', number) if number + 1 > self.display_count: self.current = self.screen_list[0] self.override = copy.deepcopy(self.current) @@ -99,4 +99,4 @@ class ScreenList(object): user wants to use the correct screen attributes """ log.debug(u'reset_current_display') - self.set_current_display(self.current_display) \ No newline at end of file + self.set_current_display(self.current_display) diff --git a/openlp/core/ui/serviceitemeditdialog.py b/openlp/core/ui/serviceitemeditdialog.py index f22f3dcf5..f2909eabb 100644 --- a/openlp/core/ui/serviceitemeditdialog.py +++ b/openlp/core/ui/serviceitemeditdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate -from openlp.core.lib.ui import create_save_cancel_button_box, \ +from openlp.core.lib.ui import create_accept_reject_button_box, \ create_delete_push_button, create_up_down_push_button_set class Ui_ServiceItemEditDialog(object): @@ -50,7 +50,7 @@ class Ui_ServiceItemEditDialog(object): self.buttonLayout.addWidget(self.downButton) self.dialogLayout.addLayout(self.buttonLayout, 0, 1) self.dialogLayout.addWidget( - create_save_cancel_button_box(serviceItemEditDialog), 1, 0, 1, 2) + create_accept_reject_button_box(serviceItemEditDialog), 1, 0, 1, 2) self.retranslateUi(serviceItemEditDialog) QtCore.QMetaObject.connectSlotsByName(serviceItemEditDialog) diff --git a/openlp/core/ui/serviceitemeditform.py b/openlp/core/ui/serviceitemeditform.py index 70518f30c..588bdbfd6 100644 --- a/openlp/core/ui/serviceitemeditform.py +++ b/openlp/core/ui/serviceitemeditform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -110,11 +110,12 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog): temp = self.itemList[row] self.itemList.remove(self.itemList[row]) if direction == u'up': - self.itemList.insert(row - 1, temp) + row -= 1 else: - self.itemList.insert(row + 1, temp) + row += 1 + self.itemList.insert(row, temp) self.loadData() - self.listWidget.setCurrentRow(row + 1) + self.listWidget.setCurrentRow(row) def onCurrentRowChanged(self, row): """ diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index bddd150b8..f5a08d8b2 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -23,10 +23,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### - -import os -import logging import cPickle +import logging +import os import zipfile log = logging.getLogger(__name__) @@ -34,10 +33,11 @@ log = logging.getLogger(__name__) from PyQt4 import QtCore, QtGui from openlp.core.lib import OpenLPToolbar, ServiceItem, context_menu_action, \ - Receiver, build_icon, ItemCapabilities, SettingsManager, translate, \ - ThemeLevel -from openlp.core.lib.ui import critical_error_message_box -from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm + Receiver, build_icon, ItemCapabilities, SettingsManager, translate +from openlp.core.lib.theme import ThemeLevel +from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm +from openlp.core.ui.printserviceform import PrintServiceForm from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ split_filename @@ -67,8 +67,8 @@ class ServiceManagerList(QtGui.QTreeWidget): class ServiceManager(QtGui.QWidget): """ - Manages the services. This involves taking text strings from plugins and - adding them to the service. This service can then be zipped up with all + Manages the services. This involves taking text strings from plugins and + adding them to the service. This service can then be zipped up with all the resources used into one OSZ file for use on any OpenLP v2 installation. Also handles the UI tasks of moving things up and down etc. """ @@ -88,6 +88,7 @@ class ServiceManager(QtGui.QWidget): self._fileName = u'' self.serviceNoteForm = ServiceNoteForm(self.mainwindow) self.serviceItemEditForm = ServiceItemEditForm(self.mainwindow) + self.startTimeForm = StartTimeForm(self.mainwindow) # start with the layout self.layout = QtGui.QVBoxLayout(self) self.layout.setSpacing(0) @@ -95,23 +96,18 @@ class ServiceManager(QtGui.QWidget): # Create the top toolbar self.toolbar = OpenLPToolbar(self) self.toolbar.addToolbarButton( - translate('OpenLP.ServiceManager', 'New Service'), - u':/general/general_new.png', - translate('OpenLP.ServiceManager', 'Create a new service'), - self.onNewServiceClicked) + UiStrings.NewService, u':/general/general_new.png', + UiStrings.CreateService, self.onNewServiceClicked) self.toolbar.addToolbarButton( - translate('OpenLP.ServiceManager', 'Open Service'), - u':/general/general_open.png', + UiStrings.OpenService, u':/general/general_open.png', translate('OpenLP.ServiceManager', 'Load an existing service'), self.onLoadServiceClicked) self.toolbar.addToolbarButton( - translate('OpenLP.ServiceManager', 'Save Service'), - u':/general/general_save.png', + UiStrings.SaveService, u':/general/general_save.png', translate('OpenLP.ServiceManager', 'Save this service'), self.saveFile) self.toolbar.addSeparator() - self.themeLabel = QtGui.QLabel(translate('OpenLP.ServiceManager', - 'Theme:'), self) + self.themeLabel = QtGui.QLabel(u'%s:' % UiStrings.Theme, self) self.themeLabel.setMargin(3) self.themeLabel.setObjectName(u'themeLabel') self.toolbar.addToolbarWidget(u'ThemeLabel', self.themeLabel) @@ -270,16 +266,19 @@ class ServiceManager(QtGui.QWidget): self.notesAction = self.menu.addAction( translate('OpenLP.ServiceManager', '&Notes')) self.notesAction.setIcon(build_icon(u':/services/service_notes.png')) + self.timeAction = self.menu.addAction( + translate('OpenLP.ServiceManager', '&Start Time')) + self.timeAction.setIcon(build_icon(u':/media/media_time.png')) self.deleteAction = self.menu.addAction( translate('OpenLP.ServiceManager', '&Delete From Service')) self.deleteAction.setIcon(build_icon(u':/general/general_delete.png')) self.sep1 = self.menu.addAction(u'') self.sep1.setSeparator(True) self.previewAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Preview Verse')) + translate('OpenLP.ServiceManager', 'Show &Preview')) self.previewAction.setIcon(build_icon(u':/general/general_preview.png')) self.liveAction = self.menu.addAction( - translate('OpenLP.ServiceManager', '&Live Verse')) + translate('OpenLP.ServiceManager', 'Show &Live')) self.liveAction.setIcon(build_icon(u':/general/general_live.png')) self.sep2 = self.menu.addAction(u'') self.sep2.setSeparator(True) @@ -391,7 +390,7 @@ class ServiceManager(QtGui.QWidget): return QtGui.QMessageBox.question(self.mainwindow, translate('OpenLP.ServiceManager', 'Modified Service'), translate('OpenLP.ServiceManager', 'The current service has ' - 'been modified. Would you like to save this service?'), + 'been modified. Would you like to save this service?'), QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) @@ -461,11 +460,11 @@ class ServiceManager(QtGui.QWidget): def saveFileAs(self): """ - Get a file name and then call :function:`ServiceManager.saveFile` to + Get a file name and then call :func:`ServiceManager.saveFile` to save the file. """ fileName = unicode(QtGui.QFileDialog.getSaveFileName(self.mainwindow, - translate('OpenLP.ServiceManager', 'Save Service'), + UiStrings.SaveService, SettingsManager.get_last_dir( self.mainwindow.serviceSettingsSection), translate('OpenLP.ServiceManager', 'OpenLP Service Files (*.osz)'))) @@ -563,6 +562,7 @@ class ServiceManager(QtGui.QWidget): self.editAction.setVisible(False) self.maintainAction.setVisible(False) self.notesAction.setVisible(False) + self.timeAction.setVisible(False) if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit)\ and serviceItem[u'service_item'].edit_id: self.editAction.setVisible(True) @@ -571,6 +571,9 @@ class ServiceManager(QtGui.QWidget): self.maintainAction.setVisible(True) if item.parent() is None: self.notesAction.setVisible(True) + if serviceItem[u'service_item']\ + .is_capable(ItemCapabilities.AllowsVarableStartTime): + self.timeAction.setVisible(True) self.themeMenu.menuAction().setVisible(False) if serviceItem[u'service_item'].is_text(): self.themeMenu.menuAction().setVisible(True) @@ -583,6 +586,8 @@ class ServiceManager(QtGui.QWidget): self.onDeleteFromService() if action == self.notesAction: self.onServiceItemNoteForm() + if action == self.timeAction: + self.onStartTimeForm() if action == self.previewAction: self.makePreview() if action == self.liveAction: @@ -597,6 +602,16 @@ class ServiceManager(QtGui.QWidget): self.serviceNoteForm.textEdit.toPlainText() self.repaintServiceList(item, -1) + def onStartTimeForm(self): + item = self.findServiceItem()[0] + self.startTimeForm.item = self.serviceItems[item] + if self.startTimeForm.exec_(): + self.serviceItems[item][u'service_item'].start_time = \ + self.startTimeForm.hourSpinBox.value() * 3600 + \ + self.startTimeForm.minuteSpinBox.value() * 60 + \ + self.startTimeForm.secondSpinBox.value() + self.repaintServiceList(item, -1) + def onServiceItemEditForm(self): item = self.findServiceItem()[0] self.serviceItemEditForm.setServiceItem( @@ -843,6 +858,11 @@ class ServiceManager(QtGui.QWidget): text = frame[u'title'].replace(u'\n', u' ') child.setText(0, text[:40]) child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count)) + if item[u'service_item'] \ + .is_capable(ItemCapabilities.AllowsVarableStartTime): + tip = item[u'service_item'].get_media_time() + if tip: + child.setToolTip(0, tip) if serviceItem == itemcount: if item[u'expanded'] and serviceItemChild == count: self.serviceManagerList.setCurrentItem(child) @@ -1041,8 +1061,8 @@ class ServiceManager(QtGui.QWidget): if self.serviceItems[item][u'service_item']\ .is_capable(ItemCapabilities.AllowsEdit): Receiver.send_message(u'%s_edit' % - self.serviceItems[item][u'service_item'].name.lower(), u'L:%s' % - self.serviceItems[item][u'service_item'].edit_id ) + self.serviceItems[item][u'service_item'].name.lower(), + u'L:%s' % self.serviceItems[item][u'service_item'].edit_id) def findServiceItem(self): """ @@ -1187,41 +1207,5 @@ class ServiceManager(QtGui.QWidget): """ Print a Service Order Sheet. """ - if not self.serviceItems: - critical_error_message_box( - message=translate('OpenLP.ServiceManager', - 'There is no service item in this service.')) - return - printDialog = QtGui.QPrintDialog() - if not printDialog.exec_(): - return - text = u'

%s

' % translate('OpenLP.ServiceManager', - 'Service Order Sheet') - for item in self.serviceItems: - item = item[u'service_item'] - # add the title - text += u'

%s

' % (item.icon, - item.get_display_title()) - if not QtCore.QSettings().value(u'advanced' + - u'/detailed service print', QtCore.QVariant(True)).toBool(): - continue - if item.is_text(): - # Add the text of the service item. - for slide in item.get_frames(): - text += u'

' + slide[u'text'] + u'

' - elif item.is_image(): - # Add the image names of the service item. - text += u'
    ' - for slide in range(len(item.get_frames())): - text += u'
  1. %s

  2. ' % item.get_frame_title(slide) - text += u'
' - if item.foot_text: - # add footer - text += u'

%s

' % item.foot_text - if item.notes: - # add notes - text += u'

%s %s

' % (translate( - 'OpenLP.ServiceManager', 'Notes:'), item.notes) - serviceDocument = QtGui.QTextDocument() - serviceDocument.setHtml(text) - serviceDocument.print_(printDialog.printer()) + settingDialog = PrintServiceForm(self.mainwindow, self) + settingDialog.exec_() diff --git a/openlp/core/ui/servicenoteform.py b/openlp/core/ui/servicenoteform.py index 473cc1685..200e12818 100644 --- a/openlp/core/ui/servicenoteform.py +++ b/openlp/core/ui/servicenoteform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import create_accept_reject_button_box class ServiceNoteForm(QtGui.QDialog): """ @@ -48,9 +48,9 @@ class ServiceNoteForm(QtGui.QDialog): self.textEdit = QtGui.QTextEdit(self) self.textEdit.setObjectName(u'textEdit') self.dialogLayout.addWidget(self.textEdit) - self.dialogLayout.addWidget(create_save_cancel_button_box(self)) + self.dialogLayout.addWidget(create_accept_reject_button_box(self)) QtCore.QMetaObject.connectSlotsByName(self) def retranslateUi(self): self.setWindowTitle( - translate('OpenLP.ServiceNoteForm', 'Service Item Notes')) + translate('OpenLP.ServiceNoteForm', 'Service Item Notes')) diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py index 61c73961c..af8ba84ab 100644 --- a/openlp/core/ui/settingsdialog.py +++ b/openlp/core/ui/settingsdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,6 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, build_icon +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_SettingsDialog(object): def setupUi(self, settingsDialog): @@ -35,21 +36,13 @@ class Ui_SettingsDialog(object): settingsDialog.setWindowIcon( build_icon(u':/system/system_settings.png')) self.settingsLayout = QtGui.QVBoxLayout(settingsDialog) - margins = self.settingsLayout.contentsMargins() self.settingsLayout.setObjectName(u'settingsLayout') self.settingsTabWidget = QtGui.QTabWidget(settingsDialog) self.settingsTabWidget.setObjectName(u'settingsTabWidget') self.settingsLayout.addWidget(self.settingsTabWidget) - self.buttonBox = QtGui.QDialogButtonBox(settingsDialog) - self.buttonBox.setStandardButtons( - QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName(u'buttonBox') + self.buttonBox = create_accept_reject_button_box(settingsDialog, True) self.settingsLayout.addWidget(self.buttonBox) self.retranslateUi(settingsDialog) - QtCore.QObject.connect(self.buttonBox, - QtCore.SIGNAL(u'accepted()'), settingsDialog.accept) - QtCore.QObject.connect(self.buttonBox, - QtCore.SIGNAL(u'rejected()'), settingsDialog.reject) QtCore.QMetaObject.connectSlotsByName(settingsDialog) def retranslateUi(self, settingsDialog): diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index afea928b6..872b37586 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -31,7 +31,7 @@ import logging from PyQt4 import QtGui from openlp.core.lib import Receiver -from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab, DisplayTagTab +from openlp.core.ui import AdvancedTab, GeneralTab, ThemesTab from settingsdialog import Ui_SettingsDialog log = logging.getLogger(__name__) @@ -47,17 +47,14 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): QtGui.QDialog.__init__(self, parent) self.setupUi(self) # General tab - self.generalTab = GeneralTab(screens) - self.addTab(u'General', self.generalTab) + generalTab = GeneralTab(screens) + self.addTab(u'General', generalTab) # Themes tab - self.themesTab = ThemesTab(mainWindow) - self.addTab(u'Themes', self.themesTab) + themesTab = ThemesTab(mainWindow) + self.addTab(u'Themes', themesTab) # Advanced tab - self.advancedTab = AdvancedTab() - self.addTab(u'Advanced', self.advancedTab) - # Edit Display Tags tab - self.displayTagTab = DisplayTagTab() - self.addTab(u'Display Tags', self.displayTagTab) + advancedTab = AdvancedTab() + self.addTab(u'Advanced', advancedTab) def addTab(self, name, tab): """ @@ -71,9 +68,9 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog): Add a tab to the form at a specific location """ log.debug(u'Inserting %s tab' % tab.tabTitle) - # 15 : There are 4 tables currently and locations starts at -10 + # 14 : There are 3 tables currently and locations starts at -10 self.settingsTabWidget.insertTab( - location + 15, tab, tab.tabTitleVisible) + location + 14, tab, tab.tabTitleVisible) def removeTab(self, tab): """ diff --git a/openlp/core/ui/shortcutlistdialog.py b/openlp/core/ui/shortcutlistdialog.py index 3f41d377a..b4673f410 100644 --- a/openlp/core/ui/shortcutlistdialog.py +++ b/openlp/core/ui/shortcutlistdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -36,7 +36,7 @@ class Ui_ShortcutListDialog(object): self.treeWidget = QtGui.QTreeWidget(shortcutListDialog) self.treeWidget.setAlternatingRowColors(True) self.treeWidget.setObjectName(u'treeWidget') - self.treeWidget.setColumnCount(2) + self.treeWidget.setColumnCount(3) self.dialogLayout.addWidget(self.treeWidget) self.defaultButton = QtGui.QRadioButton(shortcutListDialog) self.defaultButton.setChecked(True) @@ -78,7 +78,8 @@ class Ui_ShortcutListDialog(object): translate('OpenLP.ShortcutListDialog', 'Customize Shortcuts')) self.treeWidget.setHeaderLabels([ translate('OpenLP.ShortcutListDialog', 'Action'), - translate('OpenLP.ShortcutListDialog', 'Shortcut')]) + translate('OpenLP.ShortcutListDialog', 'Shortcut'), + translate('OpenLP.ShortcutListDialog', 'Alternate')]) self.defaultButton.setText( translate('OpenLP.ShortcutListDialog', 'Default: %s')) self.customButton.setText( diff --git a/openlp/core/ui/shortcutlistform.py b/openlp/core/ui/shortcutlistform.py index 9d2b31853..4f770045c 100644 --- a/openlp/core/ui/shortcutlistform.py +++ b/openlp/core/ui/shortcutlistform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -95,8 +95,14 @@ class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog): item = QtGui.QTreeWidgetItem([category.name]) for action in category.actions: actionText = REMOVE_AMPERSAND.sub('', unicode(action.text())) - shortcutText = action.shortcut().toString() - actionItem = QtGui.QTreeWidgetItem([actionText, shortcutText]) + if (len(action.shortcuts()) == 2): + shortcutText = action.shortcuts()[0].toString() + alternateText = action.shortcuts()[1].toString() + else: + shortcutText = action.shortcut().toString() + alternateText = u'' + actionItem = QtGui.QTreeWidgetItem( + [actionText, shortcutText, alternateText]) actionItem.setIcon(0, action.icon()) item.addChild(actionItem) item.setExpanded(True) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index bf0453e05..8d612676b 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,7 +32,7 @@ from PyQt4.phonon import Phonon from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \ ItemCapabilities, translate -from openlp.core.lib.ui import shortcut_action +from openlp.core.lib.ui import UiStrings, shortcut_action from openlp.core.ui import HideMode, MainDisplay log = logging.getLogger(__name__) @@ -78,7 +78,7 @@ class SlideController(QtGui.QWidget): self.selectedRow = 0 self.serviceItem = None self.alertTab = None - self.panel = QtGui.QWidget(parent.ControlSplitter) + self.panel = QtGui.QWidget(parent.controlSplitter) self.slideList = {} # Layout for holding panel self.panelLayout = QtGui.QVBoxLayout(self.panel) @@ -87,12 +87,11 @@ class SlideController(QtGui.QWidget): # Type label for the top of the slide controller self.typeLabel = QtGui.QLabel(self.panel) if self.isLive: - self.typeLabel.setText(translate('OpenLP.SlideController', 'Live')) + self.typeLabel.setText(UiStrings.Live) self.split = 1 self.typePrefix = u'live' else: - self.typeLabel.setText(translate('OpenLP.SlideController', - 'Preview')) + self.typeLabel.setText(UiStrings.Preview) self.split = 0 self.typePrefix = u'preview' self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;') @@ -179,10 +178,12 @@ class SlideController(QtGui.QWidget): QtCore.SIGNAL(u'triggered(bool)'), self.onHideDisplay) self.toolbar.addToolbarSeparator(u'Loop Separator') self.toolbar.addToolbarButton( + # Does not need translating - control string. u'Start Loop', u':/media/media_time.png', translate('OpenLP.SlideController', 'Start continuous loop'), self.onStartLoop) self.toolbar.addToolbarButton( + # Does not need translating - control string. u'Stop Loop', u':/media/media_stop.png', translate('OpenLP.SlideController', 'Stop continuous loop'), self.onStopLoop) @@ -190,18 +191,19 @@ class SlideController(QtGui.QWidget): self.delaySpinBox.setMinimum(1) self.delaySpinBox.setMaximum(180) self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox) - self.delaySpinBox.setSuffix(translate('OpenLP.SlideController', - 's')) + self.delaySpinBox.setSuffix(UiStrings.S) self.delaySpinBox.setToolTip(translate('OpenLP.SlideController', 'Delay between slides in seconds')) else: self.toolbar.addToolbarSeparator(u'Close Separator') self.toolbar.addToolbarButton( + # Does not need translating - control string. u'Go Live', u':/general/general_live.png', translate('OpenLP.SlideController', 'Move to live'), self.onGoLive) self.toolbar.addToolbarSeparator(u'Close Separator') self.toolbar.addToolbarButton( + # Does not need translating - control string. u'Edit Song', u':/general/general_edit.png', translate('OpenLP.SlideController', 'Edit and reload song preview'), @@ -377,7 +379,7 @@ class SlideController(QtGui.QWidget): self.previousItem.setShortcuts([QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp]) self.previousItem.setShortcutContext( QtCore.Qt.WidgetWithChildrenShortcut) - actionList.add_action(self.nextItem, u'Live') + actionList.add_action(self.previousItem, u'Live') self.nextItem.setShortcuts([QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown]) self.nextItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) actionList.add_action(self.nextItem, u'Live') @@ -455,7 +457,7 @@ class SlideController(QtGui.QWidget): self.previewListWidget.resizeRowsToContents() else: # Sort out image heights. - width = self.parent.ControlSplitter.sizes()[self.split] + width = self.parent.controlSplitter.sizes()[self.split] for framenumber in range(len(self.serviceItem.get_frames())): self.previewListWidget.setRowHeight( framenumber, width / self.ratio) @@ -584,7 +586,7 @@ class SlideController(QtGui.QWidget): Receiver.send_message(u'%s_start' % serviceItem.name.lower(), [serviceItem, self.isLive, blanked, slideno]) self.slideList = {} - width = self.parent.ControlSplitter.sizes()[self.split] + width = self.parent.controlSplitter.sizes()[self.split] self.serviceItem = serviceItem self.previewListWidget.clear() self.previewListWidget.setRowCount(0) @@ -600,14 +602,15 @@ class SlideController(QtGui.QWidget): slideHeight = 0 if self.serviceItem.is_text(): if frame[u'verseTag']: - bits = frame[u'verseTag'].split(u':') - tag = u'%s\n%s' % (bits[0][0], bits[1][0:] ) - tag1 = u'%s%s' % (bits[0][0], bits[1][0:] ) - row = tag + # These tags are already translated. + verse_def = frame[u'verseTag'] + verse_def = u'%s%s' % (verse_def[0].upper(), verse_def[1:]) + two_line_def = u'%s\n%s' % (verse_def[0], verse_def[1:]) + row = two_line_def if self.isLive: - if tag1 not in self.slideList: - self.slideList[tag1] = framenumber - self.songMenu.menu().addAction(tag1, + if verse_def not in self.slideList: + self.slideList[verse_def] = framenumber + self.songMenu.menu().addAction(verse_def, self.onSongBarHandler) else: row += 1 @@ -874,7 +877,8 @@ class SlideController(QtGui.QWidget): using *Blank to Theme*. """ log.debug(u'updatePreview %s ' % self.screens.current[u'primary']) - if not self.screens.current[u'primary']: + if not self.screens.current[u'primary'] and self.serviceItem and \ + self.serviceItem.is_capable(ItemCapabilities.ProvidesOwnDisplay): # Grab now, but try again in a couple of seconds if slide change # is slow QtCore.QTimer.singleShot(0.5, self.grabMainDisplay) diff --git a/openlp/core/ui/splashscreen.py b/openlp/core/ui/splashscreen.py index 8c2364ec2..88c6f09f9 100644 --- a/openlp/core/ui/splashscreen.py +++ b/openlp/core/ui/splashscreen.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/ui/starttimedialog.py b/openlp/core/ui/starttimedialog.py new file mode 100644 index 000000000..14ef84aac --- /dev/null +++ b/openlp/core/ui/starttimedialog.py @@ -0,0 +1,70 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import translate +from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box + +class Ui_StartTimeDialog(object): + def setupUi(self, StartTimeDialog): + StartTimeDialog.setObjectName(u'StartTimeDialog') + StartTimeDialog.resize(300, 10) + self.dialogLayout = QtGui.QGridLayout(StartTimeDialog) + self.dialogLayout.setObjectName(u'dialogLayout') + self.hourLabel = QtGui.QLabel(StartTimeDialog) + self.hourLabel.setObjectName("hourLabel") + self.dialogLayout.addWidget(self.hourLabel, 0, 0, 1, 1) + self.hourSpinBox = QtGui.QSpinBox(StartTimeDialog) + self.hourSpinBox.setObjectName("hourSpinBox") + self.dialogLayout.addWidget(self.hourSpinBox, 0, 1, 1, 1) + self.minuteLabel = QtGui.QLabel(StartTimeDialog) + self.minuteLabel.setObjectName("minuteLabel") + self.dialogLayout.addWidget(self.minuteLabel, 1, 0, 1, 1) + self.minuteSpinBox = QtGui.QSpinBox(StartTimeDialog) + self.minuteSpinBox.setObjectName("minuteSpinBox") + self.dialogLayout.addWidget(self.minuteSpinBox, 1, 1, 1, 1) + self.secondLabel = QtGui.QLabel(StartTimeDialog) + self.secondLabel.setObjectName("secondLabel") + self.dialogLayout.addWidget(self.secondLabel, 2, 0, 1, 1) + self.secondSpinBox = QtGui.QSpinBox(StartTimeDialog) + self.secondSpinBox.setObjectName("secondSpinBox") + self.dialogLayout.addWidget(self.secondSpinBox, 2, 1, 1, 1) + self.buttonBox = create_accept_reject_button_box(StartTimeDialog, True) + self.dialogLayout.addWidget(self.buttonBox, 4, 0, 1, 2) + self.retranslateUi(StartTimeDialog) + self.setMaximumHeight(self.sizeHint().height()) + QtCore.QMetaObject.connectSlotsByName(StartTimeDialog) + + def retranslateUi(self, StartTimeDialog): + self.setWindowTitle(translate('OpenLP.StartTimeForm', + 'Item Start Time')) + self.hourLabel.setText(translate('OpenLP.StartTimeForm', 'Hours:')) + self.hourSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 'h')) + self.minuteSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 'm')) + self.secondSpinBox.setSuffix(UiStrings.S) + self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:')) + self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:')) diff --git a/openlp/core/ui/starttimeform.py b/openlp/core/ui/starttimeform.py new file mode 100644 index 000000000..01800602f --- /dev/null +++ b/openlp/core/ui/starttimeform.py @@ -0,0 +1,52 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +from PyQt4 import QtGui + +from starttimedialog import Ui_StartTimeDialog + +class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog): + """ + The exception dialog + """ + def __init__(self, parent): + QtGui.QDialog.__init__(self, parent) + self.setupUi(self) + + def exec_(self): + """ + Run the Dialog with correct heading. + """ + seconds = self.item[u'service_item'].start_time + hours = seconds / 3600 + seconds -= 3600 * hours + minutes = seconds / 60 + seconds -= 60 * minutes + self.hourSpinBox.setValue(hours) + self.minuteSpinBox.setValue(minutes) + self.secondSpinBox.setValue(seconds) + return QtGui.QDialog.exec_(self) + diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 018df7597..cc490bf9b 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,9 +29,9 @@ import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import translate, BackgroundType, BackgroundGradientType, \ - Receiver -from openlp.core.lib.ui import critical_error_message_box +from openlp.core.lib import Receiver, translate +from openlp.core.lib.theme import BackgroundType, BackgroundGradientType +from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.utils import get_images_filter from themewizard import Ui_ThemeWizard @@ -204,7 +204,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): # Do not trigger on start up if self.currentPage != self.welcomePage: self.updateTheme() - frame = self.thememanager.generateImage(self.theme, True) + self.thememanager.generateImage(self.theme, True) def updateLinesText(self, lines): """ @@ -301,7 +301,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): 'Edit Theme - %s')) % self.theme.theme_name) self.next() else: - self.setWindowTitle(translate('OpenLP.ThemeWizard', 'New Theme')) + self.setWindowTitle(UiStrings.NewTheme) return QtGui.QWizard.exec_(self) def initializePage(self, id): @@ -483,8 +483,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): Background Image button pushed. """ images_filter = get_images_filter() - images_filter = '%s;;%s (*.*) (*)' % (images_filter, - translate('OpenLP.ThemeForm', 'All Files')) + images_filter = u'%s;;%s (*.*) (*)' % ( + images_filter, UiStrings.AllFiles) filename = QtGui.QFileDialog.getOpenFileName(self, translate('OpenLP.ThemeForm', 'Select Image'), u'', images_filter) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index e0dbf789a..0e04d7b46 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,10 +32,12 @@ import logging from xml.etree.ElementTree import ElementTree, XML from PyQt4 import QtCore, QtGui -from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \ - build_icon, Receiver, SettingsManager, translate, check_item_selected, \ - BackgroundType, BackgroundGradientType, check_directory_exists -from openlp.core.lib.ui import critical_error_message_box +from openlp.core.lib import OpenLPToolbar, get_text_file_string, build_icon, \ + Receiver, SettingsManager, translate, check_item_selected, \ + check_directory_exists +from openlp.core.lib.theme import ThemeXML, BackgroundType, VerticalType, \ + BackgroundGradientType +from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.theme import Theme from openlp.core.ui import FileRenameForm, ThemeForm from openlp.core.utils import AppLocation, delete_file, file_is_unicode, \ @@ -61,8 +63,7 @@ class ThemeManager(QtGui.QWidget): self.layout.setMargin(0) self.layout.setObjectName(u'layout') self.toolbar = OpenLPToolbar(self) - self.toolbar.addToolbarButton( - translate('OpenLP.ThemeManager', 'New Theme'), + self.toolbar.addToolbarButton(UiStrings.NewTheme, u':/themes/theme_new.png', translate('OpenLP.ThemeManager', 'Create a new theme.'), self.onAddTheme) @@ -265,7 +266,7 @@ class ThemeManager(QtGui.QWidget): oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) self.fileRenameForm.fileNameEdit.setText(oldThemeName) if self.fileRenameForm.exec_(): - newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) + newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) if self.checkIfThemeExists(newThemeName): oldThemeData = self.getThemeData(oldThemeName) self.cloneThemeData(oldThemeData, newThemeName) @@ -283,7 +284,7 @@ class ThemeManager(QtGui.QWidget): oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString()) self.fileRenameForm.fileNameEdit.setText(oldThemeName) if self.fileRenameForm.exec_(True): - newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) + newThemeName = unicode(self.fileRenameForm.fileNameEdit.text()) if self.checkIfThemeExists(newThemeName): themeData = self.getThemeData(oldThemeName) self.cloneThemeData(themeData, newThemeName) @@ -313,7 +314,6 @@ class ThemeManager(QtGui.QWidget): translate('OpenLP.ThemeManager', 'You must select a theme to edit.')): item = self.themeListWidget.currentItem() - themeName = unicode(item.text()) theme = self.getThemeData( unicode(item.data(QtCore.Qt.UserRole).toString())) if theme.background_type == u'image': @@ -334,9 +334,8 @@ class ThemeManager(QtGui.QWidget): row = self.themeListWidget.row(item) self.themeListWidget.takeItem(row) self.deleteTheme(theme) - # As we do not reload the themes, push out the change - # Reaload the list as the internal lists and events need - # to be triggered + # As we do not reload the themes, push out the change. Reload the + # list as the internal lists and events need to be triggered. self._pushThemes() def deleteTheme(self, theme): @@ -400,14 +399,14 @@ class ThemeManager(QtGui.QWidget): def onImportTheme(self): """ Opens a file dialog to select the theme file(s) to import before - attempting to extract OpenLP themes from those files. This process + attempting to extract OpenLP themes from those files. This process will load both OpenLP version 1 and version 2 themes. """ files = QtGui.QFileDialog.getOpenFileNames(self, translate('OpenLP.ThemeManager', 'Select Theme Import File'), SettingsManager.get_last_dir(self.settingsSection), - translate('OpenLP.ThemeManager', 'Theme v1 (*.theme);;' - 'Theme v2 (*.otz);;All Files (*.*)')) + unicode(translate('OpenLP.ThemeManager', + 'OpenLP Themes (*.theme *.otz)'))) log.info(u'New Themes %s', unicode(files)) if files: for file in files: @@ -530,6 +529,18 @@ class ThemeManager(QtGui.QWidget): else: outfile = open(fullpath, u'wb') outfile.write(zip.read(file)) + except (IOError, NameError): + critical_error_message_box( + translate('OpenLP.ThemeManager', 'Validation Error'), + translate('OpenLP.ThemeManager', 'File is not a valid theme.')) + log.exception(u'Importing theme from zip failed %s' % filename) + finally: + # Close the files, to be able to continue creating the theme. + if zip: + zip.close() + if outfile: + outfile.close() + # As all files are closed, we can create the Theme. if filexml: theme = self._createThemeFromXml(filexml, self.path) self.generateAndSaveImage(dir, themename, theme) @@ -540,17 +551,6 @@ class ThemeManager(QtGui.QWidget): 'File is not a valid theme.')) log.exception(u'Theme file does not contain XML data %s' % filename) - except (IOError, NameError): - critical_error_message_box( - translate('OpenLP.ThemeManager', 'Validation Error'), - translate('OpenLP.ThemeManager', - 'File is not a valid theme.')) - log.exception(u'Importing theme from zip failed %s' % filename) - finally: - if zip: - zip.close() - if outfile: - outfile.close() def checkIfThemeExists(self, themeName): """ @@ -763,11 +763,11 @@ class ThemeManager(QtGui.QWidget): newtheme.font_main_outline = True newtheme.font_main_outline_color = \ unicode(theme.OutlineColor.name()) - vAlignCorrection = 0 + vAlignCorrection = VerticalType.Top if theme.VerticalAlign == 2: - vAlignCorrection = 1 + vAlignCorrection = VerticalType.Middle elif theme.VerticalAlign == 1: - vAlignCorrection = 2 + vAlignCorrection = VerticalType.Bottom newtheme.display_horizontal_align = theme.HorizontalAlign newtheme.display_vertical_align = vAlignCorrection return newtheme.extract_xml() diff --git a/openlp/core/ui/themestab.py b/openlp/core/ui/themestab.py index 441b95155..c7442744f 100644 --- a/openlp/core/ui/themestab.py +++ b/openlp/core/ui/themestab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,7 +26,9 @@ from PyQt4 import QtCore, QtGui -from openlp.core.lib import SettingsTab, Receiver, ThemeLevel, translate +from openlp.core.lib import SettingsTab, Receiver, translate +from openlp.core.lib.theme import ThemeLevel +from openlp.core.lib.ui import UiStrings class ThemesTab(SettingsTab): """ @@ -98,7 +100,7 @@ class ThemesTab(SettingsTab): QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList) def retranslateUi(self): - self.tabTitleVisible = translate('OpenLP.ThemesTab', 'Themes') + self.tabTitleVisible = UiStrings.Themes self.GlobalGroupBox.setTitle( translate('OpenLP.ThemesTab', 'Global Theme')) self.LevelGroupBox.setTitle( @@ -198,7 +200,7 @@ class ThemesTab(SettingsTab): """ Utility method to update the global theme preview image. """ - image = self.parent.ThemeManagerContents.getPreviewImage( + image = self.parent.themeManagerContents.getPreviewImage( self.global_theme) preview = QtGui.QPixmap(unicode(image)) if not preview.isNull(): diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index 49522df70..20cca69c6 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,9 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, build_icon -from openlp.core.lib.ui import add_welcome_page +from openlp.core.lib.theme import HorizontalType, BackgroundType, \ + BackgroundGradientType +from openlp.core.lib.ui import UiStrings, add_welcome_page, create_valign_combo class Ui_ThemeWizard(object): def setupUi(self, themeWizard): @@ -242,12 +244,8 @@ class Ui_ThemeWizard(object): self.horizontalComboBox.setObjectName(u'HorizontalComboBox') self.alignmentLayout.addRow(self.horizontalLabel, self.horizontalComboBox) - self.verticalLabel = QtGui.QLabel(self.alignmentPage) - self.verticalLabel.setObjectName(u'VerticalLabel') - self.verticalComboBox = QtGui.QComboBox(self.alignmentPage) - self.verticalComboBox.addItems([u'', u'', u'']) - self.verticalComboBox.setObjectName(u'VerticalComboBox') - self.alignmentLayout.addRow(self.verticalLabel, self.verticalComboBox) + create_valign_combo(themeWizard, self.alignmentPage, + self.alignmentLayout) self.transitionsLabel = QtGui.QLabel(self.alignmentPage) self.transitionsLabel.setObjectName(u'TransitionsLabel') self.transitionsCheckBox = QtGui.QCheckBox(self.alignmentPage) @@ -421,12 +419,12 @@ class Ui_ThemeWizard(object): 'according to the parameters below.')) self.backgroundLabel.setText( translate('OpenLP.ThemeWizard', 'Background type:')) - self.backgroundComboBox.setItemText(0, + self.backgroundComboBox.setItemText(BackgroundType.Solid, translate('OpenLP.ThemeWizard', 'Solid Color')) - self.backgroundComboBox.setItemText(1, + self.backgroundComboBox.setItemText(BackgroundType.Gradient, translate('OpenLP.ThemeWizard', 'Gradient')) - self.backgroundComboBox.setItemText(2, - translate('OpenLP.ThemeWizard', 'Image')) + self.backgroundComboBox.setItemText( + BackgroundType.Image, UiStrings.Image) self.colorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.gradientStartLabel.setText( translate(u'OpenLP.ThemeWizard', 'Starting color:')) @@ -434,39 +432,37 @@ class Ui_ThemeWizard(object): translate(u'OpenLP.ThemeWizard', 'Ending color:')) self.gradientTypeLabel.setText( translate('OpenLP.ThemeWizard', 'Gradient:')) - self.gradientComboBox.setItemText(0, + self.gradientComboBox.setItemText(BackgroundGradientType.Horizontal, translate('OpenLP.ThemeWizard', 'Horizontal')) - self.gradientComboBox.setItemText(1, + self.gradientComboBox.setItemText(BackgroundGradientType.Vertical, translate('OpenLP.ThemeWizard', 'Vertical')) - self.gradientComboBox.setItemText(2, + self.gradientComboBox.setItemText(BackgroundGradientType.Circular, translate('OpenLP.ThemeWizard', 'Circular')) - self.gradientComboBox.setItemText(3, + self.gradientComboBox.setItemText(BackgroundGradientType.LeftTop, translate('OpenLP.ThemeWizard', 'Top Left - Bottom Right')) - self.gradientComboBox.setItemText(4, + self.gradientComboBox.setItemText(BackgroundGradientType.LeftBottom, translate('OpenLP.ThemeWizard', 'Bottom Left - Top Right')) - self.imageLabel.setText(translate('OpenLP.ThemeWizard', 'Image:')) + self.imageLabel.setText(u'%s:' % UiStrings.Image) self.mainAreaPage.setTitle( translate('OpenLP.ThemeWizard', 'Main Area Font Details')) self.mainAreaPage.setSubTitle( translate('OpenLP.ThemeWizard', 'Define the font and display ' 'characteristics for the Display text')) - self.mainFontLabel.setText( - translate('OpenLP.ThemeWizard', 'Font:')) + self.mainFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:')) self.mainColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.mainSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.mainSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.mainSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.lineSpacingLabel.setText( translate('OpenLP.ThemeWizard', 'Line Spacing:')) - self.lineSpacingSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.lineSpacingSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.outlineCheckBox.setText( translate('OpenLP.ThemeWizard', '&Outline:')) self.outlineSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.outlineSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.outlineSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.shadowCheckBox.setText(translate('OpenLP.ThemeWizard', '&Shadow:')) self.shadowSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.shadowSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) - self.mainBoldCheckBox.setText( - translate('OpenLP.ThemeWizard', 'Bold')) + self.shadowSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) + self.mainBoldCheckBox.setText(translate('OpenLP.ThemeWizard', 'Bold')) self.mainItalicsCheckBox.setText( translate('OpenLP.ThemeWizard', 'Italic')) self.footerAreaPage.setTitle( @@ -477,7 +473,7 @@ class Ui_ThemeWizard(object): self.footerFontLabel.setText(translate('OpenLP.ThemeWizard', 'Font:')) self.footerColorLabel.setText(translate('OpenLP.ThemeWizard', 'Color:')) self.footerSizeLabel.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.footerSizeSpinBox.setSuffix(translate('OpenLP.ThemeWizard', 'pt')) + self.footerSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.alignmentPage.setTitle( translate('OpenLP.ThemeWizard', 'Text Formatting Details')) self.alignmentPage.setSubTitle( @@ -485,20 +481,12 @@ class Ui_ThemeWizard(object): 'formatting information to be defined')) self.horizontalLabel.setText( translate('OpenLP.ThemeWizard', 'Horizontal Align:')) - self.horizontalComboBox.setItemText(0, + self.horizontalComboBox.setItemText(HorizontalType.Left, translate('OpenLP.ThemeWizard', 'Left')) - self.horizontalComboBox.setItemText(1, + self.horizontalComboBox.setItemText(HorizontalType.Right, translate('OpenLP.ThemeWizard', 'Right')) - self.horizontalComboBox.setItemText(2, + self.horizontalComboBox.setItemText(HorizontalType.Center, translate('OpenLP.ThemeWizard', 'Center')) - self.verticalLabel.setText( - translate('OpenLP.ThemeWizard', 'Vertical Align:')) - self.verticalComboBox.setItemText(0, - translate('OpenLP.ThemeWizard', 'Top')) - self.verticalComboBox.setItemText(1, - translate('OpenLP.ThemeWizard', 'Middle')) - self.verticalComboBox.setItemText(2, - translate('OpenLP.ThemeWizard', 'Bottom')) self.transitionsLabel.setText( translate('OpenLP.ThemeWizard', 'Transitions:')) self.areaPositionPage.setTitle( diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index 2fa448db8..0b275733e 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,14 +27,55 @@ The :mod:``wizard`` module provides generic wizard tools for OpenLP. """ import logging +import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import build_icon, Receiver -from openlp.core.lib.ui import add_welcome_page +from openlp.core.lib import build_icon, Receiver, SettingsManager, translate +from openlp.core.lib.ui import UiStrings, add_welcome_page log = logging.getLogger(__name__) +class WizardStrings(object): + """ + Provide standard strings for wizards to use. + """ + # Applications/Formats we import from or export to. These get used in + # multiple places but do not need translating unless you find evidence of + # the writers translating their own product name. + CCLI = u'CCLI/SongSelect' + CSV = u'CSV' + EW = u'EasyWorship' + ES = u'EasiSlides' + FP = u'Foilpresenter' + OL = u'OpenLyrics' + OS = u'OpenSong' + OSIS = u'OSIS' + SB = u'SongBeamer' + SoF = u'Songs of Fellowship' + SSP = u'SongShow Plus' + WoW = u'Words of Worship' + # These strings should need a good reason to be retranslated elsewhere. + FinishedImport = translate('OpenLP.Ui', 'Finished import.') + FormatLabel = translate('OpenLP.Ui', 'Format:') + HeaderStyle = u'%s' + Importing = translate('OpenLP.Ui', 'Importing') + ImportingType = unicode(translate('OpenLP.Ui', 'Importing "%s"...')) + ImportSelect = translate('OpenLP.Ui', 'Select Import Source') + ImportSelectLong = unicode(translate('OpenLP.Ui', + 'Select the import format and the location to import from.')) + NoSqlite = translate('OpenLP.Ui', 'The openlp.org 1.x importer has been ' + 'disabled due to a missing Python module. If you want to use this ' + 'importer, you will need to install the "python-sqlite" ' + 'module.') + OpenTypeFile = unicode(translate('OpenLP.Ui', 'Open %s File')) + PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%')) + Ready = translate('OpenLP.Ui', 'Ready.') + StartingImport = translate('OpenLP.Ui', 'Starting import...') + YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify at ' + 'least one %s file to import from.', 'A file type e.g. OpenSong')) + + class OpenLPWizard(QtGui.QWizard): """ Generic OpenLP wizard to provide generic functionality and a unified look @@ -42,6 +83,7 @@ class OpenLPWizard(QtGui.QWizard): """ def __init__(self, parent, plugin, name, image): QtGui.QWizard.__init__(self, parent) + self.plugin = plugin self.setObjectName(name) self.openIcon = build_icon(u':/general/general_open.png') self.deleteIcon = build_icon(u':/general/general_delete.png') @@ -49,7 +91,6 @@ class OpenLPWizard(QtGui.QWizard): self.cancelButton = self.button(QtGui.QWizard.CancelButton) self.setupUi(image) self.registerFields() - self.plugin = plugin self.customInit() self.customSignals() QtCore.QObject.connect(self, QtCore.SIGNAL(u'currentIdChanged(int)'), @@ -70,6 +111,12 @@ class OpenLPWizard(QtGui.QWizard): self.retranslateUi() QtCore.QMetaObject.connectSlotsByName(self) + def registerFields(self): + """ + Hook method for wizards to register any fields they need. + """ + pass + def addProgressPage(self): """ Add the progress page for the wizard. This page informs the user how @@ -146,3 +193,30 @@ class OpenLPWizard(QtGui.QWizard): self.finishButton.setVisible(True) self.cancelButton.setVisible(False) Receiver.send_message(u'openlp_process_events') + + def getFileName(self, title, editbox, filters=u''): + """ + Opens a QFileDialog and saves the filename to the given editbox. + + ``title`` + The title of the dialog (unicode). + + ``editbox`` + A editbox (QLineEdit). + + ``filters`` + The file extension filters. It should contain the file description + as well as the file extension. For example:: + + u'OpenLP 2.0 Databases (*.sqlite)' + """ + if filters: + filters += u';;' + filters += u'%s (*)' % UiStrings.AllFiles + filename = QtGui.QFileDialog.getOpenFileName(self, title, + os.path.dirname(SettingsManager.get_last_dir( + self.plugin.settingsSection, 1)), filters) + if filename: + editbox.setText(filename) + SettingsManager.set_last_dir(self.plugin.settingsSection, + filename, 1) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 37cbd7a63..70b994653 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -24,7 +24,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`utils` module provides the utility libraries for OpenLP +The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP. """ import logging import os @@ -164,24 +164,34 @@ def _get_os_dir_path(dir_type): """ Return a path based on which OS and environment we are running in. """ + encoding = sys.getfilesystemencoding() if sys.platform == u'win32': - return os.path.join(os.getenv(u'APPDATA'), u'openlp') + if dir_type == AppLocation.DataDir: + return os.path.join(unicode(os.getenv(u'APPDATA'), encoding), + u'openlp', u'data') + return os.path.join(unicode(os.getenv(u'APPDATA'), encoding), + u'openlp') elif sys.platform == u'darwin': if dir_type == AppLocation.DataDir: - return os.path.join(os.getenv(u'HOME'), u'Library', - u'Application Support', u'openlp', u'Data') - return os.path.join(os.getenv(u'HOME'), u'Library', - u'Application Support', u'openlp') + return os.path.join(unicode(os.getenv(u'HOME'), encoding), + u'Library', u'Application Support', u'openlp', u'Data') + return os.path.join(unicode(os.getenv(u'HOME'), encoding), + u'Library', u'Application Support', u'openlp') else: if XDG_BASE_AVAILABLE: if dir_type == AppLocation.ConfigDir: - return os.path.join(BaseDirectory.xdg_config_home, u'openlp') + return os.path.join(unicode(BaseDirectory.xdg_config_home, + encoding), u'openlp') elif dir_type == AppLocation.DataDir: - return os.path.join(BaseDirectory.xdg_data_home, u'openlp') + return os.path.join( + unicode(BaseDirectory.xdg_data_home, encoding), u'openlp') elif dir_type == AppLocation.CacheDir: - return os.path.join(BaseDirectory.xdg_cache_home, u'openlp') - else: - return os.path.join(os.getenv(u'HOME'), u'.openlp') + return os.path.join(unicode(BaseDirectory.xdg_cache_home, + encoding), u'openlp') + if dir_type == AppLocation.DataDir: + return os.path.join(unicode(os.getenv(u'HOME'), encoding), + u'.openlp', u'data') + return os.path.join(unicode(os.getenv(u'HOME'), encoding), u'.openlp') def _get_frozen_path(frozen_option, non_frozen_option): """ @@ -189,8 +199,7 @@ def _get_frozen_path(frozen_option, non_frozen_option): """ if hasattr(sys, u'frozen') and sys.frozen == 1: return frozen_option - else: - return non_frozen_option + return non_frozen_option def check_latest_version(current_version): """ @@ -233,7 +242,7 @@ def add_actions(target, actions): The menu or toolbar to add actions to. ``actions`` - The actions to be added. An action consisting of the keyword 'None' + The actions to be added. An action consisting of the keyword 'None' will result in a separator being inserted into the target. """ for action in actions: @@ -309,7 +318,7 @@ def get_web_page(url, header=None, update_openlp=False): Tells OpenLP to update itself if the page is successfully downloaded. Defaults to False. """ - # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a + # TODO: Add proxy usage. Get proxy info from OpenLP settings, add to a # proxy_handler, build into an opener and install the opener into urllib2. # http://docs.python.org/library/urllib2.html if not url: @@ -373,13 +382,13 @@ def get_uno_command(): """ Returns the UNO command to launch an openoffice.org instance. """ + COMMAND = u'soffice' + OPTIONS = u'-nologo -norestore -minimized -invisible -nofirststartwizard' if UNO_CONNECTION_TYPE == u'pipe': - return u'openoffice.org -nologo -norestore -minimized -invisible ' \ - + u'-nofirststartwizard -accept=pipe,name=openlp_pipe;urp;' + CONNECTION = u'"-accept=pipe,name=openlp_pipe;urp;"' else: - return u'openoffice.org -nologo -norestore -minimized ' \ - + u'-invisible -nofirststartwizard ' \ - + u'-accept=socket,host=localhost,port=2002;urp;' + CONNECTION = u'"-accept=socket,host=localhost,port=2002;urp;"' + return u'%s %s %s' % (COMMAND, OPTIONS, CONNECTION) def get_uno_instance(resolver): """ diff --git a/openlp/core/utils/actions.py b/openlp/core/utils/actions.py index e181dd2e1..30d1d7586 100644 --- a/openlp/core/utils/actions.py +++ b/openlp/core/utils/actions.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/core/utils/languagemanager.py b/openlp/core/utils/languagemanager.py index 454d14fa2..ced2fa843 100644 --- a/openlp/core/utils/languagemanager.py +++ b/openlp/core/utils/languagemanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/__init__.py b/openlp/plugins/__init__.py index 7bf441119..5fd39d572 100644 --- a/openlp/plugins/__init__.py +++ b/openlp/plugins/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### """ The :mod:`plugins` module provides all the project produced plugins -""" \ No newline at end of file +""" diff --git a/openlp/plugins/alerts/__init__.py b/openlp/plugins/alerts/__init__.py index dafae0885..f3c629b25 100644 --- a/openlp/plugins/alerts/__init__.py +++ b/openlp/plugins/alerts/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ """ The :mod:`alerts` module provides the Alerts plugin for producing impromptu on-screen announcements during a service. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 443ec1e84..1d9bd4c61 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -40,21 +40,14 @@ class AlertsPlugin(Plugin): log.info(u'Alerts Plugin loaded') def __init__(self, plugin_helpers): - Plugin.__init__(self, u'Alerts', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Alerts', u'1.9.4', plugin_helpers, + settingsTabClass=AlertsTab) self.weight = -3 self.icon = build_icon(u':/plugins/plugin_alerts.png') self.alertsmanager = AlertsManager(self) self.manager = Manager(u'alerts', init_schema) - self.visible_name = self.getString(StringContent.VisibleName) self.alertForm = AlertForm(self) - def getSettingsTab(self): - """ - Return the settings tab for the Alerts plugin - """ - self.alertsTab = AlertsTab(self, self.visible_name[u'title']) - return self.alertsTab - def addToolsMenuItem(self, tools_menu): """ Give the alerts plugin the opportunity to add items to the @@ -81,7 +74,7 @@ class AlertsPlugin(Plugin): log.info(u'Alerts Initialising') Plugin.initialise(self) self.toolsAlertItem.setVisible(True) - self.liveController.alertTab = self.alertsTab + self.liveController.alertTab = self.settings_tab def finalise(self): """ diff --git a/openlp/plugins/alerts/forms/__init__.py b/openlp/plugins/alerts/forms/__init__.py index da7ae6683..e2809ed73 100644 --- a/openlp/plugins/alerts/forms/__init__.py +++ b/openlp/plugins/alerts/forms/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -24,4 +24,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from alertform import AlertForm \ No newline at end of file +from alertform import AlertForm diff --git a/openlp/plugins/alerts/forms/alertdialog.py b/openlp/plugins/alerts/forms/alertdialog.py index 93f7ead06..27b0b0f7d 100644 --- a/openlp/plugins/alerts/forms/alertdialog.py +++ b/openlp/plugins/alerts/forms/alertdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 0639f2bb1..75475d524 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/alerts/lib/__init__.py b/openlp/plugins/alerts/lib/__init__.py index f6a535b1b..3b446b67d 100644 --- a/openlp/plugins/alerts/lib/__init__.py +++ b/openlp/plugins/alerts/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### from alertsmanager import AlertsManager -from alertstab import AlertsTab \ No newline at end of file +from alertstab import AlertsTab diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 6fe0ae132..a05a29575 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -84,7 +84,7 @@ class AlertsManager(QtCore.QObject): if len(self.alertList) == 0: return text = self.alertList.pop(0) - alertTab = self.parent.alertsTab + alertTab = self.parent.settings_tab self.parent.liveController.display.alert(text) # Check to see if we have a timer running. if self.timer_id == 0: @@ -103,4 +103,4 @@ class AlertsManager(QtCore.QObject): self.parent.liveController.display.alert(u'') self.killTimer(self.timer_id) self.timer_id = 0 - self.generateAlert() \ No newline at end of file + self.generateAlert() diff --git a/openlp/plugins/alerts/lib/alertstab.py b/openlp/plugins/alerts/lib/alertstab.py index 96870d94c..5b4f670a3 100644 --- a/openlp/plugins/alerts/lib/alertstab.py +++ b/openlp/plugins/alerts/lib/alertstab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,61 +27,55 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import SettingsTab, translate +from openlp.core.lib.ui import UiStrings, create_valign_combo class AlertsTab(SettingsTab): """ AlertsTab is the alerts settings tab in the settings dialog. """ - def __init__(self, parent, visible_title): - self.parent = parent - self.manager = parent.manager - SettingsTab.__init__(self, parent.name, visible_title) + def __init__(self, name, visible_title): + SettingsTab.__init__(self, name, visible_title) def setupUi(self): self.setObjectName(u'AlertsTab') SettingsTab.setupUi(self) - self.FontGroupBox = QtGui.QGroupBox(self.leftColumn) - self.FontGroupBox.setObjectName(u'FontGroupBox') - self.FontLayout = QtGui.QFormLayout(self.FontGroupBox) - self.FontLayout.setObjectName(u'FontLayout') - self.FontLabel = QtGui.QLabel(self.FontGroupBox) + self.fontGroupBox = QtGui.QGroupBox(self.leftColumn) + self.fontGroupBox.setObjectName(u'fontGroupBox') + self.fontLayout = QtGui.QFormLayout(self.fontGroupBox) + self.fontLayout.setObjectName(u'fontLayout') + self.FontLabel = QtGui.QLabel(self.fontGroupBox) self.FontLabel.setObjectName(u'FontLabel') - self.FontComboBox = QtGui.QFontComboBox(self.FontGroupBox) + self.FontComboBox = QtGui.QFontComboBox(self.fontGroupBox) self.FontComboBox.setObjectName(u'FontComboBox') - self.FontLayout.addRow(self.FontLabel, self.FontComboBox) - self.FontColorLabel = QtGui.QLabel(self.FontGroupBox) + self.fontLayout.addRow(self.FontLabel, self.FontComboBox) + self.FontColorLabel = QtGui.QLabel(self.fontGroupBox) self.FontColorLabel.setObjectName(u'FontColorLabel') self.ColorLayout = QtGui.QHBoxLayout() self.ColorLayout.setObjectName(u'ColorLayout') - self.FontColorButton = QtGui.QPushButton(self.FontGroupBox) + self.FontColorButton = QtGui.QPushButton(self.fontGroupBox) self.FontColorButton.setObjectName(u'FontColorButton') self.ColorLayout.addWidget(self.FontColorButton) self.ColorLayout.addSpacing(20) - self.BackgroundColorLabel = QtGui.QLabel(self.FontGroupBox) + self.BackgroundColorLabel = QtGui.QLabel(self.fontGroupBox) self.BackgroundColorLabel.setObjectName(u'BackgroundColorLabel') self.ColorLayout.addWidget(self.BackgroundColorLabel) - self.BackgroundColorButton = QtGui.QPushButton(self.FontGroupBox) + self.BackgroundColorButton = QtGui.QPushButton(self.fontGroupBox) self.BackgroundColorButton.setObjectName(u'BackgroundColorButton') self.ColorLayout.addWidget(self.BackgroundColorButton) - self.FontLayout.addRow(self.FontColorLabel, self.ColorLayout) - self.FontSizeLabel = QtGui.QLabel(self.FontGroupBox) + self.fontLayout.addRow(self.FontColorLabel, self.ColorLayout) + self.FontSizeLabel = QtGui.QLabel(self.fontGroupBox) self.FontSizeLabel.setObjectName(u'FontSizeLabel') - self.FontSizeSpinBox = QtGui.QSpinBox(self.FontGroupBox) + self.FontSizeSpinBox = QtGui.QSpinBox(self.fontGroupBox) self.FontSizeSpinBox.setObjectName(u'FontSizeSpinBox') - self.FontLayout.addRow(self.FontSizeLabel, self.FontSizeSpinBox) - self.TimeoutLabel = QtGui.QLabel(self.FontGroupBox) + self.fontLayout.addRow(self.FontSizeLabel, self.FontSizeSpinBox) + self.TimeoutLabel = QtGui.QLabel(self.fontGroupBox) self.TimeoutLabel.setObjectName(u'TimeoutLabel') - self.TimeoutSpinBox = QtGui.QSpinBox(self.FontGroupBox) + self.TimeoutSpinBox = QtGui.QSpinBox(self.fontGroupBox) self.TimeoutSpinBox.setMaximum(180) self.TimeoutSpinBox.setObjectName(u'TimeoutSpinBox') - self.FontLayout.addRow(self.TimeoutLabel, self.TimeoutSpinBox) - self.LocationLabel = QtGui.QLabel(self.FontGroupBox) - self.LocationLabel.setObjectName(u'LocationLabel') - self.LocationComboBox = QtGui.QComboBox(self.FontGroupBox) - self.LocationComboBox.addItems([u'', u'', u'']) - self.LocationComboBox.setObjectName(u'LocationComboBox') - self.FontLayout.addRow(self.LocationLabel, self.LocationComboBox) - self.leftLayout.addWidget(self.FontGroupBox) + self.fontLayout.addRow(self.TimeoutLabel, self.TimeoutSpinBox) + create_valign_combo(self, self.fontGroupBox, self.fontLayout) + self.leftLayout.addWidget(self.fontGroupBox) self.leftLayout.addStretch() self.PreviewGroupBox = QtGui.QGroupBox(self.rightColumn) self.PreviewGroupBox.setObjectName(u'PreviewGroupBox') @@ -99,15 +93,13 @@ class AlertsTab(SettingsTab): QtCore.SIGNAL(u'pressed()'), self.onFontColorButtonClicked) QtCore.QObject.connect(self.FontComboBox, QtCore.SIGNAL(u'activated(int)'), self.onFontComboBoxClicked) - QtCore.QObject.connect(self.LocationComboBox, - QtCore.SIGNAL(u'activated(int)'), self.onLocationComboBoxClicked) QtCore.QObject.connect(self.TimeoutSpinBox, QtCore.SIGNAL(u'valueChanged(int)'), self.onTimeoutSpinBoxChanged) QtCore.QObject.connect(self.FontSizeSpinBox, QtCore.SIGNAL(u'valueChanged(int)'), self.onFontSizeSpinBoxChanged) def retranslateUi(self): - self.FontGroupBox.setTitle( + self.fontGroupBox.setTitle( translate('AlertsPlugin.AlertsTab', 'Font')) self.FontLabel.setText( translate('AlertsPlugin.AlertsTab', 'Font name:')) @@ -117,24 +109,12 @@ class AlertsTab(SettingsTab): translate('AlertsPlugin.AlertsTab', 'Background color:')) self.FontSizeLabel.setText( translate('AlertsPlugin.AlertsTab', 'Font size:')) - self.FontSizeSpinBox.setSuffix( - translate('AlertsPlugin.AlertsTab', 'pt')) + self.FontSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.TimeoutLabel.setText( translate('AlertsPlugin.AlertsTab', 'Alert timeout:')) - self.TimeoutSpinBox.setSuffix( - translate('AlertsPlugin.AlertsTab', 's')) - self.LocationLabel.setText( - translate('AlertsPlugin.AlertsTab', 'Location:')) - self.PreviewGroupBox.setTitle( - translate('AlertsPlugin.AlertsTab', 'Preview')) - self.FontPreview.setText( - translate('AlertsPlugin.AlertsTab', 'OpenLP 2.0')) - self.LocationComboBox.setItemText(0, - translate('AlertsPlugin.AlertsTab', 'Top')) - self.LocationComboBox.setItemText(1, - translate('AlertsPlugin.AlertsTab', 'Middle')) - self.LocationComboBox.setItemText(2, - translate('AlertsPlugin.AlertsTab', 'Bottom')) + self.TimeoutSpinBox.setSuffix(UiStrings.S) + self.PreviewGroupBox.setTitle(UiStrings.Preview) + self.FontPreview.setText(UiStrings.OLPV2) def onBackgroundColorButtonClicked(self): new_color = QtGui.QColorDialog.getColor( @@ -148,9 +128,6 @@ class AlertsTab(SettingsTab): def onFontComboBoxClicked(self): self.updateDisplay() - def onLocationComboBoxClicked(self, location): - self.location = location - def onFontColorButtonClicked(self): new_color = QtGui.QColorDialog.getColor( QtGui.QColor(self.font_color), self) @@ -188,7 +165,7 @@ class AlertsTab(SettingsTab): u'background-color: %s' % self.font_color) self.BackgroundColorButton.setStyleSheet( u'background-color: %s' % self.bg_color) - self.LocationComboBox.setCurrentIndex(self.location) + self.verticalComboBox.setCurrentIndex(self.location) font = QtGui.QFont() font.setFamily(self.font_face) self.FontComboBox.setCurrentFont(font) @@ -197,14 +174,14 @@ class AlertsTab(SettingsTab): def save(self): settings = QtCore.QSettings() settings.beginGroup(self.settingsSection) - self.font_face = self.FontComboBox.currentFont().family() settings.setValue(u'background color', QtCore.QVariant(self.bg_color)) settings.setValue(u'font color', QtCore.QVariant(self.font_color)) settings.setValue(u'font size', QtCore.QVariant(self.font_size)) + self.font_face = self.FontComboBox.currentFont().family() settings.setValue(u'font face', QtCore.QVariant(self.font_face)) settings.setValue(u'timeout', QtCore.QVariant(self.timeout)) - settings.setValue(u'location', - QtCore.QVariant(self.LocationComboBox.currentIndex())) + self.location = self.verticalComboBox.currentIndex() + settings.setValue(u'location', QtCore.QVariant(self.location)) settings.endGroup() def updateDisplay(self): diff --git a/openlp/plugins/alerts/lib/db.py b/openlp/plugins/alerts/lib/db.py index e324bc838..9cfa34846 100644 --- a/openlp/plugins/alerts/lib/db.py +++ b/openlp/plugins/alerts/lib/db.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -55,4 +55,4 @@ def init_schema(url): mapper(AlertItem, alerts_table) metadata.create_all(checkfirst=True) - return session \ No newline at end of file + return session diff --git a/openlp/plugins/bibles/__init__.py b/openlp/plugins/bibles/__init__.py index 59cd2afec..29364ab1a 100644 --- a/openlp/plugins/bibles/__init__.py +++ b/openlp/plugins/bibles/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ """ The :mod:`bibles` module provides the Bible plugin to enable OpenLP to display scripture. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/bibles/bibleplugin.py b/openlp/plugins/bibles/bibleplugin.py index e3b2ad4aa..73a9b7e1d 100644 --- a/openlp/plugins/bibles/bibleplugin.py +++ b/openlp/plugins/bibles/bibleplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -37,7 +37,8 @@ class BiblePlugin(Plugin): log.info(u'Bible Plugin loaded') def __init__(self, plugin_helpers): - Plugin.__init__(self, u'Bibles', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Bibles', u'1.9.4', plugin_helpers, + BibleMediaItem, BiblesTab) self.weight = -9 self.icon_path = u':/plugins/plugin_bibles.png' self.icon = build_icon(self.icon_path) @@ -61,14 +62,6 @@ class BiblePlugin(Plugin): self.importBibleItem.setVisible(False) self.exportBibleItem.setVisible(False) - def getSettingsTab(self): - visible_name = self.getString(StringContent.VisibleName) - return BiblesTab(self.name, visible_name[u'title']) - - def getMediaManagerItem(self): - # Create the BibleManagerItem object. - return BibleMediaItem(self, self, self.icon) - def addImportMenuItem(self, import_menu): self.importBibleItem = QtGui.QAction(import_menu) self.importBibleItem.setObjectName(u'importBibleItem') @@ -135,40 +128,15 @@ class BiblePlugin(Plugin): u'title': translate('BiblesPlugin', 'Bibles', 'container title') } # Middle Header Bar - ## Import Action ## - self.textStrings[StringContent.Import] = { - u'title': translate('BiblesPlugin', '&Import'), - u'tooltip': translate('BiblesPlugin', 'Import a Bible') - } - ## New Action ## - self.textStrings[StringContent.New] = { - u'title': translate('BiblesPlugin', '&Add'), - u'tooltip': translate('BiblesPlugin', 'Add a new Bible') - } - ## Edit Action ## - self.textStrings[StringContent.Edit] = { - u'title': translate('BiblesPlugin', '&Edit'), - u'tooltip': translate('BiblesPlugin', 'Edit the selected Bible') - } - ## Delete Action ## - self.textStrings[StringContent.Delete] = { - u'title': translate('BiblesPlugin', '&Delete'), - u'tooltip': translate('BiblesPlugin', 'Delete the selected Bible') - } - ## Preview Action ## - self.textStrings[StringContent.Preview] = { - u'title': translate('BiblesPlugin', 'Preview'), - u'tooltip': translate('BiblesPlugin', 'Preview the selected Bible') - } - ## Send Live Action ## - self.textStrings[StringContent.Live] = { - u'title': translate('BiblesPlugin', 'Live'), - u'tooltip': translate('BiblesPlugin', - 'Send the selected Bible live') - } - ## Add to Service Action ## - self.textStrings[StringContent.Service] = { - u'title': translate('BiblesPlugin', 'Service'), - u'tooltip': translate('BiblesPlugin', + tooltips = { + u'load': u'', + u'import': translate('BiblesPlugin', 'Import a Bible'), + u'new': translate('BiblesPlugin', 'Add a new Bible'), + u'edit': translate('BiblesPlugin', 'Edit the selected Bible'), + u'delete': translate('BiblesPlugin', 'Delete the selected Bible'), + u'preview': translate('BiblesPlugin', 'Preview the selected Bible'), + u'live': translate('BiblesPlugin', 'Send the selected Bible live'), + u'service': translate('BiblesPlugin', 'Add the selected Bible to the service') } + self.setPluginUiTextStrings(tooltips) diff --git a/openlp/plugins/bibles/forms/__init__.py b/openlp/plugins/bibles/forms/__init__.py index 1365dc5e0..15f14de9e 100644 --- a/openlp/plugins/bibles/forms/__init__.py +++ b/openlp/plugins/bibles/forms/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -53,4 +53,4 @@ from the .ui files later if necessary. from bibleimportform import BibleImportForm -__all__ = ['BibleImportForm'] \ No newline at end of file +__all__ = ['BibleImportForm'] diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index f21dd0e07..67996e158 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,10 +33,10 @@ import os.path from PyQt4 import QtCore, QtGui -from openlp.core.lib import Receiver, SettingsManager, translate +from openlp.core.lib import Receiver, translate from openlp.core.lib.db import delete_database -from openlp.core.lib.ui import critical_error_message_box -from openlp.core.ui.wizard import OpenLPWizard +from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.utils import AppLocation, string_is_unicode from openlp.plugins.bibles.lib.manager import BibleFormat @@ -51,18 +51,7 @@ class WebDownload(object): BibleGateway = 1 Bibleserver = 2 - Names = { - 0: u'Crosswalk', - 1: u'BibleGateway', - 2: u'Bibleserver' - } - - @classmethod - def get_name(cls, name): - """ - Get the web bible type name. - """ - return cls.Names[name] + Names = [u'Crosswalk', u'BibleGateway', u'Bibleserver'] class BibleImportForm(OpenLPWizard): @@ -363,32 +352,22 @@ class BibleImportForm(OpenLPWizard): """ self.setWindowTitle( translate('BiblesPlugin.ImportWizardForm', 'Bible Import Wizard')) - self.titleLabel.setText( - u'%s' % \ - translate('BiblesPlugin.ImportWizardForm', - 'Welcome to the Bible Import Wizard')) + self.titleLabel.setText(WizardStrings.HeaderStyle % + translate('OpenLP.Ui', 'Welcome to the Bible Import Wizard')) self.informationLabel.setText( translate('BiblesPlugin.ImportWizardForm', - 'This wizard will help you to import Bibles from a ' - 'variety of formats. Click the next button below to start the ' - 'process by selecting a format to import from.')) - self.selectPage.setTitle(translate('BiblesPlugin.ImportWizardForm', - 'Select Import Source')) - self.selectPage.setSubTitle( - translate('BiblesPlugin.ImportWizardForm', - 'Select the import format, and where to import from.')) - self.formatLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Format:')) - self.formatComboBox.setItemText(0, - translate('BiblesPlugin.ImportWizardForm', 'OSIS')) - self.formatComboBox.setItemText(1, - translate('BiblesPlugin.ImportWizardForm', 'CSV')) - self.formatComboBox.setItemText(2, - translate('BiblesPlugin.ImportWizardForm', 'OpenSong')) - self.formatComboBox.setItemText(3, + 'This wizard will help you to import Bibles from a variety of ' + 'formats. Click the next button below to start the process by ' + 'selecting a format to import from.')) + self.selectPage.setTitle(WizardStrings.ImportSelect) + self.selectPage.setSubTitle(WizardStrings.ImportSelectLong) + self.formatLabel.setText(WizardStrings.FormatLabel) + self.formatComboBox.setItemText(BibleFormat.OSIS, WizardStrings.OSIS) + self.formatComboBox.setItemText(BibleFormat.CSV, WizardStrings.CSV) + self.formatComboBox.setItemText(BibleFormat.OpenSong, WizardStrings.OS) + self.formatComboBox.setItemText(BibleFormat.WebDownload, translate('BiblesPlugin.ImportWizardForm', 'Web Download')) - self.formatComboBox.setItemText(4, - translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x')) + self.formatComboBox.setItemText(BibleFormat.OpenLP1, UiStrings.OLPV1) self.openlp1FileLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Bible file:')) self.osisFileLabel.setText( @@ -403,11 +382,11 @@ class BibleImportForm(OpenLPWizard): translate('BiblesPlugin.ImportWizardForm', 'Bible file:')) self.webSourceLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Location:')) - self.webSourceComboBox.setItemText(0, + self.webSourceComboBox.setItemText(WebDownload.Crosswalk, translate('BiblesPlugin.ImportWizardForm', 'Crosswalk')) - self.webSourceComboBox.setItemText(1, + self.webSourceComboBox.setItemText(WebDownload.BibleGateway, translate('BiblesPlugin.ImportWizardForm', 'BibleGateway')) - self.webSourceComboBox.setItemText(2, + self.webSourceComboBox.setItemText(WebDownload.Bibleserver, translate('BiblesPlugin.ImportWizardForm', 'Bibleserver')) self.webTranslationLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Bible:')) @@ -435,19 +414,13 @@ class BibleImportForm(OpenLPWizard): translate('BiblesPlugin.ImportWizardForm', 'Copyright:')) self.permissionsLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Permissions:')) - self.progressPage.setTitle( - translate('BiblesPlugin.ImportWizardForm', 'Importing')) + self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( translate('BiblesPlugin.ImportWizardForm', 'Please wait while your Bible is imported.')) - self.progressLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Ready.')) + self.progressLabel.setText(WizardStrings.Ready) self.progressBar.setFormat(u'%p%') - self.openlp1DisabledLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'The openlp.org 1.x ' - 'importer has been disabled due to a missing Python module. If ' - 'you want to use this importer, you will need to install the ' - '"python-sqlite" module.')) + self.openlp1DisabledLabel.setText(WizardStrings.NoSqlite) # Align all QFormLayouts towards each other. labelWidth = max(self.formatLabel.minimumSizeHint().width(), self.osisFileLabel.minimumSizeHint().width(), @@ -468,37 +441,28 @@ class BibleImportForm(OpenLPWizard): elif self.currentPage() == self.selectPage: if self.field(u'source_format').toInt()[0] == BibleFormat.OSIS: if not self.field(u'osis_location').toString(): - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Invalid Bible Location'), - translate('BiblesPlugin.ImportWizardForm', - 'You need to specify a file to import your ' - 'Bible from.')) + critical_error_message_box(UiStrings.NFSs, + WizardStrings.YouSpecifyFile % WizardStrings.OSIS) self.osisFileEdit.setFocus() return False elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV: if not self.field(u'csv_testamentsfile').toString(): - answer = critical_error_message_box(translate( - 'BiblesPlugin.ImportWizardForm', 'No Testaments File'), + answer = critical_error_message_box(UiStrings.NFSs, translate('BiblesPlugin.ImportWizardForm', 'You have not specified a testaments file. Do you ' 'want to proceed with the import?'), question=True) if answer == QtGui.QMessageBox.No: self.csvTestamentsEdit.setFocus() return False - elif not self.field(u'csv_booksfile').toString(): - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Invalid Books File'), + if not self.field(u'csv_booksfile').toString(): + critical_error_message_box(UiStrings.NFSs, translate('BiblesPlugin.ImportWizardForm', 'You need to specify a file with books of ' 'the Bible to use in the import.')) self.csvBooksEdit.setFocus() return False elif not self.field(u'csv_versefile').toString(): - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Invalid Verse File'), + critical_error_message_box(UiStrings.NFSs, translate('BiblesPlugin.ImportWizardForm', 'You need to specify a file of Bible ' 'verses to import.')) @@ -507,22 +471,14 @@ class BibleImportForm(OpenLPWizard): elif self.field(u'source_format').toInt()[0] == \ BibleFormat.OpenSong: if not self.field(u'opensong_file').toString(): - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Invalid OpenSong Bible'), - translate('BiblesPlugin.ImportWizardForm', - 'You need to specify an OpenSong Bible ' - 'file to import.')) + critical_error_message_box(UiStrings.NFSs, + WizardStrings.YouSpecifyFile % WizardStrings.OS) self.openSongFileEdit.setFocus() return False elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1: if not self.field(u'openlp1_location').toString(): - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Invalid Bible Location'), - translate('BiblesPlugin.ImportWizardForm', - 'You need to specify a file to import your ' - 'Bible from.')) + critical_error_message_box(UiStrings.NFSs, + WizardStrings.YouSpecifyFile % UiStrings.OLPV1) self.openlp1FileEdit.setFocus() return False return True @@ -531,17 +487,13 @@ class BibleImportForm(OpenLPWizard): license_copyright = \ unicode(self.field(u'license_copyright').toString()) if not license_version: - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Empty Version Name'), + critical_error_message_box(UiStrings.EmptyField, translate('BiblesPlugin.ImportWizardForm', 'You need to specify a version name for your Bible.')) self.versionNameEdit.setFocus() return False elif not license_copyright: - critical_error_message_box( - translate('BiblesPlugin.ImportWizardForm', - 'Empty Copyright'), + critical_error_message_box(UiStrings.EmptyField, translate('BiblesPlugin.ImportWizardForm', 'You need to set a copyright for your Bible. ' 'Bibles in the Public Domain need to be marked as such.')) @@ -576,24 +528,22 @@ class BibleImportForm(OpenLPWizard): """ Show the file open dialog for the OSIS file. """ - self.getFileName( - translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'), + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OSIS, self.osisFileEdit) def onCsvTestamentsBrowseButtonClicked(self): """ Show the file open dialog for the testaments CSV file. """ - self.getFileName(translate('BiblesPlugin.ImportWizardForm', - 'Open Testaments CSV File'), self.csvTestamentsEdit, u'%s (*.csv)' + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, + self.csvTestamentsEdit, u'%s (*.csv)' % translate('BiblesPlugin.ImportWizardForm', 'CSV File')) def onCsvBooksBrowseButtonClicked(self): """ Show the file open dialog for the books CSV file. """ - self.getFileName( - translate('BiblesPlugin.ImportWizardForm', 'Open Books CSV File'), + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, self.csvBooksEdit, u'%s (*.csv)' % translate('BiblesPlugin.ImportWizardForm', 'CSV File')) @@ -601,27 +551,24 @@ class BibleImportForm(OpenLPWizard): """ Show the file open dialog for the verses CSV file. """ - self.getFileName(translate('BiblesPlugin.ImportWizardForm', - 'Open Verses CSV File'), self.csvVersesEdit, u'%s (*.csv)' + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV, + self.csvVersesEdit, u'%s (*.csv)' % translate('BiblesPlugin.ImportWizardForm', 'CSV File')) def onOpenSongBrowseButtonClicked(self): """ Show the file open dialog for the OpenSong file. """ - self.getFileName( - translate('BiblesPlugin.ImportWizardForm', 'Open OpenSong Bible'), + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OS, self.openSongFileEdit) def onOpenlp1BrowseButtonClicked(self): """ Show the file open dialog for the openlp.org 1.x file. """ - self.getFileName( - translate('BiblesPlugin.ImportWizardForm', - 'Open openlp.org 1.x Bible'), self.openlp1FileEdit, - u'%s (*.bible)' % translate('BiblesPlugin.ImportWizardForm', - 'openlp.org 1.x bible')) + self.getFileName(WizardStrings.OpenTypeFile % UiStrings.OLPV1, + self.openlp1FileEdit, u'%s (*.bible)' % + translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x bible')) def registerFields(self): """ @@ -722,39 +669,11 @@ class BibleImportForm(OpenLPWizard): self.web_bible_list[download_type][ver] = name.strip() except IOError: log.exception(u'%s resources missing' % - WebDownload.get_name(download_type)) + WebDownload.Names[download_type]) finally: if books_file: books_file.close() - def getFileName(self, title, editbox, filters=u''): - """ - Opens a QFileDialog and saves the filename to the given editbox. - - ``title`` - The title of the dialog (unicode). - - ``editbox`` - A editbox (QLineEdit). - - ``filters`` - The file extension filters. It should contain the file description - as well as the file extension. For example:: - - u'openlp.org 1.x bible (*.bible)' - """ - if filters: - filters += u';;' - filters += u'%s (*)' % translate('BiblesPlugin.ImportWizardForm', - 'All Files') - filename = QtGui.QFileDialog.getOpenFileName(self, title, - os.path.dirname(SettingsManager.get_last_dir( - self.plugin.settingsSection, 1)), filters) - if filename: - editbox.setText(filename) - SettingsManager.set_last_dir( - self.plugin.settingsSection, filename, 1) - def preWizard(self): """ Prepare the UI for the import. @@ -766,8 +685,7 @@ class BibleImportForm(OpenLPWizard): 'BiblesPlugin.ImportWizardForm', 'Starting Registering bible...')) else: - self.progressLabel.setText(translate( - 'BiblesPlugin.ImportWizardForm', 'Starting import...')) + self.progressLabel.setText(WizardStrings.StartingImport) Receiver.send_message(u'openlp_process_events') def performWizard(self): @@ -805,18 +723,10 @@ class BibleImportForm(OpenLPWizard): self.progressBar.setMaximum(1) download_location = self.field(u'web_location').toInt()[0] bible_version = unicode(self.webTranslationComboBox.currentText()) - if download_location == WebDownload.Crosswalk: - bible = \ - self.web_bible_list[WebDownload.Crosswalk][bible_version] - elif download_location == WebDownload.BibleGateway: - bible = \ - self.web_bible_list[WebDownload.BibleGateway][bible_version] - elif download_location == WebDownload.Bibleserver: - bible = \ - self.web_bible_list[WebDownload.Bibleserver][bible_version] + bible = self.web_bible_list[download_location][bible_version] importer = self.manager.import_bible( BibleFormat.WebDownload, name=license_version, - download_source=WebDownload.get_name(download_location), + download_source=WebDownload.Names[download_location], download_name=bible, proxy_server=unicode(self.field(u'proxy_server').toString()), proxy_username=\ @@ -839,9 +749,9 @@ class BibleImportForm(OpenLPWizard): 'bible. Please note, that verses will be downloaded on\n' 'demand and thus an internet connection is required.')) else: - self.progressLabel.setText(translate( - 'BiblesPlugin.ImportWizardForm', 'Finished import.')) + self.progressLabel.setText(WizardStrings.FinishedImport) else: self.progressLabel.setText(translate( 'BiblesPlugin.ImportWizardForm', 'Your Bible import failed.')) + del self.manager.db_cache[importer.name] delete_database(self.plugin.settingsSection, importer.file) diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index e6fff1cc8..e8634c3a3 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,7 +32,33 @@ import re log = logging.getLogger(__name__) +class LayoutStyle(object): + """ + An enumeration for bible screen layout styles. + """ + VersePerSlide = 0 + VersePerLine = 1 + Continuous = 2 + + +class DisplayStyle(object): + """ + An enumeration for bible text bracket display styles. + """ + NoBrackets = 0 + Round = 1 + Curly = 2 + Square = 3 + + def get_reference_match(match_type): + """ + Provides the regexes and matches to use while parsing strings for bible + references. + + ``match_type`` + The type of reference information trying to be extracted in this call. + """ local_separator = unicode(u':;;\s*[:vV]\s*;;-;;\s*-\s*;;,;;\s*,\s*;;end' ).split(u';;') # English # local_separator = unicode(u',;;\s*,\s*;;-;;\s*-\s*;;.;;\.;;[Ee]nde' @@ -62,69 +88,90 @@ def get_reference_match(match_type): def parse_reference(reference): """ This is the next generation über-awesome function that takes a person's - typed in string and converts it to a reference list, a list of references to - be queried from the Bible database files. + typed in string and converts it to a list of references to be queried from + the Bible database files. - This is a user manual like description, how the references are working. + ``reference`` + A string. The Bible reference to parse. - - Each reference starts with the book name. A chapter name is manditory. - ``John 3`` refers to Gospel of John chapter 3 - - A reference range can be given after a range separator. - ``John 3-5`` refers to John chapters 3 to 5 - - Single verses can be addressed after a verse separator - ``John 3:16`` refers to John chapter 3 verse 16 - ``John 3:16-4:3`` refers to John chapter 3 verse 16 to chapter 4 verse 3 - - After a verse reference all further single values are treat as verse in - the last selected chapter. - ``John 3:16-18`` refers to John chapter 3 verses 16 to 18 - - After a list separator it is possible to refer to additional verses. They - are build analog to the first ones. This way it is possible to define each - number of verse references. It is not possible to refer to verses in - additional books. - ``John 3:16,18`` refers to John chapter 3 verses 16 and 18 - ``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 and 20 - ``John 3:16-18,4:1`` refers to John chapter 3 verses 16 to 18 and - chapter 3 verse 1 - - If there is a range separator without further verse declaration the last - refered chapter is addressed until the end. - - ``range_string`` is a regular expression which matches for verse range - declarations: - - 1. ``(?:(?P[0-9]+)%(sep_v)s)?`` - It starts with a optional chapter reference ``from_chapter`` followed by - a verse separator. - 2. ``(?P[0-9]+)`` - The verse reference ``from_verse`` is manditory - 3. ``(?P%(sep_r)s(?:`` ... ``|%(sep_e)s)?)?`` - A ``range_to`` declaration is optional. It starts with a range separator - and contains optional a chapter and verse declaration or a end - separator. - 4. ``(?:(?P[0-9]+)%(sep_v)s)?`` - The ``to_chapter`` reference with separator is equivalent to group 1. - 5. ``(?P[0-9]+)`` - The ``to_verse`` reference is equivalent to group 2. - - The full reference is matched against get_reference_match(u'full'). This - regular expression looks like this: - - 1. ``^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$`` - The second group contains all ``ranges``. This can be multiple - declarations of a range_string separated by a list separator. + Returns ``None`` or a reference list. The reference list is a list of tuples, with each tuple structured like this:: (book, chapter, from_verse, to_verse) - ``reference`` - The bible reference to parse. + For example:: + + [(u'John', 3, 16, 18), (u'John', 4, 1, 1)] + + **Reference string details:** + + Each reference starts with the book name and a chapter number. These are + both mandatory. + + * ``John 3`` refers to Gospel of John chapter 3 + + A reference range can be given after a range separator. + + * ``John 3-5`` refers to John chapters 3 to 5 + + Single verses can be addressed after a verse separator. + + * ``John 3:16`` refers to John chapter 3 verse 16 + * ``John 3:16-4:3`` refers to John chapter 3 verse 16 to chapter 4 verse 3 + + After a verse reference all further single values are treat as verse in + the last selected chapter. + + * ``John 3:16-18`` refers to John chapter 3 verses 16 to 18 + + After a list separator it is possible to refer to additional verses. They + are build analog to the first ones. This way it is possible to define each + number of verse references. It is not possible to refer to verses in + additional books. + + * ``John 3:16,18`` refers to John chapter 3 verses 16 and 18 + * ``John 3:16-18,20`` refers to John chapter 3 verses 16 to 18 and 20 + * ``John 3:16-18,4:1`` refers to John chapter 3 verses 16 to 18 and + chapter 4 verse 1 + + If there is a range separator without further verse declaration the last + refered chapter is addressed until the end. + + ``range_string`` is a regular expression which matches for verse range + declarations: + + ``(?:(?P[0-9]+)%(sep_v)s)?`` + It starts with a optional chapter reference ``from_chapter`` followed by + a verse separator. + + ``(?P[0-9]+)`` + The verse reference ``from_verse`` is manditory + + ``(?P%(sep_r)s(?:`` ... ``|%(sep_e)s)?)?`` + A ``range_to`` declaration is optional. It starts with a range separator + and contains optional a chapter and verse declaration or a end + separator. + + ``(?:(?P[0-9]+)%(sep_v)s)?`` + The ``to_chapter`` reference with separator is equivalent to group 1. + + ``(?P[0-9]+)`` + The ``to_verse`` reference is equivalent to group 2. + + The full reference is matched against get_reference_match(u'full'). This + regular expression looks like this: + + ``^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$`` + The second group contains all ``ranges``. This can be multiple + declarations of a range_string separated by a list separator. - Returns None or a reference list. """ log.debug(u'parse_reference("%s")', reference) match = get_reference_match(u'full').match(reference) @@ -194,7 +241,7 @@ def parse_reference(reference): class SearchResults(object): """ - Encapsulate a set of search results. This is Bible-type independent. + Encapsulate a set of search results. This is Bible-type independent. """ def __init__(self, book, chapter, verselist): """ @@ -207,7 +254,8 @@ class SearchResults(object): The chapter of the book. ``verselist`` - The list of verses for this reading + The list of verses for this reading. + """ self.book = book self.chapter = chapter diff --git a/openlp/plugins/bibles/lib/biblestab.py b/openlp/plugins/bibles/lib/biblestab.py index f6bd27324..74be7145b 100644 --- a/openlp/plugins/bibles/lib/biblestab.py +++ b/openlp/plugins/bibles/lib/biblestab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,6 +29,7 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsTab, translate +from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle log = logging.getLogger(__name__) @@ -122,19 +123,19 @@ class BiblesTab(SettingsTab): translate('BiblesPlugin.BiblesTab', 'Display style:')) self.BibleThemeLabel.setText( translate('BiblesPlugin.BiblesTab', 'Bible theme:')) - self.LayoutStyleComboBox.setItemText(0, + self.LayoutStyleComboBox.setItemText(LayoutStyle.VersePerSlide, translate('BiblesPlugin.BiblesTab', 'Verse Per Slide')) - self.LayoutStyleComboBox.setItemText(1, + self.LayoutStyleComboBox.setItemText(LayoutStyle.VersePerLine, translate('BiblesPlugin.BiblesTab', 'Verse Per Line')) - self.LayoutStyleComboBox.setItemText(2, + self.LayoutStyleComboBox.setItemText(LayoutStyle.Continuous, translate('BiblesPlugin.BiblesTab', 'Continuous')) - self.DisplayStyleComboBox.setItemText(0, + self.DisplayStyleComboBox.setItemText(DisplayStyle.NoBrackets, translate('BiblesPlugin.BiblesTab', 'No Brackets')) - self.DisplayStyleComboBox.setItemText(1, + self.DisplayStyleComboBox.setItemText(DisplayStyle.Round, translate('BiblesPlugin.BiblesTab', '( And )')) - self.DisplayStyleComboBox.setItemText(2, + self.DisplayStyleComboBox.setItemText(DisplayStyle.Curly, translate('BiblesPlugin.BiblesTab', '{ And }')) - self.DisplayStyleComboBox.setItemText(3, + self.DisplayStyleComboBox.setItemText(DisplayStyle.Square, translate('BiblesPlugin.BiblesTab', '[ And ]')) self.ChangeNoteLabel.setText(translate('BiblesPlugin.BiblesTab', 'Note:\nChanges do not affect verses already in the service.')) diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 82872e15b..18bf06cfb 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -94,8 +94,6 @@ class CSVBible(BibleDB): self.testamentsfile = None self.booksfile = kwargs[u'booksfile'] self.versesfile = kwargs[u'versefile'] - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def setup_testaments(self): """ diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index b986b0d66..5cf000ee1 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,7 +33,7 @@ from sqlalchemy import Column, ForeignKey, or_, Table, types from sqlalchemy.orm import class_mapper, mapper, relation from sqlalchemy.orm.exc import UnmappedClassError -from openlp.core.lib import translate +from openlp.core.lib import Receiver, translate from openlp.core.lib.db import BaseModel, init_db, Manager from openlp.core.lib.ui import critical_error_message_box @@ -162,6 +162,8 @@ class BibleDB(QtCore.QObject, Manager): if u'file' in kwargs: self.get_name() self.wizard = None + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def stop_import(self): """ @@ -320,7 +322,7 @@ class BibleDB(QtCore.QObject, Manager): def get_books(self): """ A wrapper so both local and web bibles have a get_books() method that - manager can call. Used in the media manager advanced search tab. + manager can call. Used in the media manager advanced search tab. """ return self.get_all_objects(Book, order_by_ref=Book.id) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 7cba6facb..e2dde59fd 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -35,7 +35,7 @@ import socket import urllib from HTMLParser import HTMLParseError -from BeautifulSoup import BeautifulSoup, NavigableString +from BeautifulSoup import BeautifulSoup, NavigableString, Tag from openlp.core.lib import Receiver, translate from openlp.core.lib.ui import critical_error_message_box @@ -221,24 +221,42 @@ class BGExtract(object): crossrefs = soup.findAll(u'sup', u'xref') if crossrefs: [crossref.extract() for crossref in crossrefs] + headings = soup.findAll(u'h5') + if headings: + [heading.extract() for heading in headings] cleanup = [(re.compile('\s+'), lambda match: ' ')] verses = BeautifulSoup(str(soup), markupMassage=cleanup) - content = verses.find(u'div', u'result-text-style-normal') - if not content: - content = verses.find(u'div', u'result-text-style-rtl-serif') - if not content: + verse_list = {} + for verse in verses(u'sup', u'versenum'): + raw_verse_num = verse.next + clean_verse_num = 0 + # Not all verses exist in all translations and may or may not be + # represented by a verse number. If they are not fine, if they are + # it will probably be in a format that breaks int(). We will then + # have no idea what garbage may be sucked in to the verse text so + # if we do not get a clean int() then ignore the verse completely. + try: + clean_verse_num = int(str(raw_verse_num)) + except ValueError: + log.exception(u'Illegal verse number in %s %s %s:%s', + version, bookname, chapter, unicode(raw_verse_num)) + if clean_verse_num: + verse_text = raw_verse_num.next + part = raw_verse_num.next.next + while not (isinstance(part, Tag) and part.attrMap and + part.attrMap[u'class'] == u'versenum'): + # While we are still in the same verse grab all the text. + if isinstance(part, NavigableString): + verse_text = verse_text + part + if isinstance(part.next, Tag) and part.next.name == u'div': + # Run out of verses so stop. + break + part = part.next + verse_list[clean_verse_num] = unicode(verse_text) + if not verse_list: log.debug(u'No content found in the BibleGateway response.') send_error_message(u'parse') return None - verse_count = len(verses.findAll(u'sup', u'versenum')) - found_count = 0 - verse_list = {} - while found_count < verse_count: - content = content.findNext(u'sup', u'versenum') - raw_verse_num = content.next - raw_verse_text = raw_verse_num.next - verse_list[int(str(raw_verse_num))] = unicode(raw_verse_text) - found_count += 1 return SearchResults(bookname, chapter, verse_list) @@ -372,7 +390,7 @@ class HTTPBible(BibleDB): BibleDB.__init__(self, parent, **kwargs) self.download_source = kwargs[u'download_source'] self.download_name = kwargs[u'download_name'] - # TODO: Clean up proxy stuff. We probably want one global proxy per + # TODO: Clean up proxy stuff. We probably want one global proxy per # connection type (HTTP and HTTPS) at most. self.proxy_server = None self.proxy_username = None @@ -446,8 +464,8 @@ class HTTPBible(BibleDB): search_results = self.get_chapter(book, reference[1]) if search_results and search_results.has_verselist(): ## We have found a book of the bible lets check to see - ## if it was there. By reusing the returned book name - ## we get a correct book. For example it is possible + ## if it was there. By reusing the returned book name + ## we get a correct book. For example it is possible ## to request ac and get Acts back. bookname = search_results.book Receiver.send_message(u'openlp_process_events') diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 85204ac7a..344d11584 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -40,22 +40,12 @@ from osis import OSISBible # Imports that might fail. try: from openlp1 import OpenLP1Bible - has_openlp1 = True + HAS_OPENLP1 = True except ImportError: - has_openlp1 = False + HAS_OPENLP1 = False log = logging.getLogger(__name__) -class BibleMode(object): - """ - This is basically an enumeration class which specifies the mode of a Bible. - Mode refers to whether or not a Bible in OpenLP is a full Bible or needs to - be downloaded from the Internet on an as-needed basis. - """ - Full = 1 - Partial = 2 - - class BibleFormat(object): """ This is a special enumeration class that holds the various types of Bibles, @@ -275,7 +265,7 @@ class BibleManager(object): 'Scripture Reference Error'), u'message': translate('BiblesPlugin.BibleManager', 'Your scripture reference is either not supported by OpenLP ' - 'or is invalid. Please make sure your reference conforms to ' + 'or is invalid. Please make sure your reference conforms to ' 'one of the following patterns:\n\n' 'Book Chapter\n' 'Book Chapter-Chapter\n' @@ -367,6 +357,6 @@ class BibleManager(object): for bible in self.db_cache: self.db_cache[bible].finalise() -BibleFormat.set_availability(BibleFormat.OpenLP1, has_openlp1) +BibleFormat.set_availability(BibleFormat.OpenLP1, HAS_OPENLP1) __all__ = [u'BibleFormat'] diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index c162447b2..ab7897828 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,22 +28,23 @@ import logging from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ - ItemCapabilities, translate -from openlp.core.lib.ui import add_widget_completer, media_item_combo_box, \ - critical_error_message_box +from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ + translate +from openlp.core.lib.searchedit import SearchEdit +from openlp.core.lib.ui import UiStrings, add_widget_completer, \ + media_item_combo_box, critical_error_message_box from openlp.plugins.bibles.forms import BibleImportForm -from openlp.plugins.bibles.lib import get_reference_match +from openlp.plugins.bibles.lib import LayoutStyle, DisplayStyle, \ + get_reference_match log = logging.getLogger(__name__) -class BibleListView(BaseListWithDnD): +class BibleSearch(object): """ - Custom list view descendant, required for drag and drop. + Enumeration class for the different search methods for the "quick search". """ - def __init__(self, parent=None): - self.PluginName = u'Bibles' - BaseListWithDnD.__init__(self, parent) + Reference = 1 + Text = 2 class BibleMediaItem(MediaManagerItem): @@ -54,9 +55,9 @@ class BibleMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'songs/song' - self.ListViewWithDnD_class = BibleListView MediaManagerItem.__init__(self, parent, plugin, icon) # Place to store the search results for both bibles. + self.settings = self.parent.settings_tab self.search_results = {} self.second_search_results = {} QtCore.QObject.connect(Receiver.get_receiver(), @@ -93,18 +94,17 @@ class BibleMediaItem(MediaManagerItem): u'quickSecondComboBox') self.quickSecondLabel.setBuddy(self.quickSecondComboBox) self.quickLayout.addRow(self.quickSecondLabel, self.quickSecondComboBox) - self.quickSearchTypeLabel = QtGui.QLabel(self.quickTab) - self.quickSearchTypeLabel.setObjectName(u'quickSearchTypeLabel') - self.quickSearchComboBox = media_item_combo_box(self.quickTab, - u'quickSearchComboBox') - self.quickSearchTypeLabel.setBuddy(self.quickSearchComboBox) - self.quickLayout.addRow(self.quickSearchTypeLabel, - self.quickSearchComboBox) self.quickSearchLabel = QtGui.QLabel(self.quickTab) self.quickSearchLabel.setObjectName(u'quickSearchLabel') - self.quickSearchEdit = QtGui.QLineEdit(self.quickTab) + self.quickSearchEdit = SearchEdit(self.quickTab) self.quickSearchEdit.setObjectName(u'quickSearchEdit') self.quickSearchLabel.setBuddy(self.quickSearchEdit) + self.quickSearchEdit.setSearchTypes([ + (BibleSearch.Reference, u':/bibles/bibles_search_reference.png', + translate('BiblesPlugin.MediaItem', 'Scripture Reference')), + (BibleSearch.Text, u':/bibles/bibles_search_text.png', + translate('BiblesPlugin.MediaItem', 'Text Search')) + ]) self.quickLayout.addRow(self.quickSearchLabel, self.quickSearchEdit) self.quickClearLabel = QtGui.QLabel(self.quickTab) self.quickClearLabel.setObjectName(u'quickClearLabel') @@ -192,8 +192,7 @@ class BibleMediaItem(MediaManagerItem): self.advancedSearchButtonLayout.addWidget(self.advancedSearchButton) self.advancedLayout.addLayout( self.advancedSearchButtonLayout, 7, 0, 1, 3) - self.searchTabWidget.addTab(self.advancedTab, - translate('BiblesPlugin.MediaItem', 'Advanced')) + self.searchTabWidget.addTab(self.advancedTab, UiStrings.Advanced) # Add the search tab widget to the page layout. self.pageLayout.addWidget(self.searchTabWidget) # Combo Boxes @@ -207,8 +206,8 @@ class BibleMediaItem(MediaManagerItem): QtCore.SIGNAL(u'activated(int)'), self.onAdvancedFromVerse) QtCore.QObject.connect(self.advancedToChapter, QtCore.SIGNAL(u'activated(int)'), self.onAdvancedToChapter) - QtCore.QObject.connect(self.quickSearchComboBox, - QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) + QtCore.QObject.connect(self.quickSearchEdit, + QtCore.SIGNAL(u'searchTypeChanged(int)'), self.updateAutoCompleter) QtCore.QObject.connect(self.quickVersionComboBox, QtCore.SIGNAL(u'activated(int)'), self.updateAutoCompleter) # Buttons @@ -238,20 +237,15 @@ class BibleMediaItem(MediaManagerItem): def retranslateUi(self): log.debug(u'retranslateUi') - self.quickVersionLabel.setText( - translate('BiblesPlugin.MediaItem', 'Version:')) + self.quickVersionLabel.setText(u'%s:' % UiStrings.Version) self.quickSecondLabel.setText( translate('BiblesPlugin.MediaItem', 'Second:')) - self.quickSearchTypeLabel.setText( - translate('BiblesPlugin.MediaItem', 'Search type:')) self.quickSearchLabel.setText( translate('BiblesPlugin.MediaItem', 'Find:')) - self.quickSearchButton.setText( - translate('BiblesPlugin.MediaItem', 'Search')) + self.quickSearchButton.setText(UiStrings.Search) self.quickClearLabel.setText( translate('BiblesPlugin.MediaItem', 'Results:')) - self.advancedVersionLabel.setText( - translate('BiblesPlugin.MediaItem', 'Version:')) + self.advancedVersionLabel.setText(u'%s:' % UiStrings.Version) self.advancedSecondLabel.setText( translate('BiblesPlugin.MediaItem', 'Second:')) self.advancedBookLabel.setText( @@ -266,12 +260,7 @@ class BibleMediaItem(MediaManagerItem): translate('BiblesPlugin.MediaItem', 'To:')) self.advancedClearLabel.setText( translate('BiblesPlugin.MediaItem', 'Results:')) - self.advancedSearchButton.setText( - translate('BiblesPlugin.MediaItem', 'Search')) - self.quickSearchComboBox.addItem( - translate('BiblesPlugin.MediaItem', 'Verse Search')) - self.quickSearchComboBox.addItem( - translate('BiblesPlugin.MediaItem', 'Text Search')) + self.advancedSearchButton.setText(UiStrings.Search) self.quickClearComboBox.addItem( translate('BiblesPlugin.MediaItem', 'Clear')) self.quickClearComboBox.addItem( @@ -369,11 +358,11 @@ class BibleMediaItem(MediaManagerItem): """ This updates the bible book completion list for the search field. The completion depends on the bible. It is only updated when we are doing a - verse search, otherwise the auto completion list is removed. + reference search, otherwise the auto completion list is removed. """ books = [] - # We have to do a 'Verse Search'. - if self.quickSearchComboBox.currentIndex() == 0: + # We have to do a 'Reference Search'. + if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference: bibles = self.parent.manager.get_bibles() bible = unicode(self.quickVersionComboBox.currentText()) if bible: @@ -493,7 +482,7 @@ class BibleMediaItem(MediaManagerItem): self.listView.clear() if self.listView.count() != 0: self.__checkSecondBible(bible, second_bible) - else: + elif self.search_results: self.displayResults(bible, second_bible) Receiver.send_message(u'cursor_normal') self.advancedSearchButton.setEnabled(True) @@ -502,7 +491,7 @@ class BibleMediaItem(MediaManagerItem): def onQuickSearchButton(self): """ Does a quick search and saves the search results. Quick search can - either be "Verse Search" or "Text Search". + either be "Reference Search" or "Text Search". """ log.debug(u'Quick Search Button pressed') self.quickSearchButton.setEnabled(False) @@ -510,8 +499,8 @@ class BibleMediaItem(MediaManagerItem): bible = unicode(self.quickVersionComboBox.currentText()) second_bible = unicode(self.quickSecondComboBox.currentText()) text = unicode(self.quickSearchEdit.text()) - if self.quickSearchComboBox.currentIndex() == 0: - # We are doing a 'Verse Search'. + if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference: + # We are doing a 'Reference Search'. self.search_results = self.parent.manager.get_verses(bible, text) if second_bible and self.search_results: self.second_search_results = self.parent.manager.get_verses( @@ -679,12 +668,12 @@ class BibleMediaItem(MediaManagerItem): raw_slides.append(bible_text.rstrip()) bible_text = u'' # If we are 'Verse Per Slide' then create a new slide. - elif self.parent.settings_tab.layout_style == 0: + elif self.settings.layout_style == LayoutStyle.VersePerSlide: bible_text = u'%s %s' % (verse_text, text) raw_slides.append(bible_text.rstrip()) bible_text = u'' # If we are 'Verse Per Line' then force a new line. - elif self.parent.settings_tab.layout_style == 1: + elif self.settings.layout_style == LayoutStyle.VersePerLine: bible_text = u'%s %s %s\n' % (bible_text, verse_text, text) # We have to be 'Continuous'. else: @@ -702,22 +691,19 @@ class BibleMediaItem(MediaManagerItem): raw_slides.append(bible_text.lstrip()) bible_text = u'' # Service Item: Capabilities - if self.parent.settings_tab.layout_style == 2 and not second_bible: + if self.settings.layout_style == LayoutStyle.Continuous and \ + not second_bible: # Split the line but do not replace line breaks in renderer. service_item.add_capability(ItemCapabilities.NoLineBreaks) service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsLoop) # Service Item: Title - for title in raw_title: - if not service_item.title: - service_item.title = title - else: - service_item.title += u', ' + title + service_item.title = u', '.join(raw_title) # Service Item: Theme - if len(self.parent.settings_tab.bible_theme) == 0: + if len(self.settings.bible_theme) == 0: service_item.theme = None else: - service_item.theme = self.parent.settings_tab.bible_theme + service_item.theme = self.settings.bible_theme for slide in raw_slides: service_item.add_from_text(slide[:30], slide) if service_item.raw_footer: @@ -826,16 +812,15 @@ class BibleMediaItem(MediaManagerItem): The verse number (int). """ verse_separator = get_reference_match(u'sep_v_display') - if not self.parent.settings_tab.show_new_chapters or \ - old_chapter != chapter: + if not self.settings.show_new_chapters or old_chapter != chapter: verse_text = unicode(chapter) + verse_separator + unicode(verse) else: verse_text = unicode(verse) - if self.parent.settings_tab.display_style == 1: + if self.settings.display_style == DisplayStyle.Round: verse_text = u'{su}(' + verse_text + u'){/su}' - elif self.parent.settings_tab.display_style == 2: + elif self.settings.display_style == DisplayStyle.Curly: verse_text = u'{su}{' + verse_text + u'}{/su}' - elif self.parent.settings_tab.display_style == 3: + elif self.settings.display_style == DisplayStyle.Square: verse_text = u'{su}[' + verse_text + u']{/su}' else: verse_text = u'{su}' + verse_text + u'{/su}' diff --git a/openlp/plugins/bibles/lib/openlp1.py b/openlp/plugins/bibles/lib/openlp1.py index 2df6b1677..03011fa5e 100644 --- a/openlp/plugins/bibles/lib/openlp1.py +++ b/openlp/plugins/bibles/lib/openlp1.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,7 +29,8 @@ import sqlite from PyQt4 import QtCore -from openlp.core.lib import Receiver, translate +from openlp.core.lib import Receiver +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) @@ -45,8 +46,6 @@ class OpenLP1Bible(BibleDB): log.debug(self.__class__.__name__) BibleDB.__init__(self, parent, **kwargs) self.filename = kwargs[u'filename'] - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): """ @@ -73,8 +72,7 @@ class OpenLP1Bible(BibleDB): abbreviation = unicode(book[3], u'cp1252') self.create_book(name, abbreviation, testament_id) # Update the progess bar. - self.wizard.incrementProgressBar(unicode(translate( - 'BiblesPlugin.OpenLP1Import', 'Importing %s...')) % name) + self.wizard.incrementProgressBar(WizardStrings.ImportingType % name) # Import the verses for this book. cursor.execute(u'SELECT chapter, verse, text || \'\' AS text FROM ' 'verse WHERE book_id=%s' % book_id) diff --git a/openlp/plugins/bibles/lib/opensong.py b/openlp/plugins/bibles/lib/opensong.py index 9a0fd110d..356483986 100644 --- a/openlp/plugins/bibles/lib/opensong.py +++ b/openlp/plugins/bibles/lib/opensong.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -46,8 +46,6 @@ class OpenSongBible(BibleDB): log.debug(self.__class__.__name__) BibleDB.__init__(self, parent, **kwargs) self.filename = kwargs['filename'] - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): """ diff --git a/openlp/plugins/bibles/lib/osis.py b/openlp/plugins/bibles/lib/osis.py index 4a001987d..000471b96 100644 --- a/openlp/plugins/bibles/lib/osis.py +++ b/openlp/plugins/bibles/lib/osis.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -41,15 +41,11 @@ log = logging.getLogger(__name__) class OSISBible(BibleDB): """ - OSIS Bible format importer class. + `OSIS `_ Bible format importer class. """ log.info(u'BibleOSISImpl loaded') def __init__(self, parent, **kwargs): - """ - Constructor to create and set up an instance of the OpenSongBible - class. This class is used to import Bibles from OpenSong's XML format. - """ log.debug(self.__class__.__name__) BibleDB.__init__(self, parent, **kwargs) self.filename = kwargs[u'filename'] @@ -69,7 +65,7 @@ class OSISBible(BibleDB): self.q1_regex = re.compile(r'') self.q2_regex = re.compile(r'') self.trans_regex = re.compile(r'(.*?)') - self.divineName_regex = re.compile( + self.divine_name_regex = re.compile( r'(.*?)') self.spaces_regex = re.compile(r'([ ]{2,})') filepath = os.path.join( @@ -86,8 +82,6 @@ class OSISBible(BibleDB): finally: if fbibles: fbibles.close() - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): """ @@ -126,7 +120,7 @@ class OSISBible(BibleDB): verse_text = match.group(4) if not db_book or db_book.name != self.books[book][0]: log.debug(u'New book: "%s"', self.books[book][0]) - if book == u'Matt': + if book == u'Matt' or book == u'Jdt': testament += 1 db_book = self.create_book( unicode(self.books[book][0]), @@ -161,7 +155,7 @@ class OSISBible(BibleDB): verse_text = self.q1_regex.sub(u'"', verse_text) verse_text = self.q2_regex.sub(u'\'', verse_text) verse_text = self.trans_regex.sub(u'', verse_text) - verse_text = self.divineName_regex.sub(u'', verse_text) + verse_text = self.divine_name_regex.sub(u'', verse_text) verse_text = verse_text.replace(u'', u'')\ .replace(u'', u'').replace(u'', u'')\ .replace(u'', u'').replace(u'', u'')\ diff --git a/openlp/plugins/bibles/resources/osisbooks.csv b/openlp/plugins/bibles/resources/osisbooks.csv index c14f76ded..372cbd92d 100644 --- a/openlp/plugins/bibles/resources/osisbooks.csv +++ b/openlp/plugins/bibles/resources/osisbooks.csv @@ -64,3 +64,13 @@ Jas,James,Jas 3John,3 John,3John Jude,Jude,Jude Rev,Revelation,Rev +Jdt,Judith,Jdt +Wis,Wisdom,Wis +Tob,Tobit,Tob +Sir,Sirach,Sir +Bar,Baruch,Bar +1Macc,1 Maccabees,1Macc +2Macc,2 Maccabees,2Macc +AddDan,Rest of Daniel,AddDan +AddEsth,Rest of Esther,AddEsth +PrMan,Prayer of Manasses,PrMan diff --git a/openlp/plugins/custom/__init__.py b/openlp/plugins/custom/__init__.py index fb86201a3..3a1e4461a 100644 --- a/openlp/plugins/custom/__init__.py +++ b/openlp/plugins/custom/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,4 +27,4 @@ The :mod:`custom` module provides the Custom plugin which allows custom, themed, text based items to be displayed without having to misuse another item type. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/custom/customplugin.py b/openlp/plugins/custom/customplugin.py index 54cb38501..c6c129e68 100644 --- a/openlp/plugins/custom/customplugin.py +++ b/openlp/plugins/custom/customplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -47,21 +47,14 @@ class CustomPlugin(Plugin): log.info(u'Custom Plugin loaded') def __init__(self, plugin_helpers): - Plugin.__init__(self, u'Custom', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Custom', u'1.9.4', plugin_helpers, + CustomMediaItem, CustomTab) self.weight = -5 self.manager = Manager(u'custom', init_schema) - self.edit_custom_form = EditCustomForm(self.manager) + self.edit_custom_form = EditCustomForm(self) self.icon_path = u':/plugins/plugin_custom.png' self.icon = build_icon(self.icon_path) - def getSettingsTab(self): - visible_name = self.getString(StringContent.VisibleName) - return CustomTab(self.name, visible_name[u'title']) - - def getMediaManagerItem(self): - # Create the ManagerItem object - return CustomMediaItem(self, self, self.icon) - def about(self): about_text = translate('CustomPlugin', 'Custom Plugin' '
The custom plugin provides the ability to set up custom ' @@ -112,54 +105,20 @@ class CustomPlugin(Plugin): u'title': translate('CustomsPlugin', 'Custom', 'container title') } # Middle Header Bar - ## Import Action ## - self.textStrings[StringContent.Import] = { - u'title': translate('CustomsPlugin', 'Import'), - u'tooltip': translate('CustomsPlugin', - 'Import a Custom') - } - ## Load Action ## - self.textStrings[StringContent.Load] = { - u'title': translate('CustomsPlugin', 'Load'), - u'tooltip': translate('CustomsPlugin', - 'Load a new Custom') - } - ## New Action ## - self.textStrings[StringContent.New] = { - u'title': translate('CustomsPlugin', 'Add'), - u'tooltip': translate('CustomsPlugin', - 'Add a new Custom') - } - ## Edit Action ## - self.textStrings[StringContent.Edit] = { - u'title': translate('CustomsPlugin', 'Edit'), - u'tooltip': translate('CustomsPlugin', - 'Edit the selected Custom') - } - ## Delete Action ## - self.textStrings[StringContent.Delete] = { - u'title': translate('CustomsPlugin', 'Delete'), - u'tooltip': translate('CustomsPlugin', - 'Delete the selected Custom') - } - ## Preview Action ## - self.textStrings[StringContent.Preview] = { - u'title': translate('CustomsPlugin', 'Preview'), - u'tooltip': translate('CustomsPlugin', - 'Preview the selected Custom') - } - ## Send Live Action ## - self.textStrings[StringContent.Live] = { - u'title': translate('CustomsPlugin', 'Live'), - u'tooltip': translate('CustomsPlugin', - 'Send the selected Custom live') - } - ## Add to Service Action ## - self.textStrings[StringContent.Service] = { - u'title': translate('CustomsPlugin', 'Service'), - u'tooltip': translate('CustomsPlugin', + tooltips = { + u'load': translate('CustomsPlugin', 'Load a new Custom'), + u'import': translate('CustomsPlugin', 'Import a Custom'), + u'new': translate('CustomsPlugin', 'Add a new Custom'), + u'edit': translate('CustomsPlugin', 'Edit the selected Custom'), + u'delete': translate('CustomsPlugin', 'Delete the selected Custom'), + u'preview': translate('CustomsPlugin', + 'Preview the selected Custom'), + u'live': translate('CustomsPlugin', + 'Send the selected Custom live'), + u'service': translate('CustomsPlugin', 'Add the selected Custom to the service') } + self.setPluginUiTextStrings(tooltips) def finalise(self): """ diff --git a/openlp/plugins/custom/forms/__init__.py b/openlp/plugins/custom/forms/__init__.py index 60f1395fb..c12d29c07 100644 --- a/openlp/plugins/custom/forms/__init__.py +++ b/openlp/plugins/custom/forms/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### from editcustomform import EditCustomForm -from editcustomslideform import EditCustomSlideForm \ No newline at end of file +from editcustomslideform import EditCustomSlideForm diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index b7887aa90..12ac3ed7e 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate -from openlp.core.lib.ui import create_save_cancel_button_box, \ +from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box, \ create_delete_push_button, create_up_down_push_button_set class Ui_CustomEditDialog(object): @@ -94,7 +94,7 @@ class Ui_CustomEditDialog(object): self.creditLabel.setBuddy(self.creditEdit) self.bottomFormLayout.addRow(self.creditLabel, self.creditEdit) self.dialogLayout.addLayout(self.bottomFormLayout) - self.buttonBox = create_save_cancel_button_box(customEditDialog) + self.buttonBox = create_accept_reject_button_box(customEditDialog) self.previewButton = QtGui.QPushButton() self.buttonBox.addButton( self.previewButton, QtGui.QDialogButtonBox.ActionRole) @@ -107,13 +107,11 @@ class Ui_CustomEditDialog(object): translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides')) self.titleLabel.setText( translate('CustomPlugin.EditCustomForm', '&Title:')) - self.addButton.setText( - translate('CustomPlugin.EditCustomForm', '&Add')) + self.addButton.setText(UiStrings.Add) self.addButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Add a new slide at ' 'bottom.')) - self.editButton.setText( - translate('CustomPlugin.EditCustomForm', '&Edit')) + self.editButton.setText(UiStrings.Edit) self.editButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Edit the selected ' 'slide.')) @@ -126,5 +124,4 @@ class Ui_CustomEditDialog(object): translate('CustomPlugin.EditCustomForm', 'The&me:')) self.creditLabel.setText( translate('CustomPlugin.EditCustomForm', '&Credits:')) - self.previewButton.setText( - translate('CustomPlugin.EditCustomForm', 'Save && Preview')) + self.previewButton.setText(UiStrings.SaveAndPreview) diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index b667cd529..232cb1e38 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -42,14 +42,15 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): Class documentation goes here. """ log.info(u'Custom Editor loaded') - def __init__(self, manager, parent=None): + def __init__(self, parent): """ Constructor """ - QtGui.QDialog.__init__(self, parent) + QtGui.QDialog.__init__(self) + self.parent = parent + self.manager = self.parent.manager self.setupUi(self) # Create other objects and forms. - self.manager = manager self.editSlideForm = EditCustomSlideForm(self) # Connecting signals and slots QtCore.QObject.connect(self.previewButton, diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py index 24c40d6e6..08610954f 100644 --- a/openlp/plugins/custom/forms/editcustomslidedialog.py +++ b/openlp/plugins/custom/forms/editcustomslidedialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate, SpellTextEdit -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_CustomSlideEditDialog(object): def setupUi(self, customSlideEditDialog): @@ -37,7 +37,7 @@ class Ui_CustomSlideEditDialog(object): self.slideTextEdit = SpellTextEdit(self) self.slideTextEdit.setObjectName(u'slideTextEdit') self.dialogLayout.addWidget(self.slideTextEdit) - self.buttonBox = create_save_cancel_button_box(customSlideEditDialog) + self.buttonBox = create_accept_reject_button_box(customSlideEditDialog) self.splitButton = QtGui.QPushButton(customSlideEditDialog) self.splitButton.setObjectName(u'splitButton') self.buttonBox.addButton(self.splitButton, diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py index c8b74a387..2aea81482 100644 --- a/openlp/plugins/custom/forms/editcustomslideform.py +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -71,5 +71,5 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): """ if self.slideTextEdit.textCursor().columnNumber() != 0: self.slideTextEdit.insertPlainText(u'\n') - self.slideTextEdit.insertPlainText(u'[---]\n' ) - self.slideTextEdit.setFocus() \ No newline at end of file + self.slideTextEdit.insertPlainText(u'[---]\n') + self.slideTextEdit.setFocus() diff --git a/openlp/plugins/custom/lib/__init__.py b/openlp/plugins/custom/lib/__init__.py index d3d8312d7..0c53505ac 100644 --- a/openlp/plugins/custom/lib/__init__.py +++ b/openlp/plugins/custom/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ from customxmlhandler import CustomXMLBuilder, CustomXMLParser from mediaitem import CustomMediaItem -from customtab import CustomTab \ No newline at end of file +from customtab import CustomTab diff --git a/openlp/plugins/custom/lib/customtab.py b/openlp/plugins/custom/lib/customtab.py index 3c1b848aa..9b61f8f15 100644 --- a/openlp/plugins/custom/lib/customtab.py +++ b/openlp/plugins/custom/lib/customtab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/custom/lib/customxmlhandler.py b/openlp/plugins/custom/lib/customxmlhandler.py index 1171ce6bd..5ea941e35 100644 --- a/openlp/plugins/custom/lib/customxmlhandler.py +++ b/openlp/plugins/custom/lib/customxmlhandler.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -153,4 +153,4 @@ class CustomXMLParser(object): """ Debugging aid to dump XML so that we can see what we have. """ - return dump(self.custom_xml) \ No newline at end of file + return dump(self.custom_xml) diff --git a/openlp/plugins/custom/lib/db.py b/openlp/plugins/custom/lib/db.py index 1fbc04980..74155ad96 100644 --- a/openlp/plugins/custom/lib/db.py +++ b/openlp/plugins/custom/lib/db.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -59,4 +59,4 @@ def init_schema(url): mapper(CustomSlide, custom_slide_table) metadata.create_all(checkfirst=True) - return session \ No newline at end of file + return session diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 908c4e18d..c0c7a7e86 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,18 +28,14 @@ import logging from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, \ - Receiver, ItemCapabilities, translate, check_item_selected +from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ + check_item_selected +from openlp.core.lib.ui import UiStrings from openlp.plugins.custom.lib import CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide log = logging.getLogger(__name__) -class CustomListView(BaseListWithDnD): - def __init__(self, parent=None): - self.PluginName = u'Custom' - BaseListWithDnD.__init__(self, parent) - class CustomMediaItem(MediaManagerItem): """ This is the custom media manager item for Custom Slides. @@ -48,9 +44,6 @@ class CustomMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'custom/custom' - # this next is a class, not an instance of a class - it will - # be instanced by the base MediaManagerItem - self.ListViewWithDnD_class = CustomListView MediaManagerItem.__init__(self, parent, self, icon) self.singleServiceItem = False # Holds information about whether the edit is remotly triggered and @@ -62,7 +55,7 @@ class CustomMediaItem(MediaManagerItem): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'custom_edit'), self.onRemoteEdit) QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'custom_edit_clear' ), self.onRemoteEditClear) + QtCore.SIGNAL(u'custom_edit_clear'), self.onRemoteEditClear) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'custom_load_list'), self.initialise) QtCore.QObject.connect(Receiver.get_receiver(), @@ -116,9 +109,7 @@ class CustomMediaItem(MediaManagerItem): """ Edit a custom item """ - if check_item_selected(self.listView, - translate('CustomPlugin.MediaItem', - 'You haven\'t selected an item to edit.')): + if check_item_selected(self.listView, UiStrings.SelectEdit): item = self.listView.currentItem() item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] self.parent.edit_custom_form.loadCustom(item_id, False) @@ -129,9 +120,7 @@ class CustomMediaItem(MediaManagerItem): """ Remove a custom item from the list and database """ - if check_item_selected(self.listView, - translate('CustomPlugin.MediaItem', - 'You haven\'t selected an item to delete.')): + if check_item_selected(self.listView, UiStrings.SelectDelete): row_list = [item.row() for item in self.listView.selectedIndexes()] row_list.sort(reverse=True) id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0] diff --git a/openlp/plugins/images/__init__.py b/openlp/plugins/images/__init__.py index 6ea473c72..13ea2592a 100644 --- a/openlp/plugins/images/__init__.py +++ b/openlp/plugins/images/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ """ The :mod:`images` module provides the Images plugin. The Images plugin provides the facility to display images from OpenLP. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index ea118d3ec..84d7a71cc 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -35,15 +35,12 @@ class ImagePlugin(Plugin): log.info(u'Image Plugin loaded') def __init__(self, plugin_helpers): - Plugin.__init__(self, u'Images', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Images', u'1.9.4', plugin_helpers, + ImageMediaItem) self.weight = -7 self.icon_path = u':/plugins/plugin_images.png' self.icon = build_icon(self.icon_path) - def getMediaManagerItem(self): - # Create the MediaManagerItem object. - return ImageMediaItem(self, self, self.icon) - def about(self): about_text = translate('ImagePlugin', 'Image Plugin' '
The image plugin provides displaying of images.
One ' @@ -72,45 +69,15 @@ class ImagePlugin(Plugin): u'title': translate('ImagePlugin', 'Images', 'container title') } # Middle Header Bar - ## Load Button ## - self.textStrings[StringContent.Load] = { - u'title': translate('ImagePlugin', 'Load'), - u'tooltip': translate('ImagePlugin', - 'Load a new Image') - } - ## New Button ## - self.textStrings[StringContent.New] = { - u'title': translate('ImagePlugin', 'Add'), - u'tooltip': translate('ImagePlugin', - 'Add a new Image') - } - ## Edit Button ## - self.textStrings[StringContent.Edit] = { - u'title': translate('ImagePlugin', 'Edit'), - u'tooltip': translate('ImagePlugin', - 'Edit the selected Image') - } - ## Delete Button ## - self.textStrings[StringContent.Delete] = { - u'title': translate('ImagePlugin', 'Delete'), - u'tooltip': translate('ImagePlugin', - 'Delete the selected Image') - } - ## Preview ## - self.textStrings[StringContent.Preview] = { - u'title': translate('ImagePlugin', 'Preview'), - u'tooltip': translate('ImagePlugin', - 'Preview the selected Image') - } - ## Live Button ## - self.textStrings[StringContent.Live] = { - u'title': translate('ImagePlugin', 'Live'), - u'tooltip': translate('ImagePlugin', - 'Send the selected Image live') - } - ## Add to service Button ## - self.textStrings[StringContent.Service] = { - u'title': translate('ImagePlugin', 'Service'), - u'tooltip': translate('ImagePlugin', + tooltips = { + u'load': translate('ImagePlugin', 'Load a new Image'), + u'import': u'', + u'new': translate('ImagePlugin', 'Add a new Image'), + u'edit': translate('ImagePlugin', 'Edit the selected Image'), + u'delete': translate('ImagePlugin', 'Delete the selected Image'), + u'preview': translate('ImagePlugin', 'Preview the selected Image'), + u'live': translate('ImagePlugin', 'Send the selected Image live'), + u'service': translate('ImagePlugin', 'Add the selected Image to the service') } + self.setPluginUiTextStrings(tooltips) diff --git a/openlp/plugins/images/lib/__init__.py b/openlp/plugins/images/lib/__init__.py index 6ff2a295b..34c9f1ca8 100644 --- a/openlp/plugins/images/lib/__init__.py +++ b/openlp/plugins/images/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -24,4 +24,4 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### -from mediaitem import ImageMediaItem \ No newline at end of file +from mediaitem import ImageMediaItem diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 71027881c..e6fdfe7db 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,21 +29,14 @@ import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - ItemCapabilities, SettingsManager, translate, check_item_selected, \ - check_directory_exists, Receiver -from openlp.core.lib.ui import critical_error_message_box +from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \ + SettingsManager, translate, check_item_selected, check_directory_exists, \ + Receiver +from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.utils import AppLocation, delete_file, get_images_filter log = logging.getLogger(__name__) -# We have to explicitly create separate classes for each plugin -# in order for DnD to the Service manager to work correctly. -class ImageListView(BaseListWithDnD): - def __init__(self, parent=None): - self.PluginName = u'Images' - BaseListWithDnD.__init__(self, parent) - class ImageMediaItem(MediaManagerItem): """ This is the custom media manager item for images. @@ -52,27 +45,20 @@ class ImageMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'images/image' - # This next is a class, not an instance of a class - it will - # be instanced by the base MediaManagerItem. - self.ListViewWithDnD_class = ImageListView MediaManagerItem.__init__(self, parent, self, icon) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged) def retranslateUi(self): - self.OnNewPrompt = translate('ImagePlugin.MediaItem', + self.onNewPrompt = translate('ImagePlugin.MediaItem', 'Select Image(s)') file_formats = get_images_filter() - self.OnNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats, - unicode(translate('ImagePlugin.MediaItem', 'All Files'))) - self.replaceAction.setText( - translate('ImagePlugin.MediaItem', 'Replace Background')) - self.replaceAction.setToolTip( - translate('ImagePlugin.MediaItem', 'Replace Live Background')) - self.resetAction.setText( - translate('ImagePlugin.MediaItem', 'Reset Background')) - self.resetAction.setToolTip( - translate('ImagePlugin.MediaItem', 'Reset Live Background')) + self.onNewFileMasks = u'%s;;%s (*.*) (*)' % (file_formats, + UiStrings.AllFiles) + self.replaceAction.setText(UiStrings.ReplaceBG) + self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG) + self.resetAction.setText(UiStrings.ResetBG) + self.resetAction.setToolTip(UiStrings.ResetLiveBG) def requiredIcons(self): MediaManagerItem.requiredIcons(self) @@ -84,8 +70,6 @@ class ImageMediaItem(MediaManagerItem): def initialise(self): log.debug(u'initialise') self.listView.clear() - self.listView.setSelectionMode( - QtGui.QAbstractItemView.ExtendedSelection) self.listView.setIconSize(QtCore.QSize(88, 50)) self.servicePath = os.path.join( AppLocation.get_section_data_path(self.settingsSection), @@ -141,8 +125,7 @@ class ImageMediaItem(MediaManagerItem): def generateSlideData(self, service_item, item=None, xmlVersion=False): items = self.listView.selectedIndexes() if items: - service_item.title = unicode( - translate('ImagePlugin.MediaItem', 'Images')) + service_item.title = unicode(self.plugin.nameStrings[u'plural']) service_item.add_capability(ItemCapabilities.AllowsMaintain) service_item.add_capability(ItemCapabilities.AllowsPreview) service_item.add_capability(ItemCapabilities.AllowsLoop) @@ -214,8 +197,7 @@ class ImageMediaItem(MediaManagerItem): self.parent.liveController.display.directImage(name, filename) self.resetAction.setVisible(True) else: - critical_error_message_box( - translate('ImagePlugin.MediaItem', 'Live Background Error'), + critical_error_message_box(UiStrings.LiveBGError, unicode(translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, ' 'the image file "%s" no longer exists.')) % filename) diff --git a/openlp/plugins/media/__init__.py b/openlp/plugins/media/__init__.py index 7be6e5ea9..c13c59ef6 100644 --- a/openlp/plugins/media/__init__.py +++ b/openlp/plugins/media/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,4 +28,4 @@ The :mod:`media` module provides the Media plugin which allows OpenLP to display videos. The media supported depends not only on the Python support but also extensively on the codecs installed on the underlying operating system being picked up and usable by Python. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/media/lib/__init__.py b/openlp/plugins/media/lib/__init__.py index 59d7642df..cb4806631 100644 --- a/openlp/plugins/media/lib/__init__.py +++ b/openlp/plugins/media/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,4 +27,4 @@ from mediaitem import MediaMediaItem from mediatab import MediaTab -__all__ = ['MediaMediaItem'] \ No newline at end of file +__all__ = ['MediaMediaItem'] diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index ea1b679b4..40ea7abb1 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,18 +29,13 @@ import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - ItemCapabilities, SettingsManager, translate, check_item_selected, Receiver -from openlp.core.lib.ui import critical_error_message_box +from openlp.core.lib import MediaManagerItem, build_icon, ItemCapabilities, \ + SettingsManager, translate, check_item_selected, Receiver +from openlp.core.lib.ui import UiStrings, critical_error_message_box +from PyQt4.phonon import Phonon log = logging.getLogger(__name__) -class MediaListView(BaseListWithDnD): - def __init__(self, parent=None): - self.PluginName = u'Media' - BaseListWithDnD.__init__(self, parent) - - class MediaMediaItem(MediaManagerItem): """ This is the custom media manager item for Media Slides. @@ -50,30 +45,28 @@ class MediaMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'images/image' self.background = False - # this next is a class, not an instance of a class - it will - # be instanced by the base MediaManagerItem - self.ListViewWithDnD_class = MediaListView self.PreviewFunction = QtGui.QPixmap( u':/media/media_video.png').toImage() MediaManagerItem.__init__(self, parent, self, icon) self.singleServiceItem = False + self.mediaObject = Phonon.MediaObject(self) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'video_background_replaced'), self.videobackgroundReplaced) + QtCore.QObject.connect(self.mediaObject, + QtCore.SIGNAL(u'stateChanged(Phonon::State, Phonon::State)'), + self.videoStart) def retranslateUi(self): - self.OnNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media') - self.OnNewFileMasks = unicode(translate('MediaPlugin.MediaItem', - 'Videos (%s);;Audio (%s);;All files (*)')) % \ - (self.parent.video_list, self.parent.audio_list) - self.replaceAction.setText( - translate('MediaPlugin.MediaItem', 'Replace Background')) - self.replaceAction.setToolTip( - translate('MediaPlugin.MediaItem', 'Replace Live Background')) - self.resetAction.setText( - translate('MediaPlugin.MediaItem', 'Reset Background')) - self.resetAction.setToolTip( - translate('ImagePlugin.MediaItem', 'Reset Live Background')) + self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media') + self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem', + 'Videos (%s);;Audio (%s);;%s (*)')) % ( + u' '.join(self.parent.video_extensions_list), + u' '.join(self.parent.audio_extensions_list), UiStrings.AllFiles) + self.replaceAction.setText(UiStrings.ReplaceBG) + self.replaceAction.setToolTip(UiStrings.ReplaceLiveBG) + self.resetAction.setText(UiStrings.ResetBG) + self.resetAction.setToolTip(UiStrings.ResetLiveBG) def requiredIcons(self): MediaManagerItem.requiredIcons(self) @@ -120,8 +113,7 @@ class MediaMediaItem(MediaManagerItem): self.parent.liveController.display.video(filename, 0, True) self.resetAction.setVisible(True) else: - critical_error_message_box(translate('MediaPlugin.MediaItem', - 'Live Background Error'), + critical_error_message_box(UiStrings.LiveBGError, unicode(translate('MediaPlugin.MediaItem', 'There was a problem replacing your background, ' 'the media file "%s" no longer exists.')) % filename) @@ -133,13 +125,21 @@ class MediaMediaItem(MediaManagerItem): return False filename = unicode(item.data(QtCore.Qt.UserRole).toString()) if os.path.exists(filename): - service_item.title = unicode( - translate('MediaPlugin.MediaItem', 'Media')) + self.mediaState = None + self.mediaObject.stop() + self.mediaObject.clearQueue() + self.mediaObject.setCurrentSource(Phonon.MediaSource(filename)) + self.mediaObject.play() + service_item.title = unicode(self.plugin.nameStrings[u'singular']) service_item.add_capability(ItemCapabilities.RequiresMedia) + service_item.add_capability(ItemCapabilities.AllowsVarableStartTime) # force a nonexistent theme service_item.theme = -1 frame = u':/media/image_clapperboard.png' (path, name) = os.path.split(filename) + while not self.mediaState: + Receiver.send_message(u'openlp_process_events') + service_item.media_length = self.mediaLength service_item.add_from_command(path, name, frame) return True else: @@ -151,8 +151,7 @@ class MediaMediaItem(MediaManagerItem): return False def initialise(self): - self.listView.setSelectionMode( - QtGui.QAbstractItemView.ExtendedSelection) + self.listView.clear() self.listView.setIconSize(QtCore.QSize(88, 50)) self.loadList(SettingsManager.load_list(self.settingsSection, self.settingsSection)) @@ -178,3 +177,12 @@ class MediaMediaItem(MediaManagerItem): item_name.setIcon(build_icon(img)) item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file)) self.listView.addItem(item_name) + + def videoStart(self, newState, oldState): + """ + Start the video at a predetermined point. + """ + if newState == Phonon.PlayingState: + self.mediaState = newState + self.mediaLength = self.mediaObject.totalTime()/1000 + self.mediaObject.stop() diff --git a/openlp/plugins/media/lib/mediatab.py b/openlp/plugins/media/lib/mediatab.py index 461fbf4ae..995816860 100644 --- a/openlp/plugins/media/lib/mediatab.py +++ b/openlp/plugins/media/lib/mediatab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,8 +32,8 @@ class MediaTab(SettingsTab): """ MediaTab is the Media settings tab in the settings dialog. """ - def __init__(self, title): - SettingsTab.__init__(self, title) + def __init__(self, title, visible_title): + SettingsTab.__init__(self, title, visible_title) def setupUi(self): self.setObjectName(u'MediaTab') @@ -53,9 +53,8 @@ class MediaTab(SettingsTab): self.onUsePhononCheckBoxChanged) def retranslateUi(self): - self.tabTitleVisible = translate('MediaPlugin.MediaTab', 'Media') - self.mediaModeGroupBox.setTitle(translate('MediaPlugin.MediaTab', - 'Media Display')) + self.mediaModeGroupBox.setTitle( + translate('MediaPlugin.MediaTab', 'Media Display')) self.usePhononCheckBox.setText( translate('MediaPlugin.MediaTab', 'Use Phonon for video playback')) diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index ad6087daf..3438f0279 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -38,49 +38,33 @@ class MediaPlugin(Plugin): log.info(u'%s MediaPlugin loaded', __name__) def __init__(self, plugin_helpers): - Plugin.__init__(self, u'Media', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Media', u'1.9.4', plugin_helpers, + MediaMediaItem, MediaTab) self.weight = -6 self.icon_path = u':/plugins/plugin_media.png' self.icon = build_icon(self.icon_path) # passed with drag and drop messages self.dnd_id = u'Media' - self.audio_list = u'' - self.video_list = u'' + self.audio_extensions_list = [] + self.video_extensions_list = [] mimetypes.init() for mimetype in Phonon.BackendCapabilities.availableMimeTypes(): mimetype = unicode(mimetype) - type = mimetype.split(u'audio/x-') - self.audio_list, mimetype = self._addToList(self.audio_list, - type, mimetype) - type = mimetype.split(u'audio/') - self.audio_list, mimetype = self._addToList(self.audio_list, - type, mimetype) - type = mimetype.split(u'video/x-') - self.video_list, mimetype = self._addToList(self.video_list, - type, mimetype) - type = mimetype.split(u'video/') - self.video_list, mimetype = self._addToList(self.video_list, - type, mimetype) + if mimetype.startswith(u'audio/'): + self._addToList(self.audio_extensions_list, mimetype) + elif mimetype.startswith(u'video/'): + self._addToList(self.video_extensions_list, mimetype) - def _addToList(self, list, value, mimetype): - # Is it a media type - if len(value) == 2: - extensions = mimetypes.guess_all_extensions(unicode(mimetype)) - # we have an extension - if extensions: - for extension in extensions: - if list.find(extension) == -1: - list += u'*%s ' % extension - self.serviceManager.supportedSuffixes(extension[1:]) - mimetype = u'' - return list, mimetype - - def getSettingsTab(self): - return MediaTab(self.name) - - def getMediaManagerItem(self): - # Create the MediaManagerItem object. - return MediaMediaItem(self, self, self.icon) + def _addToList(self, list, mimetype): + # Add all extensions which mimetypes provides us for supported types. + extensions = mimetypes.guess_all_extensions(unicode(mimetype)) + for extension in extensions: + ext = u'*%s' % extension + if ext not in list: + list.append(ext) + self.serviceManager.supportedSuffixes(extension[1:]) + log.info(u'MediaPlugin: %s extensions: %s' % (mimetype, + u' '.join(extensions))) def about(self): about_text = translate('MediaPlugin', 'Media Plugin' @@ -101,45 +85,15 @@ class MediaPlugin(Plugin): u'title': translate('MediaPlugin', 'Media', 'container title') } # Middle Header Bar - ## Load Action ## - self.textStrings[StringContent.Load] = { - u'title': translate('MediaPlugin', 'Load'), - u'tooltip': translate('MediaPlugin', - 'Load a new Media') - } - ## New Action ## - self.textStrings[StringContent.New] = { - u'title': translate('MediaPlugin', 'Add'), - u'tooltip': translate('MediaPlugin', - 'Add a new Media') - } - ## Edit Action ## - self.textStrings[StringContent.Edit] = { - u'title': translate('MediaPlugin', 'Edit'), - u'tooltip': translate('MediaPlugin', - 'Edit the selected Media') - } - ## Delete Action ## - self.textStrings[StringContent.Delete] = { - u'title': translate('MediaPlugin', 'Delete'), - u'tooltip': translate('MediaPlugin', - 'Delete the selected Media') - } - ## Preview Action ## - self.textStrings[StringContent.Preview] = { - u'title': translate('MediaPlugin', 'Preview'), - u'tooltip': translate('MediaPlugin', - 'Preview the selected Media') - } - ## Send Live Action ## - self.textStrings[StringContent.Live] = { - u'title': translate('MediaPlugin', 'Live'), - u'tooltip': translate('MediaPlugin', - 'Send the selected Media live') - } - ## Add to Service Action ## - self.textStrings[StringContent.Service] = { - u'title': translate('MediaPlugin', 'Service'), - u'tooltip': translate('MediaPlugin', + tooltips = { + u'load': translate('MediaPlugin', 'Load a new Media'), + u'import': u'', + u'new': translate('MediaPlugin', 'Add a new Media'), + u'edit': translate('MediaPlugin', 'Edit the selected Media'), + u'delete': translate('MediaPlugin', 'Delete the selected Media'), + u'preview': translate('MediaPlugin', 'Preview the selected Media'), + u'live': translate('MediaPlugin', 'Send the selected Media live'), + u'service': translate('MediaPlugin', 'Add the selected Media to the service') } + self.setPluginUiTextStrings(tooltips) diff --git a/openlp/plugins/presentations/__init__.py b/openlp/plugins/presentations/__init__.py index 317281c23..628816bcf 100644 --- a/openlp/plugins/presentations/__init__.py +++ b/openlp/plugins/presentations/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ """ The :mod:`presentations` module provides the Presentations plugin which allows OpenLP to show presentations from most popular presentation packages. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/presentations/lib/__init__.py b/openlp/plugins/presentations/lib/__init__.py index 2e46cf486..b5575268a 100644 --- a/openlp/plugins/presentations/lib/__init__.py +++ b/openlp/plugins/presentations/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,4 +27,4 @@ from presentationcontroller import PresentationController from messagelistener import MessageListener from mediaitem import PresentationMediaItem -from presentationtab import PresentationTab \ No newline at end of file +from presentationtab import PresentationTab diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index f12d36dc8..48fb85ed3 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -69,7 +69,8 @@ class ImpressController(PresentationController): Initialise the class """ log.debug(u'Initialising') - PresentationController.__init__(self, plugin, u'Impress') + PresentationController.__init__(self, plugin, u'Impress', + ImpressDocument) self.supports = [u'odp'] self.alsosupports = [u'ppt', u'pps', u'pptx', u'ppsx'] self.process = None @@ -144,7 +145,12 @@ class ImpressController(PresentationController): log.debug(u'get COM Desktop OpenOffice') if not self.manager: return None - return self.manager.createInstance(u'com.sun.star.frame.Desktop') + desktop = None + try: + desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop') + except AttributeError: + log.exception(u'Failure to find desktop - Impress may have closed') + return desktop if desktop else None def get_com_servicemanager(self): """ @@ -165,13 +171,15 @@ class ImpressController(PresentationController): log.debug(u'Kill OpenOffice') while self.docs: self.docs[0].close_presentation() - if os.name != u'nt': - desktop = self.get_uno_desktop() - else: - desktop = self.get_com_desktop() - #Sometimes we get a failure and desktop is None - if not desktop: + desktop = None + try: + if os.name != u'nt': + desktop = self.get_uno_desktop() + else: + desktop = self.get_com_desktop() + except: log.exception(u'Failed to find an OpenOffice desktop to terminate') + if not desktop: return docs = desktop.getComponents() if docs.hasElements(): @@ -183,14 +191,6 @@ class ImpressController(PresentationController): except: log.exception(u'Failed to terminate OpenOffice') - def add_doc(self, name): - """ - Called when a new Impress document is opened - """ - log.debug(u'Add Doc OpenOffice') - doc = ImpressDocument(self, name) - self.docs.append(doc) - return doc class ImpressDocument(PresentationDocument): """ @@ -211,8 +211,8 @@ class ImpressDocument(PresentationDocument): """ Called when a presentation is added to the SlideController. It builds the environment, starts communcations with the background - OpenOffice task started earlier. If OpenOffice is not present is is - started. Once the environment is available the presentation is loaded + OpenOffice task started earlier. If OpenOffice is not present is is + started. Once the environment is available the presentation is loaded and started. ``presentation`` @@ -431,35 +431,36 @@ class ImpressDocument(PresentationDocument): def get_slide_text(self, slide_no): """ - Returns the text on the slide + Returns the text on the slide. ``slide_no`` - The slide the text is required for, starting at 1 + The slide the text is required for, starting at 1 + """ + return self.__get_text_from_page(slide_no) + + def get_slide_notes(self, slide_no): + """ + Returns the text in the slide notes. + + ``slide_no`` + The slide the notes are required for, starting at 1 + """ + return self.__get_text_from_page(slide_no, True) + + def __get_text_from_page(self, slide_no, notes=False): + """ + Return any text extracted from the presentation page. + + ``notes`` + A boolean. If set the method searches the notes of the slide. """ - doc = self.document - pages = doc.getDrawPages() text = '' + pages = self.document.getDrawPages() page = pages.getByIndex(slide_no - 1) + if notes: + page = page.getNotesPage() for idx in range(page.getCount()): shape = page.getByIndex(idx) if shape.supportsService("com.sun.star.drawing.Text"): text += shape.getString() + '\n' return text - - def get_slide_notes(self, slide_no): - """ - Returns the text on the slide - - ``slide_no`` - The slide the notes are required for, starting at 1 - """ - doc = self.document - pages = doc.getDrawPages() - text = '' - page = pages.getByIndex(slide_no - 1) - notes = page.getNotesPage() - for idx in range(notes.getCount()): - shape = notes.getByIndex(idx) - if shape.supportsService("com.sun.star.drawing.Text"): - text += shape.getString() + '\n' - return text diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index a0173cb27..2a552a480 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,24 +29,14 @@ import os from PyQt4 import QtCore, QtGui -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - SettingsManager, translate, check_item_selected, Receiver, ItemCapabilities -from openlp.core.lib.ui import critical_error_message_box, media_item_combo_box +from openlp.core.lib import MediaManagerItem, build_icon, SettingsManager, \ + translate, check_item_selected, Receiver, ItemCapabilities +from openlp.core.lib.ui import UiStrings, critical_error_message_box, \ + media_item_combo_box from openlp.plugins.presentations.lib import MessageListener log = logging.getLogger(__name__) -class PresentationListView(BaseListWithDnD): - """ - Class for the list of Presentations - - We have to explicitly create separate classes for each plugin - in order for DnD to the Service manager to work correctly. - """ - def __init__(self, parent=None): - self.PluginName = u'Presentations' - BaseListWithDnD.__init__(self, parent) - class PresentationMediaItem(MediaManagerItem): """ This is the Presentation media manager item for Presentation Items. @@ -61,9 +51,6 @@ class PresentationMediaItem(MediaManagerItem): self.controllers = controllers self.IconPath = u'presentations/presentation' self.Automatic = u'' - # this next is a class, not an instance of a class - it will - # be instanced by the base MediaManagerItem - self.ListViewWithDnD_class = PresentationListView MediaManagerItem.__init__(self, parent, self, icon) self.message_listener = MessageListener(self) QtCore.QObject.connect(Receiver.get_receiver(), @@ -73,7 +60,7 @@ class PresentationMediaItem(MediaManagerItem): """ The name of the plugin media displayed in UI """ - self.OnNewPrompt = translate('PresentationPlugin.MediaItem', + self.onNewPrompt = translate('PresentationPlugin.MediaItem', 'Select Presentation(s)') self.Automatic = translate('PresentationPlugin.MediaItem', 'Automatic') @@ -93,7 +80,7 @@ class PresentationMediaItem(MediaManagerItem): if fileType.find(type) == -1: fileType += u'*.%s ' % type self.parent.serviceManager.supportedSuffixes(type) - self.OnNewFileMasks = unicode(translate('PresentationPlugin.MediaItem', + self.onNewFileMasks = unicode(translate('PresentationPlugin.MediaItem', 'Presentations (%s)')) % fileType def requiredIcons(self): @@ -186,7 +173,7 @@ class PresentationMediaItem(MediaManagerItem): controller_name = self.findControllerByType(filename) if controller_name: controller = self.controllers[controller_name] - doc = controller.add_doc(unicode(file)) + doc = controller.add_document(unicode(file)) thumb = os.path.join(doc.get_thumbnail_folder(), u'icon.png') preview = doc.get_thumbnail_path(1, True) if not preview and not initialLoad: @@ -216,9 +203,7 @@ class PresentationMediaItem(MediaManagerItem): """ Remove a presentation item from the list """ - if check_item_selected(self.listView, - translate('PresentationPlugin.MediaItem', - 'You must select an item to delete.')): + if check_item_selected(self.listView, UiStrings.SelectDelete): items = self.listView.selectedIndexes() row_list = [item.row() for item in items] row_list.sort(reverse=True) @@ -226,7 +211,7 @@ class PresentationMediaItem(MediaManagerItem): filepath = unicode(item.data( QtCore.Qt.UserRole).toString()) for cidx in self.controllers: - doc = self.controllers[cidx].add_doc(filepath) + doc = self.controllers[cidx].add_document(filepath) doc.presentation_deleted() doc.close_presentation() for row in row_list: @@ -260,7 +245,7 @@ class PresentationMediaItem(MediaManagerItem): return False controller = self.controllers[service_item.shortname] (path, name) = os.path.split(filename) - doc = controller.add_doc(filename) + doc = controller.add_document(filename) if doc.get_thumbnail_path(1, True) is None: doc.load_presentation() i = 1 diff --git a/openlp/plugins/presentations/lib/messagelistener.py b/openlp/plugins/presentations/lib/messagelistener.py index 4d926ad3d..4db78f7a5 100644 --- a/openlp/plugins/presentations/lib/messagelistener.py +++ b/openlp/plugins/presentations/lib/messagelistener.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -59,7 +59,7 @@ class Controller(object): self.controller = controller if self.doc is not None: self.shutdown() - self.doc = self.controller.add_doc(file) + self.doc = self.controller.add_document(file) if not self.doc.load_presentation(): # Display error message to user # Inform slidecontroller that the action failed? @@ -213,6 +213,7 @@ class Controller(object): def poll(self): self.doc.poll_slidenumber(self.is_live) + class MessageListener(object): """ This is the Presentation listener who acts on events from the slide diff --git a/openlp/plugins/presentations/lib/powerpointcontroller.py b/openlp/plugins/presentations/lib/powerpointcontroller.py index 012f8534a..4dc9e8f3a 100644 --- a/openlp/plugins/presentations/lib/powerpointcontroller.py +++ b/openlp/plugins/presentations/lib/powerpointcontroller.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -53,7 +53,8 @@ class PowerpointController(PresentationController): Initialise the class """ log.debug(u'Initialising') - PresentationController.__init__(self, plugin, u'Powerpoint') + PresentationController.__init__(self, plugin, u'Powerpoint', + PowerpointDocument) self.supports = [u'ppt', u'pps', u'pptx', u'ppsx'] self.process = None @@ -97,14 +98,6 @@ class PowerpointController(PresentationController): pass self.process = None - def add_doc(self, name): - """ - Called when a new powerpoint document is opened - """ - log.debug(u'Add Doc PowerPoint') - doc = PowerpointDocument(self, name) - self.docs.append(doc) - return doc class PowerpointDocument(PresentationDocument): """ @@ -154,8 +147,10 @@ class PowerpointDocument(PresentationDocument): """ if self.check_thumbnails(): return - self.presentation.Export(os.path.join(self.get_thumbnail_folder(), ''), - 'png', 320, 240) + for num in range(0, self.presentation.Slides.Count): + self.presentation.Slides(num + 1).Export(os.path.join( + self.get_thumbnail_folder(), 'slide%d.png' % (num + 1)), + 'png', 320, 240) def close_presentation(self): """ @@ -291,13 +286,7 @@ class PowerpointDocument(PresentationDocument): ``slide_no`` The slide the text is required for, starting at 1. """ - text = '' - shapes = self.presentation.Slides(slide_no).Shapes - for idx in range(shapes.Count): - shape = shapes(idx + 1) - if shape.HasTextFrame: - text += shape.TextFrame.TextRange.Text + '\n' - return text + return _get_text_from_shapes(self.presentation.Slides(slide_no).Shapes) def get_slide_notes(self, slide_no): """ @@ -306,10 +295,19 @@ class PowerpointDocument(PresentationDocument): ``slide_no`` The slide the notes are required for, starting at 1. """ - text = '' - shapes = self.presentation.Slides(slide_no).NotesPage.Shapes - for idx in range(shapes.Count): - shape = shapes(idx + 1) - if shape.HasTextFrame: - text += shape.TextFrame.TextRange.Text + '\n' - return text \ No newline at end of file + return _get_text_from_shapes( + self.presentation.Slides(slide_no).NotesPage.Shapes) + +def _get_text_from_shapes(shapes): + """ + Returns any text extracted from the shapes on a presentation slide. + + ``shapes`` + A set of shapes to search for text. + """ + text = '' + for idx in range(shapes.Count): + shape = shapes(idx + 1) + if shape.HasTextFrame: + text += shape.TextFrame.TextRange.Text + '\n' + return text diff --git a/openlp/plugins/presentations/lib/pptviewcontroller.py b/openlp/plugins/presentations/lib/pptviewcontroller.py index 4c8e7bf95..0900d1d9d 100644 --- a/openlp/plugins/presentations/lib/pptviewcontroller.py +++ b/openlp/plugins/presentations/lib/pptviewcontroller.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -49,7 +49,8 @@ class PptviewController(PresentationController): """ log.debug(u'Initialising') self.process = None - PresentationController.__init__(self, plugin, u'Powerpoint Viewer') + PresentationController.__init__(self, plugin, u'Powerpoint Viewer', + PptviewDocument) self.supports = [u'ppt', u'pps', u'pptx', u'ppsx'] def check_available(self): @@ -93,14 +94,6 @@ class PptviewController(PresentationController): while self.docs: self.docs[0].close_presentation() - def add_doc(self, name): - """ - Called when a new powerpoint document is opened - """ - log.debug(u'Add Doc PPTView') - doc = PptviewDocument(self, name) - self.docs.append(doc) - return doc class PptviewDocument(PresentationDocument): """ @@ -161,8 +154,9 @@ class PptviewDocument(PresentationDocument): being shut down """ log.debug(u'ClosePresentation') - self.controller.process.ClosePPT(self.pptid) - self.pptid = -1 + if self.controller.process: + self.controller.process.ClosePPT(self.pptid) + self.pptid = -1 self.controller.remove_doc(self) def is_loaded(self): @@ -247,4 +241,4 @@ class PptviewDocument(PresentationDocument): """ Triggers the previous slide on the running presentation """ - self.controller.process.PrevStep(self.pptid) \ No newline at end of file + self.controller.process.PrevStep(self.pptid) diff --git a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py index de0be3e73..1e10def7d 100644 --- a/openlp/plugins/presentations/lib/pptviewlib/ppttest.py +++ b/openlp/plugins/presentations/lib/pptviewlib/ppttest.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -169,4 +169,4 @@ if __name__ == '__main__': app = QtGui.QApplication(sys.argv) qb = PPTViewer() qb.show() - sys.exit(app.exec_()) \ No newline at end of file + sys.exit(app.exec_()) diff --git a/openlp/plugins/presentations/lib/presentationcontroller.py b/openlp/plugins/presentations/lib/presentationcontroller.py index 42f7b654a..bd37746c1 100644 --- a/openlp/plugins/presentations/lib/presentationcontroller.py +++ b/openlp/plugins/presentations/lib/presentationcontroller.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -35,151 +35,6 @@ from openlp.core.utils import AppLocation log = logging.getLogger(__name__) -class PresentationController(object): - """ - This class is used to control interactions with presentation applications - by creating a runtime environment. This is a base class for presentation - controllers to inherit from. - - To create a new controller, take a copy of this file and name it so it ends - with ``controller.py``, i.e. ``foobarcontroller.py``. Make sure it inherits - :class:`~openlp.plugins.presentations.lib.presentationcontroller.PresentationController`, - and then fill in the blanks. If possible try to make sure it loads on all - platforms, usually by using :mod:``os.name`` checks, although - ``__init__``, ``check_available`` and ``presentation_deleted`` should - always be implemented. - - See :class:`~openlp.plugins.presentations.lib.impresscontroller.ImpressController`, - :class:`~openlp.plugins.presentations.lib.powerpointcontroller.PowerpointController` or - :class:`~openlp.plugins.presentations.lib.pptviewcontroller.PptviewController` - for examples. - - **Basic Attributes** - - ``name`` - The name that appears in the options and the media manager - - ``enabled`` - The controller is enabled - - ``available`` - The controller is available on this machine. Set by init via - call to check_available - - ``plugin`` - The presentationplugin object - - ``supports`` - The primary native file types this application supports - - ``alsosupports`` - Other file types the application can import, although not necessarily - the first choice due to potential incompatibilities - - **Hook Functions** - - ``kill()`` - Called at system exit to clean up any running presentations - - ``check_available()`` - Returns True if presentation application is installed/can run on this - machine - - ``presentation_deleted()`` - Deletes presentation specific files, e.g. thumbnails - - """ - log.info(u'PresentationController loaded') - - def __init__(self, plugin=None, name=u'PresentationController'): - """ - This is the constructor for the presentationcontroller object. This - provides an easy way for descendent plugins to populate common data. - This method *must* be overridden, like so:: - - class MyPresentationController(PresentationController): - def __init__(self, plugin): - PresentationController.__init( - self, plugin, u'My Presenter App') - - ``plugin`` - Defaults to *None*. The presentationplugin object - - ``name`` - Name of the application, to appear in the application - """ - self.supports = [] - self.alsosupports = [] - self.docs = [] - self.plugin = plugin - self.name = name - self.settings_section = self.plugin.settingsSection - self.available = self.check_available() - self.temp_folder = os.path.join( - AppLocation.get_section_data_path(self.settings_section), name) - self.thumbnail_folder = os.path.join( - AppLocation.get_section_data_path(self.settings_section), - u'thumbnails') - self.thumbnail_prefix = u'slide' - if not os.path.isdir(self.thumbnail_folder): - os.makedirs(self.thumbnail_folder) - if not os.path.isdir(self.temp_folder): - os.makedirs(self.temp_folder) - - def enabled(self): - """ - Return whether the controller is currently enabled - """ - if self.available: - return QtCore.QSettings().value( - self.settings_section + u'/' + self.name, - QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \ - QtCore.Qt.Checked - else: - return False - - def check_available(self): - """ - Presentation app is able to run on this machine - """ - return False - - def start_process(self): - """ - Loads a running version of the presentation application in the - background. - """ - pass - - def kill(self): - """ - Called at system exit to clean up any running presentations and - close the application - """ - log.debug(u'Kill') - self.close_presentation() - - def add_doc(self, name): - """ - Called when a new presentation document is opened - """ - doc = PresentationDocument(self, name) - self.docs.append(doc) - return doc - - def remove_doc(self, doc=None): - """ - Called to remove an open document from the collection - """ - log.debug(u'remove_doc Presentation') - if doc is None: - return - if doc in self.docs: - self.docs.remove(doc) - - def close_presentation(self): - pass - class PresentationDocument(object): """ Base class for presentation documents to inherit from. @@ -440,4 +295,152 @@ class PresentationDocument(object): ``slide_no`` The slide the notes are required for, starting at 1 """ - return '' \ No newline at end of file + return '' + + +class PresentationController(object): + """ + This class is used to control interactions with presentation applications + by creating a runtime environment. This is a base class for presentation + controllers to inherit from. + + To create a new controller, take a copy of this file and name it so it ends + with ``controller.py``, i.e. ``foobarcontroller.py``. Make sure it inherits + :class:`~openlp.plugins.presentations.lib.presentationcontroller.PresentationController`, + and then fill in the blanks. If possible try to make sure it loads on all + platforms, usually by using :mod:``os.name`` checks, although + ``__init__``, ``check_available`` and ``presentation_deleted`` should + always be implemented. + + See :class:`~openlp.plugins.presentations.lib.impresscontroller.ImpressController`, + :class:`~openlp.plugins.presentations.lib.powerpointcontroller.PowerpointController` or + :class:`~openlp.plugins.presentations.lib.pptviewcontroller.PptviewController` + for examples. + + **Basic Attributes** + + ``name`` + The name that appears in the options and the media manager + + ``enabled`` + The controller is enabled + + ``available`` + The controller is available on this machine. Set by init via + call to check_available + + ``plugin`` + The presentationplugin object + + ``supports`` + The primary native file types this application supports + + ``alsosupports`` + Other file types the application can import, although not necessarily + the first choice due to potential incompatibilities + + **Hook Functions** + + ``kill()`` + Called at system exit to clean up any running presentations + + ``check_available()`` + Returns True if presentation application is installed/can run on this + machine + + ``presentation_deleted()`` + Deletes presentation specific files, e.g. thumbnails + + """ + log.info(u'PresentationController loaded') + + def __init__(self, plugin=None, name=u'PresentationController', + document_class=PresentationDocument): + """ + This is the constructor for the presentationcontroller object. This + provides an easy way for descendent plugins to populate common data. + This method *must* be overridden, like so:: + + class MyPresentationController(PresentationController): + def __init__(self, plugin): + PresentationController.__init( + self, plugin, u'My Presenter App') + + ``plugin`` + Defaults to *None*. The presentationplugin object + + ``name`` + Name of the application, to appear in the application + """ + self.supports = [] + self.alsosupports = [] + self.docs = [] + self.plugin = plugin + self.name = name + self.document_class = document_class + self.settings_section = self.plugin.settingsSection + self.available = self.check_available() + self.temp_folder = os.path.join( + AppLocation.get_section_data_path(self.settings_section), name) + self.thumbnail_folder = os.path.join( + AppLocation.get_section_data_path(self.settings_section), + u'thumbnails') + self.thumbnail_prefix = u'slide' + if not os.path.isdir(self.thumbnail_folder): + os.makedirs(self.thumbnail_folder) + if not os.path.isdir(self.temp_folder): + os.makedirs(self.temp_folder) + + def enabled(self): + """ + Return whether the controller is currently enabled + """ + if self.available: + return QtCore.QSettings().value( + self.settings_section + u'/' + self.name, + QtCore.QVariant(QtCore.Qt.Checked)).toInt()[0] == \ + QtCore.Qt.Checked + else: + return False + + def check_available(self): + """ + Presentation app is able to run on this machine + """ + return False + + def start_process(self): + """ + Loads a running version of the presentation application in the + background. + """ + pass + + def kill(self): + """ + Called at system exit to clean up any running presentations and + close the application + """ + log.debug(u'Kill') + self.close_presentation() + + def add_document(self, name): + """ + Called when a new presentation document is opened + """ + document = self.document_class(self, name) + self.docs.append(document) + return document + + def remove_doc(self, doc=None): + """ + Called to remove an open document from the collection + """ + log.debug(u'remove_doc Presentation') + if doc is None: + return + if doc in self.docs: + self.docs.remove(doc) + + def close_presentation(self): + pass diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index fc82600df..7b85eebb4 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,6 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsTab, translate +from openlp.core.lib.ui import UiStrings class PresentationTab(SettingsTab): """ @@ -84,10 +85,8 @@ class PresentationTab(SettingsTab): else: checkbox.setText( unicode(translate('PresentationPlugin.PresentationTab', - '%s (unvailable)')) % controller.name) - self.AdvancedGroupBox.setTitle( - translate('PresentationPlugin.PresentationTab', - 'Advanced')) + '%s (unavailable)')) % controller.name) + self.AdvancedGroupBox.setTitle(UiStrings.Advanced) self.OverrideAppCheckBox.setText( translate('PresentationPlugin.PresentationTab', 'Allow presentation application to be overriden')) diff --git a/openlp/plugins/presentations/presentationplugin.py b/openlp/plugins/presentations/presentationplugin.py index 17417df58..eb7e714f0 100644 --- a/openlp/plugins/presentations/presentationplugin.py +++ b/openlp/plugins/presentations/presentationplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -167,33 +167,18 @@ class PresentationPlugin(Plugin): 'container title') } # Middle Header Bar - ## Load Action ## - self.textStrings[StringContent.Load] = { - u'title': translate('PresentationPlugin', 'Load'), - u'tooltip': translate('PresentationPlugin', - 'Load a new Presentation') - } - ## Delete Action ## - self.textStrings[StringContent.Delete] = { - u'title': translate('PresentationPlugin', 'Delete'), - u'tooltip': translate('PresentationPlugin', - 'Delete the selected Presentation') - } - ## Preview Action ## - self.textStrings[StringContent.Preview] = { - u'title': translate('PresentationPlugin', 'Preview'), - u'tooltip': translate('PresentationPlugin', - 'Preview the selected Presentation') - } - ## Send Live Action ## - self.textStrings[StringContent.Live] = { - u'title': translate('PresentationPlugin', 'Live'), - u'tooltip': translate('PresentationPlugin', - 'Send the selected Presentation live') - } - ## Add to Service Action ## - self.textStrings[StringContent.Service] = { - u'title': translate('PresentationPlugin', 'Service'), - u'tooltip': translate('PresentationPlugin', + tooltips = { + u'load': translate('PresentationPlugin', 'Load a new Presentation'), + u'import': u'', + u'new': u'', + u'edit': u'', + u'delete': translate('PresentationPlugin', + 'Delete the selected Presentation'), + u'preview': translate('PresentationPlugin', + 'Preview the selected Presentation'), + u'live': translate('PresentationPlugin', + 'Send the selected Presentation live'), + u'service': translate('PresentationPlugin', 'Add the selected Presentation to the service') } + self.setPluginUiTextStrings(tooltips) diff --git a/openlp/plugins/remotes/__init__.py b/openlp/plugins/remotes/__init__.py index 4e619fb67..b5077f435 100644 --- a/openlp/plugins/remotes/__init__.py +++ b/openlp/plugins/remotes/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ """ The :mod:`remotes` plugin allows OpenLP to be controlled from another machine over a network connection. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/remotes/lib/__init__.py b/openlp/plugins/remotes/lib/__init__.py index b6f952242..8e4f1b210 100644 --- a/openlp/plugins/remotes/lib/__init__.py +++ b/openlp/plugins/remotes/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### from remotetab import RemoteTab -from httpserver import HttpServer \ No newline at end of file +from httpserver import HttpServer diff --git a/openlp/plugins/remotes/lib/httpserver.py b/openlp/plugins/remotes/lib/httpserver.py index 6ec9476a8..c92569a4a 100644 --- a/openlp/plugins/remotes/lib/httpserver.py +++ b/openlp/plugins/remotes/lib/httpserver.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -43,7 +43,7 @@ log = logging.getLogger(__name__) class HttpServer(object): """ Ability to control OpenLP via a webbrowser - e.g. http://localhost:4316/send/slidecontroller_live_next + e.g. http://localhost:4316/send/slidecontroller_live_next http://localhost:4316/send/alerts_text?q=your%20alert%20text """ def __init__(self, parent): @@ -68,11 +68,13 @@ class HttpServer(object): """ log.debug(u'Start TCP server') port = QtCore.QSettings().value( - self.parent.settingsSection + u'/remote port', + self.parent.settingsSection + u'/port', QtCore.QVariant(4316)).toInt()[0] + address = QtCore.QSettings().value( + self.parent.settingsSection + u'/ip address', + QtCore.QVariant(u'0.0.0.0')).toString() self.server = QtNetwork.QTcpServer() - self.server.listen(QtNetwork.QHostAddress(QtNetwork.QHostAddress.Any), - port) + self.server.listen(QtNetwork.QHostAddress(address), port) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_changed'), self.slide_change) @@ -347,4 +349,4 @@ class HttpConnection(object): log.debug(u'close socket') self.socket.close() self.socket = None - self.parent.close_connection(self) \ No newline at end of file + self.parent.close_connection(self) diff --git a/openlp/plugins/remotes/lib/remotetab.py b/openlp/plugins/remotes/lib/remotetab.py index d06e69164..2dfee06ce 100644 --- a/openlp/plugins/remotes/lib/remotetab.py +++ b/openlp/plugins/remotes/lib/remotetab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/remotes/remoteplugin.py b/openlp/plugins/remotes/remoteplugin.py index dbc56a61c..7236d7546 100644 --- a/openlp/plugins/remotes/remoteplugin.py +++ b/openlp/plugins/remotes/remoteplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -38,7 +38,8 @@ class RemotesPlugin(Plugin): """ remotes constructor """ - Plugin.__init__(self, u'Remotes', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Remotes', u'1.9.4', plugin_helpers, + settingsTabClass=RemoteTab) self.icon = build_icon(u':/plugins/plugin_remote.png') self.weight = -1 self.server = None @@ -61,13 +62,6 @@ class RemotesPlugin(Plugin): if self.server: self.server.close() - def getSettingsTab(self): - """ - Create the settings Tab - """ - visible_name = self.getString(StringContent.VisibleName) - return RemoteTab(self.name, visible_name[u'title']) - def about(self): """ Information about this plugin diff --git a/openlp/plugins/songs/__init__.py b/openlp/plugins/songs/__init__.py index c95d29c46..8332f7233 100644 --- a/openlp/plugins/songs/__init__.py +++ b/openlp/plugins/songs/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,4 +26,4 @@ """ The :mod:`songs` module provides the Songs plugin. The Songs plugin provides the main lyric projection function of OpenLP. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/songs/forms/__init__.py b/openlp/plugins/songs/forms/__init__.py index 160a014ac..356817ef9 100644 --- a/openlp/plugins/songs/forms/__init__.py +++ b/openlp/plugins/songs/forms/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -57,4 +57,6 @@ from songbookform import SongBookForm from editverseform import EditVerseForm from editsongform import EditSongForm from songmaintenanceform import SongMaintenanceForm -from songimportform import SongImportForm \ No newline at end of file +from songimportform import SongImportForm +from songexportform import SongExportForm + diff --git a/openlp/plugins/songs/forms/authorsdialog.py b/openlp/plugins/songs/forms/authorsdialog.py index 0b3f791d1..ed2f87e2e 100644 --- a/openlp/plugins/songs/forms/authorsdialog.py +++ b/openlp/plugins/songs/forms/authorsdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_AuthorsDialog(object): def setupUi(self, authorsDialog): @@ -57,7 +57,7 @@ class Ui_AuthorsDialog(object): self.authorLayout.addRow(self.displayLabel, self.displayEdit) self.dialogLayout.addLayout(self.authorLayout) self.dialogLayout.addWidget( - create_save_cancel_button_box(authorsDialog)) + create_accept_reject_button_box(authorsDialog)) self.retranslateUi(authorsDialog) authorsDialog.setMaximumHeight(authorsDialog.sizeHint().height()) QtCore.QMetaObject.connectSlotsByName(authorsDialog) diff --git a/openlp/plugins/songs/forms/authorsform.py b/openlp/plugins/songs/forms/authorsform.py index 3a37cf290..ad4cea3de 100644 --- a/openlp/plugins/songs/forms/authorsform.py +++ b/openlp/plugins/songs/forms/authorsform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songs/forms/editsongdialog.py b/openlp/plugins/songs/forms/editsongdialog.py index e9be62830..c9dfb1e13 100644 --- a/openlp/plugins/songs/forms/editsongdialog.py +++ b/openlp/plugins/songs/forms/editsongdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,8 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box +from openlp.plugins.songs.lib.ui import SongStrings class Ui_EditSongDialog(object): def setupUi(self, editSongDialog): @@ -241,7 +242,7 @@ class Ui_EditSongDialog(object): self.themeTabLayout.addWidget(self.commentsGroupBox) self.songTabWidget.addTab(self.themeTab, u'') self.dialogLayout.addWidget(self.songTabWidget) - self.buttonBox = create_save_cancel_button_box(editSongDialog) + self.buttonBox = create_accept_reject_button_box(editSongDialog) self.dialogLayout.addWidget(self.buttonBox) self.retranslateUi(editSongDialog) QtCore.QMetaObject.connectSlotsByName(editSongDialog) @@ -257,33 +258,27 @@ class Ui_EditSongDialog(object): translate('SongsPlugin.EditSongForm', '&Lyrics:')) self.verseOrderLabel.setText( translate('SongsPlugin.EditSongForm', '&Verse order:')) - self.verseAddButton.setText( - translate('SongsPlugin.EditSongForm', '&Add')) - self.verseEditButton.setText( - translate('SongsPlugin.EditSongForm', '&Edit')) + self.verseAddButton.setText(UiStrings.Add) + self.verseEditButton.setText(UiStrings.Edit) self.verseEditAllButton.setText( translate('SongsPlugin.EditSongForm', 'Ed&it All')) - self.verseDeleteButton.setText( - translate('SongsPlugin.EditSongForm', '&Delete')) + self.verseDeleteButton.setText(UiStrings.Delete) self.songTabWidget.setTabText( self.songTabWidget.indexOf(self.lyricsTab), translate('SongsPlugin.EditSongForm', 'Title && Lyrics')) - self.authorsGroupBox.setTitle( - translate('SongsPlugin.EditSongForm', 'Authors')) + self.authorsGroupBox.setTitle(SongStrings.Authors) self.authorAddButton.setText( translate('SongsPlugin.EditSongForm', '&Add to Song')) self.authorRemoveButton.setText( translate('SongsPlugin.EditSongForm', '&Remove')) self.maintenanceButton.setText(translate('SongsPlugin.EditSongForm', '&Manage Authors, Topics, Song Books')) - self.topicsGroupBox.setTitle( - translate('SongsPlugin.EditSongForm', 'Topic')) + self.topicsGroupBox.setTitle(SongStrings.Topic) self.topicAddButton.setText( translate('SongsPlugin.EditSongForm', 'A&dd to Song')) self.topicRemoveButton.setText( translate('SongsPlugin.EditSongForm', 'R&emove')) - self.songBookGroupBox.setTitle( - translate('SongsPlugin.EditSongForm', 'Song Book')) + self.songBookGroupBox.setTitle(SongStrings.SongBook) self.songBookNameLabel.setText(translate('SongsPlugin.EditSongForm', 'Book:')) self.songBookNumberLabel.setText(translate('SongsPlugin.EditSongForm', @@ -292,16 +287,13 @@ class Ui_EditSongDialog(object): self.songTabWidget.indexOf(self.authorsTab), translate('SongsPlugin.EditSongForm', 'Authors, Topics && Song Book')) - self.themeGroupBox.setTitle( - translate('SongsPlugin.EditSongForm', 'Theme')) + self.themeGroupBox.setTitle(UiStrings.Theme) self.themeAddButton.setText( translate('SongsPlugin.EditSongForm', 'New &Theme')) self.rightsGroupBox.setTitle( translate('SongsPlugin.EditSongForm', 'Copyright Information')) - self.copyrightInsertButton.setText( - translate('SongsPlugin.EditSongForm', '\xa9')) - self.CCLILabel.setText( - translate('SongsPlugin.EditSongForm', 'CCLI number:')) + self.copyrightInsertButton.setText(SongStrings.CopyrightSymbol) + self.CCLILabel.setText(UiStrings.CCLINumberLabel) self.commentsGroupBox.setTitle( translate('SongsPlugin.EditSongForm', 'Comments')) self.songTabWidget.setTabText( diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 8536d38b8..0e874c3d5 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -30,10 +30,12 @@ import re from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, translate -from openlp.core.lib.ui import add_widget_completer, critical_error_message_box +from openlp.core.lib.ui import UiStrings, add_widget_completer, \ + critical_error_message_box from openlp.plugins.songs.forms import EditVerseForm from openlp.plugins.songs.lib import SongXML, VerseType from openlp.plugins.songs.lib.db import Book, Song, Author, Topic +from openlp.plugins.songs.lib.ui import SongStrings from editsongdialog import Ui_EditSongDialog log = logging.getLogger(__name__) @@ -94,8 +96,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): QtCore.SIGNAL(u'theme_update_list'), self.loadThemes) self.previewButton = QtGui.QPushButton() self.previewButton.setObjectName(u'previewButton') - self.previewButton.setText( - translate('SongsPlugin.EditSongForm', 'Save && Preview')) + self.previewButton.setText(UiStrings.SaveAndPreview) self.buttonBox.addButton( self.previewButton, QtGui.QDialogButtonBox.ActionRole) QtCore.QObject.connect(self.buttonBox, @@ -161,6 +162,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def newSong(self): log.debug(u'New Song') + self.song = None self.initialise() self.songTabWidget.setCurrentIndex(0) self.titleEdit.setText(u'') @@ -226,10 +228,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.copyrightEdit.setText(u'') self.verseListWidget.clear() self.verseListWidget.setRowCount(0) - if self.song.verse_order: - self.verseOrderEdit.setText(self.song.verse_order) - else: - self.verseOrderEdit.setText(u'') if self.song.comments: self.commentsEdit.setPlainText(self.song.comments) else: @@ -249,15 +247,31 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): # This is just because occasionally the lyrics come back as a "buffer" if isinstance(self.song.lyrics, buffer): self.song.lyrics = unicode(self.song.lyrics) + verse_tags_translated = False if self.song.lyrics.startswith(u' 1: + index = VerseType.from_translated_string(verse_tag) + if index is None: + index = VerseType.from_string(verse_tag) + else: + verse_tags_translated = True + if index is None: + index = VerseType.from_tag(verse_tag) + if index is None: + index = VerseType.Other + verse[0][u'type'] = VerseType.Tags[index] + verse_def = u'%s%s' % (verse[0][u'type'], verse[0][u'label']) item = QtGui.QTableWidgetItem(verse[1]) - item.setData(QtCore.Qt.UserRole, QtCore.QVariant(variant)) + item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def)) self.verseListWidget.setItem(count, 0, item) else: verses = self.song.lyrics.split(u'\n\n') @@ -265,10 +279,24 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.verseListWidget.setRowCount( self.verseListWidget.rowCount() + 1) item = QtGui.QTableWidgetItem(verse) - variant = u'%s:%s' % \ - (VerseType.to_string(VerseType.Verse), unicode(count + 1)) - item.setData(QtCore.Qt.UserRole, QtCore.QVariant(variant)) + verse_def = u'%s%s' % \ + (VerseType.Tags[VerseType.Verse], unicode(count + 1)) + item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def)) self.verseListWidget.setItem(count, 0, item) + if self.song.verse_order: + # we translate verse order + translated = [] + for verse_def in self.song.verse_order.split(): + verse_index = None + if verse_tags_translated: + verse_index = VerseType.from_translated_tag(verse_def[0]) + if verse_index is None: + verse_index = VerseType.from_tag(verse_def[0]) + verse_tag = VerseType.TranslatedTags[verse_index].upper() + translated.append(u'%s%s' % (verse_tag, verse_def[1:])) + self.verseOrderEdit.setText(u' '.join(translated)) + else: + self.verseOrderEdit.setText(u'') self.verseListWidget.resizeRowsToContents() self.tagRows() # clear the results @@ -293,14 +321,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): """ Tag the Song List rows based on the verse list """ - rowLabel = [] + row_label = [] for row in range(0, self.verseListWidget.rowCount()): item = self.verseListWidget.item(row, 0) - data = unicode(item.data(QtCore.Qt.UserRole).toString()) - bit = data.split(u':') - rowTag = u'%s%s' % (bit[0][0:1], bit[1]) - rowLabel.append(rowTag) - self.verseListWidget.setVerticalHeaderLabels(rowLabel) + verse_def = unicode(item.data(QtCore.Qt.UserRole).toString()) + verse_tag = VerseType.translated_tag(verse_def[0]) + row_def = u'%s%s' % (verse_tag, verse_def[1:]) + row_label.append(row_def) + self.verseListWidget.setVerticalHeaderLabels(row_label) def onAuthorAddButtonClicked(self): item = int(self.authorsComboBox.currentIndex()) @@ -336,8 +364,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.__addAuthorToList(author) self.authorsComboBox.setCurrentIndex(0) else: - QtGui.QMessageBox.warning(self, - translate('SongsPlugin.EditSongForm', 'No Author Selected'), + QtGui.QMessageBox.warning(self, UiStrings.NISs, translate('SongsPlugin.EditSongForm', 'You have not selected ' 'a valid author. Either select an author from the list, ' 'or type in a new author and click the "Add Author to ' @@ -396,8 +423,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.topicsListView.addItem(topic_item) self.topicsComboBox.setCurrentIndex(0) else: - QtGui.QMessageBox.warning(self, - translate('SongsPlugin.EditSongForm', 'No Topic Selected'), + QtGui.QMessageBox.warning(self, UiStrings.NISs, translate('SongsPlugin.EditSongForm', 'You have not selected ' 'a valid topic. Either select a topic from the list, or ' 'type in a new topic and click the "Add Topic to Song" ' @@ -419,11 +445,11 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def onVerseAddButtonClicked(self): self.verse_form.setVerse(u'', True) if self.verse_form.exec_(): - afterText, verse, subVerse = self.verse_form.getVerse() - data = u'%s:%s' % (verse, subVerse) - item = QtGui.QTableWidgetItem(afterText) - item.setData(QtCore.Qt.UserRole, QtCore.QVariant(data)) - item.setText(afterText) + after_text, verse_tag, verse_num = self.verse_form.getVerse() + verse_def = u'%s%s' % (verse_tag, verse_num) + item = QtGui.QTableWidgetItem(after_text) + item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def)) + item.setText(after_text) self.verseListWidget.setRowCount( self.verseListWidget.rowCount() + 1) self.verseListWidget.setItem( @@ -439,12 +465,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): verseId = unicode(item.data(QtCore.Qt.UserRole).toString()) self.verse_form.setVerse(tempText, True, verseId) if self.verse_form.exec_(): - afterText, verse, subVerse = self.verse_form.getVerse() - data = u'%s:%s' % (verse, subVerse) - item.setData(QtCore.Qt.UserRole, QtCore.QVariant(data)) - item.setText(afterText) + after_text, verse_tag, verse_num = self.verse_form.getVerse() + verse_def = u'%s%s' % (verse_tag, verse_num) + item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse_def)) + item.setText(after_text) # number of lines has change so repaint the list moving the data - if len(tempText.split(u'\n')) != len(afterText.split(u'\n')): + if len(tempText.split(u'\n')) != len(after_text.split(u'\n')): tempList = {} tempId = {} for row in range(0, self.verseListWidget.rowCount()): @@ -466,7 +492,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): for row in range(0, self.verseListWidget.rowCount()): item = self.verseListWidget.item(row, 0) field = unicode(item.data(QtCore.Qt.UserRole).toString()) - verse_list += u'---[%s]---\n' % field + verse_tag = VerseType.translated_name(field[0]) + verse_num = field[1:] + verse_list += u'---[%s:%s]---\n' % (verse_tag, verse_num) verse_list += item.text() verse_list += u'\n' self.verse_form.setVerse(verse_list) @@ -482,15 +510,32 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): for count, parts in enumerate(match.split(u']---\n')): if len(parts) > 1: if count == 0: - # make sure the tag is correctly cased - variant = u'%s%s' % \ - (parts[0:1].upper(), parts[1:].lower()) + # handling carefully user inputted versetags + separator = parts.find(u':') + if separator >= 0: + verse_name = parts[0:separator].strip() + verse_num = parts[separator+1:].strip() + else: + verse_name = parts + verse_num = u'1' + verse_index = \ + VerseType.from_loose_input(verse_name) + verse_tag = VerseType.Tags[verse_index] + # Later we need to handle v1a as well. + #regex = re.compile(r'(\d+\w.)') + regex = re.compile(r'\D*(\d+)\D*') + match = regex.match(verse_num) + if match: + verse_num = match.group(1) + else: + verse_num = u'1' + verse_def = u'%s%s' % (verse_tag, verse_num) else: if parts.endswith(u'\n'): parts = parts.rstrip(u'\n') item = QtGui.QTableWidgetItem(parts) item.setData(QtCore.Qt.UserRole, - QtCore.QVariant(variant)) + QtCore.QVariant(verse_def)) self.verseListWidget.setRowCount( self.verseListWidget.rowCount() + 1) self.verseListWidget.setItem( @@ -512,7 +557,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): """ Check the validity of the song. """ - # This checks data in the form *not* self.song. self.song is still + # This checks data in the form *not* self.song. self.song is still # None at this point. log.debug(u'Validate Song') # Lets be nice and assume the data is correct. @@ -542,25 +587,31 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): order_names = unicode(self.verseOrderEdit.text()).split() for item in order_names: if len(item) == 1: - order.append(item.lower() + u'1') + verse_index = VerseType.from_translated_tag(item) + if verse_index is not None: + order.append(VerseType.Tags[verse_index] + u'1') + else: + order.append(u'') # it matches no verses anyway else: - order.append(item.lower()) + verse_index = VerseType.from_translated_tag(item[0]) + if verse_index is None: + order.append(u'') # same as above + else: + verse_tag = VerseType.Tags[verse_index] + verse_num = item[1:].lower() + order.append(verse_tag + verse_num) verses = [] verse_names = [] - for index in range (0, self.verseListWidget.rowCount()): + for index in range(0, self.verseListWidget.rowCount()): verse = self.verseListWidget.item(index, 0) verse = unicode(verse.data(QtCore.Qt.UserRole).toString()) if verse not in verse_names: - verses.append( - re.sub(r'(.)[^:]*:(.*)', r'\1\2', verse.lower())) - verse_names.append(verse) + verses.append(verse) + verse_names.append(u'%s%s' % ( + VerseType.translated_tag(verse[0]), verse[1:])) for count, item in enumerate(order): if item not in verses: - self.songTabWidget.setCurrentIndex(0) - self.verseOrderEdit.setFocus() - valid = verses.pop(0) - for verse in verses: - valid = valid + u', ' + verse + valid = u', '.join(verse_names) critical_error_message_box( message=unicode(translate('SongsPlugin.EditSongForm', 'The verse order is invalid. There is no verse ' @@ -576,7 +627,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): unicode(translate('SongsPlugin.EditSongForm', 'You have not used %s anywhere in the verse ' 'order. Are you sure you want to save the song ' - 'like this?')) % verse_names[count].replace(u':', u' '), + 'like this?')) % verse_names[count], QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) if answer == QtGui.QMessageBox.No: return False @@ -598,7 +649,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def onCopyrightInsertButtonTriggered(self): text = self.copyrightEdit.text() pos = self.copyrightEdit.cursorPosition() - sign = translate('SongsPlugin.EditSongForm', '\xa9') + sign = SongStrings.CopyrightSymbol text = text[:pos] + sign + text[pos:] self.copyrightEdit.setText(text) self.copyrightEdit.setFocus() @@ -626,8 +677,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): A button (QPushButton). """ log.debug(u'onPreview') - if unicode(button.objectName()) == u'previewButton' and \ - self.saveSong(True): + if unicode(button.objectName()) == u'previewButton': + self.saveSong(True) Receiver.send_message(u'songs_preview') def clearCaches(self): @@ -663,14 +714,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): def saveSong(self, preview=False): """ Get all the data from the widgets on the form, and then save it to the - database. The form has been validated and all reference items + database. The form has been validated and all reference items (Authors, Books and Topics) have been saved before this function is called. ``preview`` Should be ``True`` if the song is also previewed (boolean). """ - # The Song() assignment. No database calls should be made while a + # The Song() assignment. No database calls should be made while a # Song() is in a partially complete state. if not self.song: self.song = Song() @@ -683,7 +734,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): else: self.song.search_title = self.song.title self.song.comments = unicode(self.commentsEdit.toPlainText()) - self.song.verse_order = unicode(self.verseOrderEdit.text()) + ordertext = unicode(self.verseOrderEdit.text()) + order = [] + for item in ordertext.split(): + verse_tag = VerseType.Tags[ + VerseType.from_translated_tag(item[0])] + verse_num = item[1:].lower() + order.append(u'%s%s' % (verse_tag, verse_num)) + self.song.verse_order = u' '.join(order) self.song.ccli_number = unicode(self.CCLNumberEdit.text()) self.song.song_number = unicode(self.songBookNumberEdit.text()) book_name = unicode(self.songBookComboBox.currentText()) @@ -726,12 +784,14 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): for i in range(0, self.verseListWidget.rowCount()): item = self.verseListWidget.item(i, 0) verseId = unicode(item.data(QtCore.Qt.UserRole).toString()) - bits = verseId.split(u':') - sxml.add_verse_to_lyrics(bits[0], bits[1], unicode(item.text())) + verse_tag = verseId[0] + verse_num = verseId[1:] + sxml.add_verse_to_lyrics(verse_tag, verse_num, + unicode(item.text())) text = text + self.whitespace.sub(u' ', unicode(self.verseListWidget.item(i, 0).text())) + u' ' - if (bits[1] > u'1') and (bits[0][0] not in multiple): - multiple.append(bits[0][0]) + if (verse_num > u'1') and (verse_tag not in multiple): + multiple.append(verse_tag) self.song.search_lyrics = text.lower() self.song.lyrics = unicode(sxml.extract_xml(), u'utf-8') for verse in multiple: diff --git a/openlp/plugins/songs/forms/editversedialog.py b/openlp/plugins/songs/forms/editversedialog.py index b4bc4551f..391d9be65 100644 --- a/openlp/plugins/songs/forms/editversedialog.py +++ b/openlp/plugins/songs/forms/editversedialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate, SpellTextEdit -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import create_accept_reject_button_box from openlp.plugins.songs.lib import VerseType class Ui_EditVerseDialog(object): @@ -61,7 +61,7 @@ class Ui_EditVerseDialog(object): self.verseTypeLayout.addStretch() self.dialogLayout.addLayout(self.verseTypeLayout) self.dialogLayout.addWidget( - create_save_cancel_button_box(editVerseDialog)) + create_accept_reject_button_box(editVerseDialog)) self.retranslateUi(editVerseDialog) QtCore.QMetaObject.connectSlotsByName(editVerseDialog) @@ -70,19 +70,19 @@ class Ui_EditVerseDialog(object): translate('SongsPlugin.EditVerseForm', 'Edit Verse')) self.verseTypeLabel.setText( translate('SongsPlugin.EditVerseForm', '&Verse type:')) - self.verseTypeComboBox.setItemText(0, - VerseType.to_string(VerseType.Verse)) - self.verseTypeComboBox.setItemText(1, - VerseType.to_string(VerseType.Chorus)) - self.verseTypeComboBox.setItemText(2, - VerseType.to_string(VerseType.Bridge)) - self.verseTypeComboBox.setItemText(3, - VerseType.to_string(VerseType.PreChorus)) - self.verseTypeComboBox.setItemText(4, - VerseType.to_string(VerseType.Intro)) - self.verseTypeComboBox.setItemText(5, - VerseType.to_string(VerseType.Ending)) - self.verseTypeComboBox.setItemText(6, - VerseType.to_string(VerseType.Other)) + self.verseTypeComboBox.setItemText(VerseType.Verse, + VerseType.TranslatedNames[VerseType.Verse]) + self.verseTypeComboBox.setItemText(VerseType.Chorus, + VerseType.TranslatedNames[VerseType.Chorus]) + self.verseTypeComboBox.setItemText(VerseType.Bridge, + VerseType.TranslatedNames[VerseType.Bridge]) + self.verseTypeComboBox.setItemText(VerseType.PreChorus, + VerseType.TranslatedNames[VerseType.PreChorus]) + self.verseTypeComboBox.setItemText(VerseType.Intro, + VerseType.TranslatedNames[VerseType.Intro]) + self.verseTypeComboBox.setItemText(VerseType.Ending, + VerseType.TranslatedNames[VerseType.Ending]) + self.verseTypeComboBox.setItemText(VerseType.Other, + VerseType.TranslatedNames[VerseType.Other]) self.insertButton.setText( translate('SongsPlugin.EditVerseForm', '&Insert')) diff --git a/openlp/plugins/songs/forms/editverseform.py b/openlp/plugins/songs/forms/editverseform.py index e67e0733a..8a52c1859 100644 --- a/openlp/plugins/songs/forms/editverseform.py +++ b/openlp/plugins/songs/forms/editverseform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -57,22 +57,23 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): QtCore.QObject.connect(self.verseTypeComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), self.onVerseTypeComboBoxChanged) - self.verse_regex = re.compile(r'---\[([-\w]+):([\d]+)\]---') + self.verse_regex = re.compile(r'---\[(.+):\D*(\d*)\D*.*\]---') def contextMenu(self, point): item = self.serviceManagerList.itemAt(point) - def insertVerse(self, title, num=1): + def insertVerse(self, verse_tag, verse_num=1): if self.verseTextEdit.textCursor().columnNumber() != 0: self.verseTextEdit.insertPlainText(u'\n') - self.verseTextEdit.insertPlainText(u'---[%s:%s]---\n' % (title, num)) + verse_tag = VerseType.translated_name(verse_tag) + self.verseTextEdit.insertPlainText(u'---[%s:%s]---\n' % + (verse_tag, verse_num)) self.verseTextEdit.setFocus() def onInsertButtonClicked(self): - verse_type = self.verseTypeComboBox.currentIndex() - if VerseType.to_string(verse_type) is not None: - self.insertVerse(VerseType.to_string(verse_type), - self.verseNumberBox.value()) + verse_type_index = self.verseTypeComboBox.currentIndex() + self.insertVerse(VerseType.Tags[verse_type_index], + self.verseNumberBox.value()) def onVerseTypeComboBoxChanged(self): """ @@ -81,10 +82,11 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): """ position = self.verseTextEdit.textCursor().position() text = unicode(self.verseTextEdit.toPlainText()) - verse_type = VerseType.to_string(self.verseTypeComboBox.currentIndex()) + verse_name = VerseType.TranslatedNames[ + self.verseTypeComboBox.currentIndex()] if not text: return - position = text.rfind(u'---[%s' % verse_type, 0, position) + position = text.rfind(u'---[%s' % verse_name, 0, position) if position == -1: self.verseNumberBox.setValue(1) return @@ -95,11 +97,11 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): text = text[:position + 4] match = self.verse_regex.match(text) if match: - verse_type = match.group(1) - verse_number = int(match.group(2)) - verse_type_index = VerseType.from_string(verse_type) + verse_tag = match.group(1) + verse_num = int(match.group(2)) + verse_type_index = VerseType.from_loose_input(verse_tag) if verse_type_index is not None: - self.verseNumberBox.setValue(verse_number) + self.verseNumberBox.setValue(verse_num) def onCursorPositionChanged(self): """ @@ -124,25 +126,26 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): match = self.verse_regex.match(text) if match: verse_type = match.group(1) + verse_type_index = VerseType.from_loose_input(verse_type) verse_number = int(match.group(2)) - verse_type_index = VerseType.from_string(verse_type) if verse_type_index is not None: self.verseTypeComboBox.setCurrentIndex(verse_type_index) self.verseNumberBox.setValue(verse_number) def setVerse(self, text, single=False, - tag=u'%s:1' % VerseType.to_string(VerseType.Verse)): + tag=u'%s1' % VerseType.Tags[VerseType.Verse]): self.hasSingleVerse = single if single: - verse_type, verse_number = tag.split(u':') - verse_type_index = VerseType.from_string(verse_type) + verse_type_index = VerseType.from_tag(tag[0]) + verse_number = tag[1:] if verse_type_index is not None: self.verseTypeComboBox.setCurrentIndex(verse_type_index) self.verseNumberBox.setValue(int(verse_number)) self.insertButton.setVisible(False) else: if not text: - text = u'---[%s:1]---\n' % VerseType.to_string(VerseType.Verse) + text = u'---[%s:1]---\n' % \ + VerseType.TranslatedNames[VerseType.Verse] self.verseTypeComboBox.setCurrentIndex(0) self.verseNumberBox.setValue(1) self.insertButton.setVisible(True) @@ -152,14 +155,14 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog): def getVerse(self): return self.verseTextEdit.toPlainText(), \ - VerseType.to_string(self.verseTypeComboBox.currentIndex()), \ + VerseType.Tags[self.verseTypeComboBox.currentIndex()], \ unicode(self.verseNumberBox.value()) def getVerseAll(self): text = self.verseTextEdit.toPlainText() if not text.startsWith(u'---['): - text = u'---[%s:1]---\n%s' % (VerseType.to_string(VerseType.Verse), - text) + text = u'---[%s:1]---\n%s' % \ + (VerseType.TranslatedNames[VerseType.Verse], text) return text def accept(self): diff --git a/openlp/plugins/songs/forms/songbookdialog.py b/openlp/plugins/songs/forms/songbookdialog.py index 89b8941b5..337210b38 100644 --- a/openlp/plugins/songs/forms/songbookdialog.py +++ b/openlp/plugins/songs/forms/songbookdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_SongBookDialog(object): def setupUi(self, songBookDialog): @@ -51,7 +51,7 @@ class Ui_SongBookDialog(object): self.bookLayout.addRow(self.publisherLabel, self.publisherEdit) self.dialogLayout.addLayout(self.bookLayout) self.dialogLayout.addWidget( - create_save_cancel_button_box(songBookDialog)) + create_accept_reject_button_box(songBookDialog)) self.retranslateUi(songBookDialog) songBookDialog.setMaximumHeight(songBookDialog.sizeHint().height()) QtCore.QMetaObject.connectSlotsByName(songBookDialog) diff --git a/openlp/plugins/songs/forms/songbookform.py b/openlp/plugins/songs/forms/songbookform.py index 3f054fe8d..23886750b 100644 --- a/openlp/plugins/songs/forms/songbookform.py +++ b/openlp/plugins/songs/forms/songbookform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py new file mode 100644 index 000000000..231d8fd43 --- /dev/null +++ b/openlp/plugins/songs/forms/songexportform.py @@ -0,0 +1,362 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`songexportform` module provides the wizard for exporting songs to the +OpenLyrics format. +""" +import logging + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import build_icon, Receiver, SettingsManager, translate +from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.ui.wizard import OpenLPWizard, WizardStrings +from openlp.plugins.songs.lib.db import Song +from openlp.plugins.songs.lib.openlyricsexport import OpenLyricsExport + +log = logging.getLogger(__name__) + +class SongExportForm(OpenLPWizard): + """ + This is the Song Export Wizard, which allows easy exporting of Songs to the + OpenLyrics format. + """ + log.info(u'SongExportForm loaded') + + def __init__(self, parent, plugin): + """ + Instantiate the wizard, and run any extra setup we need to. + + ``parent`` + The QWidget-derived parent of the wizard. + + ``plugin`` + The songs plugin. + """ + OpenLPWizard.__init__(self, parent, plugin, u'songExportWizard', + u':/wizards/wizard_exportsong.bmp') + self.stop_export_flag = False + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_export) + + def stop_export(self): + """ + Sets the flag for the exporter to stop the export. + """ + log.debug(u'Stopping songs export') + self.stop_export_flag = True + + def setupUi(self, image): + """ + Set up the song wizard UI. + """ + OpenLPWizard.setupUi(self, image) + + def customInit(self): + """ + Song wizard specific initialisation. + """ + pass + + def customSignals(self): + """ + Song wizard specific signals. + """ + QtCore.QObject.connect(self.availableListWidget, + QtCore.SIGNAL(u'itemActivated(QListWidgetItem*)'), + self.onItemPressed) + QtCore.QObject.connect(self.searchLineEdit, + QtCore.SIGNAL(u'textEdited(const QString&)'), + self.onSearchLineEditChanged) + QtCore.QObject.connect(self.uncheckButton, + QtCore.SIGNAL(u'clicked()'), self.onUncheckButtonClicked) + QtCore.QObject.connect(self.checkButton, + QtCore.SIGNAL(u'clicked()'), self.onCheckButtonClicked) + QtCore.QObject.connect(self.directoryButton, + QtCore.SIGNAL(u'clicked()'), self.onDirectoryButtonClicked) + + def addCustomPages(self): + """ + Add song wizard specific pages. + """ + # The page with all available songs. + self.availableSongsPage = QtGui.QWizardPage() + self.availableSongsPage.setObjectName(u'availableSongsPage') + self.availableSongsLayout = QtGui.QHBoxLayout(self.availableSongsPage) + self.availableSongsLayout.setObjectName(u'availableSongsLayout') + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName(u'verticalLayout') + self.availableListWidget = QtGui.QListWidget(self.availableSongsPage) + self.availableListWidget.setObjectName(u'availableListWidget') + self.verticalLayout.addWidget(self.availableListWidget) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName(u'horizontalLayout') + self.searchLabel = QtGui.QLabel(self.availableSongsPage) + self.searchLabel.setObjectName(u'searchLabel') + self.horizontalLayout.addWidget(self.searchLabel) + self.searchLineEdit = QtGui.QLineEdit(self.availableSongsPage) + self.searchLineEdit.setObjectName(u'searchLineEdit') + self.horizontalLayout.addWidget(self.searchLineEdit) + spacerItem = QtGui.QSpacerItem(40, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.uncheckButton = QtGui.QPushButton(self.availableSongsPage) + self.uncheckButton.setObjectName(u'uncheckButton') + self.horizontalLayout.addWidget(self.uncheckButton) + self.checkButton = QtGui.QPushButton(self.availableSongsPage) + self.checkButton.setObjectName(u'selectButton') + self.horizontalLayout.addWidget(self.checkButton) + self.verticalLayout.addLayout(self.horizontalLayout) + self.availableSongsLayout.addLayout(self.verticalLayout) + self.addPage(self.availableSongsPage) + # The page with the selected songs. + self.exportSongPage = QtGui.QWizardPage() + self.exportSongPage.setObjectName(u'availableSongsPage') + self.exportSongLayout = QtGui.QHBoxLayout(self.exportSongPage) + self.exportSongLayout.setObjectName(u'exportSongLayout') + self.gridLayout = QtGui.QGridLayout() + self.gridLayout.setObjectName(u'gridLayout') + self.selectedListWidget = QtGui.QListWidget(self.exportSongPage) + self.selectedListWidget.setObjectName(u'selectedListWidget') + self.gridLayout.addWidget(self.selectedListWidget, 1, 0, 1, 1) + self.horizontalLayout = QtGui.QHBoxLayout() + self.horizontalLayout.setObjectName(u'horizontalLayout') + self.directoryLabel = QtGui.QLabel(self.exportSongPage) + self.directoryLabel.setObjectName(u'directoryLabel') + self.horizontalLayout.addWidget(self.directoryLabel) + self.directoryLineEdit = QtGui.QLineEdit(self.exportSongPage) + self.directoryLineEdit.setObjectName(u'directoryLineEdit') + self.horizontalLayout.addWidget(self.directoryLineEdit) + self.directoryButton = QtGui.QToolButton(self.exportSongPage) + self.directoryButton.setIcon(build_icon(u':/exports/export_load.png')) + self.directoryButton.setObjectName(u'directoryButton') + self.horizontalLayout.addWidget(self.directoryButton) + self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) + self.exportSongLayout.addLayout(self.gridLayout) + self.addPage(self.exportSongPage) + + def retranslateUi(self): + """ + Song wizard localisation. + """ + self.setWindowTitle( + translate('SongsPlugin.ExportWizardForm', 'Song Export Wizard')) + self.titleLabel.setText(WizardStrings.HeaderStyle % + translate('OpenLP.Ui', 'Welcome to the Song Export Wizard')) + self.informationLabel.setText( + translate('SongsPlugin.ExportWizardForm', 'This wizard will help to' + ' export your songs to the open and free OpenLyrics worship song ' + 'format.')) + self.availableSongsPage.setTitle( + translate('SongsPlugin.ExportWizardForm', 'Select Songs')) + self.availableSongsPage.setSubTitle( + translate('SongsPlugin.ExportWizardForm', + 'Check the songs you want to export.')) + self.searchLabel.setText(u'%s:' % UiStrings.Search) + self.uncheckButton.setText( + translate('SongsPlugin.ExportWizardForm', 'Uncheck All')) + self.checkButton.setText( + translate('SongsPlugin.ExportWizardForm', 'Check All')) + self.exportSongPage.setTitle( + translate('SongsPlugin.ExportWizardForm', 'Select Directory')) + self.exportSongPage.setSubTitle( + translate('SongsPlugin.ExportWizardForm', + 'Select the directory you want the songs to be saved.')) + self.directoryLabel.setText( + translate('SongsPlugin.ExportWizardForm', 'Directory:')) + self.progressPage.setTitle( + translate('SongsPlugin.ExportWizardForm', 'Exporting')) + self.progressPage.setSubTitle( + translate('SongsPlugin.ExportWizardForm', + 'Please wait while your songs are exported.')) + self.progressLabel.setText(WizardStrings.Ready) + self.progressBar.setFormat(WizardStrings.PercentSymbolFormat) + + def validateCurrentPage(self): + """ + Validate the current page before moving on to the next page. + """ + if self.currentPage() == self.welcomePage: + return True + elif self.currentPage() == self.availableSongsPage: + items = [ + item for item in self._findListWidgetItems( + self.availableListWidget) if item.checkState() + ] + if not items: + critical_error_message_box(UiStrings.NISp, + translate('SongsPlugin.ExportWizardForm', + 'You need to add at least one Song to export.')) + return False + self.selectedListWidget.clear() + # Add the songs to the list of selected songs. + for item in items: + song = QtGui.QListWidgetItem(item.text()) + song.setData(QtCore.Qt.UserRole, + QtCore.QVariant(item.data(QtCore.Qt.UserRole).toPyObject())) + song.setFlags(QtCore.Qt.ItemIsEnabled) + self.selectedListWidget.addItem(song) + return True + elif self.currentPage() == self.exportSongPage: + if not self.directoryLineEdit.text(): + critical_error_message_box( + translate('SongsPlugin.ExportWizardForm', + 'No Save Location specified'), + translate('SongsPlugin.ExportWizardForm', + 'You need to specified a directory to save the songs in.')) + return False + return True + elif self.currentPage() == self.progressPage: + self.availableListWidget.clear() + self.selectedListWidget.clear() + return True + + def setDefaults(self): + """ + Set default form values for the song export wizard. + """ + self.restart() + self.finishButton.setVisible(False) + self.cancelButton.setVisible(True) + self.availableListWidget.clear() + self.selectedListWidget.clear() + self.directoryLineEdit.clear() + self.searchLineEdit.clear() + # Load the list of songs. + Receiver.send_message(u'cursor_busy') + songs = self.plugin.manager.get_all_objects(Song) + for song in songs: + authors = u', '.join([author.display_name + for author in song.authors]) + title = u'%s (%s)' % (unicode(song.title), authors) + item = QtGui.QListWidgetItem(title) + item.setData(QtCore.Qt.UserRole, QtCore.QVariant(song)) + item.setFlags(QtCore.Qt.ItemIsSelectable| + QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) + item.setCheckState(QtCore.Qt.Unchecked) + self.availableListWidget.addItem(item) + Receiver.send_message(u'cursor_normal') + + def preWizard(self): + """ + Perform pre export tasks. + """ + OpenLPWizard.preWizard(self) + self.progressLabel.setText( + translate('SongsPlugin.ExportWizardForm', 'Starting export...')) + Receiver.send_message(u'openlp_process_events') + + def performWizard(self): + """ + Perform the actual export. This creates an *openlyricsexport* instance + and calls the *do_export* method. + """ + songs = [ + song.data(QtCore.Qt.UserRole).toPyObject() + for song in self._findListWidgetItems(self.selectedListWidget) + ] + exporter = OpenLyricsExport( + self, songs, unicode(self.directoryLineEdit.text())) + if exporter.do_export(): + self.progressLabel.setText( + translate('SongsPlugin.SongExportForm', 'Finished export.')) + else: + self.progressLabel.setText( + translate('SongsPlugin.SongExportForm', + 'Your song export failed.')) + + def _findListWidgetItems(self, listWidget, text=u''): + """ + Returns a list of *QListWidgetItem*s of the ``listWidget``. Note, that + hidden items are included. + + ``listWidget`` + The widget to get all items from. (QListWidget) + + ``text`` + The text to search for. (unicode string) + """ + return [item for item in listWidget.findItems( + QtCore.QString(unicode(text)), QtCore.Qt.MatchContains) + ] + + def onItemPressed(self, item): + """ + Called, when an item in the *availableListWidget* has been pressed. Thes + item is check if it was not checked, whereas it is unchecked when it was + checked. + + ``item`` + The *QListWidgetItem* which was pressed. + """ + item.setCheckState( + QtCore.Qt.Unchecked if item.checkState() else QtCore.Qt.Checked) + + def onSearchLineEditChanged(self, text): + """ + The *searchLineEdit*'s text has been changed. Update the list of + available songs. Note that any song, which does not match the ``text`` + will be hidden, but not unchecked! + + ``text`` + The text of the *searchLineEdit*. (QString) + """ + search_result = [ + song for song in self._findListWidgetItems( + self.availableListWidget, unicode(text)) + ] + for item in self._findListWidgetItems(self.availableListWidget): + item.setHidden(False if item in search_result else True) + + def onUncheckButtonClicked(self): + """ + The *uncheckButton* has been clicked. Set all visible songs unchecked. + """ + for row in range(self.availableListWidget.count()): + item = self.availableListWidget.item(row) + if not item.isHidden(): + item.setCheckState(QtCore.Qt.Unchecked) + + def onCheckButtonClicked(self): + """ + The *checkButton* has been clicked. Set all visible songs checked. + """ + for row in range(self.availableListWidget.count()): + item = self.availableListWidget.item(row) + if not item.isHidden(): + item.setCheckState(QtCore.Qt.Checked) + + def onDirectoryButtonClicked(self): + """ + Called when the *directoryButton* was clicked. Opens a dialog and writes + the path to *directoryLineEdit*. + """ + path = unicode(QtGui.QFileDialog.getExistingDirectory(self, + translate('SongsPlugin.ExportWizardForm', 'Selecte to Folder'), + SettingsManager.get_last_dir(self.plugin.settingsSection, 1), + options=QtGui.QFileDialog.ShowDirsOnly)) + SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1) + self.directoryLineEdit.setText(path) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index a9af7f6b2..10422aadd 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,8 +32,8 @@ import os from PyQt4 import QtCore, QtGui from openlp.core.lib import Receiver, SettingsManager, translate -from openlp.core.lib.ui import critical_error_message_box -from openlp.core.ui.wizard import OpenLPWizard +from openlp.core.lib.ui import UiStrings, critical_error_message_box +from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.plugins.songs.lib.importer import SongFormat log = logging.getLogger(__name__) @@ -140,6 +140,18 @@ class SongImportForm(OpenLPWizard): QtCore.QObject.connect(self.songBeamerRemoveButton, QtCore.SIGNAL(u'clicked()'), self.onSongBeamerRemoveButtonClicked) + QtCore.QObject.connect(self.songShowPlusAddButton, + QtCore.SIGNAL(u'clicked()'), + self.onSongShowPlusAddButtonClicked) + QtCore.QObject.connect(self.songShowPlusRemoveButton, + QtCore.SIGNAL(u'clicked()'), + self.onSongShowPlusRemoveButtonClicked) + QtCore.QObject.connect(self.foilPresenterAddButton, + QtCore.SIGNAL(u'clicked()'), + self.onFoilPresenterAddButtonClicked) + QtCore.QObject.connect(self.foilPresenterRemoveButton, + QtCore.SIGNAL(u'clicked()'), + self.onFoilPresenterRemoveButtonClicked) def addCustomPages(self): """ @@ -188,6 +200,10 @@ class SongImportForm(OpenLPWizard): self.addFileSelectItem(u'ew', single_select=True) # Words of Worship self.addFileSelectItem(u'songBeamer') + # Song Show Plus + self.addFileSelectItem(u'songShowPlus') + # Foilpresenter + self.addFileSelectItem(u'foilPresenter') # Commented out for future use. # self.addFileSelectItem(u'csv', u'CSV', single_select=True) self.sourceLayout.addLayout(self.formatStack) @@ -199,60 +215,47 @@ class SongImportForm(OpenLPWizard): """ self.setWindowTitle( translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard')) - self.titleLabel.setText( - u'%s' % \ - translate('SongsPlugin.ImportWizardForm', - 'Welcome to the Song Import Wizard')) + self.titleLabel.setText(WizardStrings.HeaderStyle % + translate('OpenLP.Ui', 'Welcome to the Song Import Wizard')) self.informationLabel.setText( translate('SongsPlugin.ImportWizardForm', 'This wizard will help you to import songs from a variety of ' 'formats. Click the next button below to start the process by ' 'selecting a format to import from.')) - self.sourcePage.setTitle( - translate('SongsPlugin.ImportWizardForm', 'Select Import Source')) - self.sourcePage.setSubTitle( - translate('SongsPlugin.ImportWizardForm', - 'Select the import format, and where to import from.')) - self.formatLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Format:')) - self.formatComboBox.setItemText(0, - translate('SongsPlugin.ImportWizardForm', 'OpenLP 2.0')) - self.formatComboBox.setItemText(1, - translate('SongsPlugin.ImportWizardForm', 'openlp.org 1.x')) - self.formatComboBox.setItemText(2, - translate('SongsPlugin.ImportWizardForm', 'OpenLyrics')) - self.formatComboBox.setItemText(3, - translate('SongsPlugin.ImportWizardForm', 'OpenSong')) - self.formatComboBox.setItemText(4, - translate('SongsPlugin.ImportWizardForm', 'Words of Worship')) - self.formatComboBox.setItemText(5, - translate('SongsPlugin.ImportWizardForm', 'CCLI/SongSelect')) - self.formatComboBox.setItemText(6, - translate('SongsPlugin.ImportWizardForm', 'Songs of Fellowship')) - self.formatComboBox.setItemText(7, + self.sourcePage.setTitle(WizardStrings.ImportSelect) + self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong) + self.formatLabel.setText(WizardStrings.FormatLabel) + self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings.OLPV2) + self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings.OLPV1) + self.formatComboBox.setItemText( + SongFormat.OpenLyrics, WizardStrings.OL) + self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS) + self.formatComboBox.setItemText( + SongFormat.WordsOfWorship, WizardStrings.WoW) + self.formatComboBox.setItemText(SongFormat.CCLI, WizardStrings.CCLI) + self.formatComboBox.setItemText( + SongFormat.SongsOfFellowship, WizardStrings.SoF) + self.formatComboBox.setItemText(SongFormat.Generic, translate('SongsPlugin.ImportWizardForm', 'Generic Document/Presentation')) - self.formatComboBox.setItemText(8, - translate('SongsPlugin.ImportWizardForm', 'EasiSlides')) - self.formatComboBox.setItemText(9, - translate('SongsPlugin.ImportWizardForm', 'EasyWorship')) - self.formatComboBox.setItemText(10, - translate('SongsPlugin.ImportWizardForm', 'SongBeamer')) -# self.formatComboBox.setItemText(11, -# translate('SongsPlugin.ImportWizardForm', 'CSV')) + self.formatComboBox.setItemText( + SongFormat.EasiSlides, WizardStrings.ES) + self.formatComboBox.setItemText( + SongFormat.EasyWorship, WizardStrings.EW) + self.formatComboBox.setItemText( + SongFormat.SongBeamer, WizardStrings.SB) + self.formatComboBox.setItemText( + SongFormat.SongShowPlus, WizardStrings.SSP) + self.formatComboBox.setItemText( + SongFormat.FoilPresenter, WizardStrings.FP) +# self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV) self.openLP2FilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP2BrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.openLP2BrowseButton.setText(UiStrings.Browse) self.openLP1FilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.openLP1BrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.openLP1DisabledLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'The openlp.org 1.x ' - 'importer has been disabled due to a missing Python module. If ' - 'you want to use this importer, you will need to install the ' - '"python-sqlite" module.')) + self.openLP1BrowseButton.setText(UiStrings.Browse) + self.openLP1DisabledLabel.setText(WizardStrings.NoSqlite) self.openLyricsAddButton.setText( translate('SongsPlugin.ImportWizardForm', 'Add Files...')) self.openLyricsRemoveButton.setText( @@ -292,29 +295,31 @@ class SongImportForm(OpenLPWizard): 'find OpenOffice.org on your computer.')) self.easiSlidesFilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.easiSlidesBrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.easiSlidesBrowseButton.setText(UiStrings.Browse) self.ewFilenameLabel.setText( translate('SongsPlugin.ImportWizardForm', 'Filename:')) - self.ewBrowseButton.setText( - translate('SongsPlugin.ImportWizardForm', 'Browse...')) + self.ewBrowseButton.setText(UiStrings.Browse) self.songBeamerAddButton.setText( translate('SongsPlugin.ImportWizardForm', 'Add Files...')) self.songBeamerRemoveButton.setText( translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.songShowPlusAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.songShowPlusRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) + self.foilPresenterAddButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Add Files...')) + self.foilPresenterRemoveButton.setText( + translate('SongsPlugin.ImportWizardForm', 'Remove File(s)')) # self.csvFilenameLabel.setText( # translate('SongsPlugin.ImportWizardForm', 'Filename:')) -# self.csvBrowseButton.setText( -# translate('SongsPlugin.ImportWizardForm', 'Browse...')) - self.progressPage.setTitle( - translate('SongsPlugin.ImportWizardForm', 'Importing')) +# self.csvBrowseButton.setText(UiStrings.Browse) + self.progressPage.setTitle(WizardStrings.Importing) self.progressPage.setSubTitle( translate('SongsPlugin.ImportWizardForm', 'Please wait while your songs are imported.')) - self.progressLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Ready.')) - self.progressBar.setFormat( - translate('SongsPlugin.ImportWizardForm', '%p%')) + self.progressLabel.setText(WizardStrings.Ready) + self.progressBar.setFormat(WizardStrings.PercentSymbolFormat) # Align all QFormLayouts towards each other. width = max(self.formatLabel.minimumSizeHint().width(), self.openLP2FilenameLabel.minimumSizeHint().width()) @@ -331,146 +336,88 @@ class SongImportForm(OpenLPWizard): source_format = self.formatComboBox.currentIndex() if source_format == SongFormat.OpenLP2: if self.openLP2FilenameEdit.text().isEmpty(): - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No OpenLP 2.0 Song Database Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to select an OpenLP 2.0 song database ' - 'file to import from.')) + critical_error_message_box(UiStrings.NFSs, + WizardStrings.YouSpecifyFile % UiStrings.OLPV2) self.openLP2BrowseButton.setFocus() return False elif source_format == SongFormat.OpenLP1: if self.openLP1FilenameEdit.text().isEmpty(): - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No openlp.org 1.x Song Database Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to select an openlp.org 1.x song ' - 'database file to import from.')) + critical_error_message_box(UiStrings.NFSs, + WizardStrings.YouSpecifyFile % UiStrings.OLPV1) self.openLP1BrowseButton.setFocus() return False elif source_format == SongFormat.OpenLyrics: if self.openLyricsFileListWidget.count() == 0: - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No OpenLyrics Files Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one OpenLyrics ' - 'song file to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.OL) self.openLyricsAddButton.setFocus() return False elif source_format == SongFormat.OpenSong: if self.openSongFileListWidget.count() == 0: - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No OpenSong Files Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one OpenSong ' - 'song file to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.OS) self.openSongAddButton.setFocus() return False elif source_format == SongFormat.WordsOfWorship: if self.wordsOfWorshipFileListWidget.count() == 0: - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No Words of Worship Files Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one Words of Worship ' - 'file to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.WoW) self.wordsOfWorshipAddButton.setFocus() return False elif source_format == SongFormat.CCLI: if self.ccliFileListWidget.count() == 0: - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No CCLI Files Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one CCLI file ' - 'to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.CCLI) self.ccliAddButton.setFocus() return False elif source_format == SongFormat.SongsOfFellowship: if self.songsOfFellowshipFileListWidget.count() == 0: - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No Songs of Fellowship File Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one Songs of Fellowship ' - 'file to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.SoF) self.songsOfFellowshipAddButton.setFocus() return False elif source_format == SongFormat.Generic: if self.genericFileListWidget.count() == 0: - critical_error_message_box( + critical_error_message_box(UiStrings.NFSp, translate('SongsPlugin.ImportWizardForm', - 'No Document/Presentation Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one document or ' + 'You need to specify at least one document or ' 'presentation file to import from.')) self.genericAddButton.setFocus() return False elif source_format == SongFormat.EasiSlides: if self.easiSlidesFilenameEdit.text().isEmpty(): - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No Easislides Songs file selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to select an xml song file exported from ' - 'EasiSlides, to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.ES) self.easiSlidesBrowseButton.setFocus() return False elif source_format == SongFormat.EasyWorship: if self.ewFilenameEdit.text().isEmpty(): - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No EasyWorship Song Database Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to select an EasyWorship song database ' - 'file to import from.')) + critical_error_message_box(UiStrings.NFSs, + WizardStrings.YouSpecifyFile % WizardStrings.EW) self.ewBrowseButton.setFocus() return False elif source_format == SongFormat.SongBeamer: if self.songBeamerFileListWidget.count() == 0: - critical_error_message_box( - translate('SongsPlugin.ImportWizardForm', - 'No SongBeamer File Selected'), - translate('SongsPlugin.ImportWizardForm', - 'You need to add at least one SongBeamer ' - 'file to import from.')) + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.SB) self.songBeamerAddButton.setFocus() return False + elif source_format == SongFormat.SongShowPlus: + if self.songShowPlusFileListWidget.count() == 0: + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.SSP) + self.wordsOfWorshipAddButton.setFocus() + return False + elif source_format == SongFormat.FoilPresenter: + if self.foilPresenterFileListWidget.count() == 0: + critical_error_message_box(UiStrings.NFSp, + WizardStrings.YouSpecifyFile % WizardStrings.FP) + self.foilPresenterAddButton.setFocus() + return False return True elif self.currentPage() == self.progressPage: return True - def getFileName(self, title, editbox, filters=u''): - """ - Opens a QFileDialog and writes the filename to the given editbox. - - ``title`` - The title of the dialog (unicode). - - ``editbox`` - A editbox (QLineEdit). - - ``filters`` - The file extension filters. It should contain the file descriptions - as well as the file extensions. For example:: - - u'OpenLP 2.0 Databases (*.sqlite)' - """ - if filters: - filters += u';;' - filters += u'%s (*)' % translate('SongsPlugin.ImportWizardForm', - 'All Files') - filename = QtGui.QFileDialog.getOpenFileName(self, title, - SettingsManager.get_last_dir(self.plugin.settingsSection, 1), - filters) - if filename: - editbox.setText(filename) - SettingsManager.set_last_dir(self.plugin.settingsSection, - os.path.split(unicode(filename))[0], 1) - def getFiles(self, title, listbox, filters=u''): """ Opens a QFileDialog and writes the filenames to the given listbox. @@ -485,19 +432,17 @@ class SongImportForm(OpenLPWizard): The file extension filters. It should contain the file descriptions as well as the file extensions. For example:: - u'SongBeamer files (*.sng)' + u'SongBeamer Files (*.sng)' """ if filters: filters += u';;' - filters += u'%s (*)' % translate('SongsPlugin.ImportWizardForm', - 'All Files') + filters += u'%s (*)' % UiStrings.AllFiles filenames = QtGui.QFileDialog.getOpenFileNames(self, title, SettingsManager.get_last_dir(self.plugin.settingsSection, 1), filters) if filenames: listbox.addItems(filenames) - SettingsManager.set_last_dir( - self.plugin.settingsSection, + SettingsManager.set_last_dir(self.plugin.settingsSection, os.path.split(unicode(filenames[0]))[0], 1) def getListOfFiles(self, listbox): @@ -521,9 +466,7 @@ class SongImportForm(OpenLPWizard): """ Get OpenLP v2 song database file """ - self.getFileName( - translate('SongsPlugin.ImportWizardForm', - 'Select OpenLP 2.0 Database File'), + self.getFileName(WizardStrings.OpenTypeFile % UiStrings.OLPV2, self.openLP2FilenameEdit, u'%s (*.sqlite)' % (translate('SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases')) @@ -533,9 +476,7 @@ class SongImportForm(OpenLPWizard): """ Get OpenLP v1 song database file """ - self.getFileName( - translate('SongsPlugin.ImportWizardForm', - 'Select openlp.org 1.x Database File'), + self.getFileName(WizardStrings.OpenTypeFile % UiStrings.OLPV1, self.openLP1FilenameEdit, u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm', 'openlp.org v1.x Databases') @@ -545,11 +486,8 @@ class SongImportForm(OpenLPWizard): """ Get OpenLyrics song database files """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', - 'Select OpenLyrics Files'), - self.openLyricsFileListWidget - ) + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OL, + self.openLyricsFileListWidget) def onOpenLyricsRemoveButtonClicked(self): """ @@ -561,10 +499,8 @@ class SongImportForm(OpenLPWizard): """ Get OpenSong song database files """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', 'Select Open Song Files'), - self.openSongFileListWidget - ) + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OS, + self.openSongFileListWidget) def onOpenSongRemoveButtonClicked(self): """ @@ -576,9 +512,7 @@ class SongImportForm(OpenLPWizard): """ Get Words of Worship song database files """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', - 'Select Words of Worship Files'), + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.WoW, self.wordsOfWorshipFileListWidget, u'%s (*.wsg *.wow-song)' % translate('SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files') @@ -594,11 +528,8 @@ class SongImportForm(OpenLPWizard): """ Get CCLI song database files """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', - 'Select CCLI Files'), - self.ccliFileListWidget - ) + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.CCLI, + self.ccliFileListWidget) def onCCLIRemoveButtonClicked(self): """ @@ -610,12 +541,10 @@ class SongImportForm(OpenLPWizard): """ Get Songs of Fellowship song database files """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', - 'Select Songs of Fellowship Files'), + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SoF, self.songsOfFellowshipFileListWidget, u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm', - 'Songs Of Felloship Song Files') + 'Songs Of Fellowship Song Files') ) def onSongsOfFellowshipRemoveButtonClicked(self): @@ -641,31 +570,23 @@ class SongImportForm(OpenLPWizard): self.removeSelectedItems(self.genericFileListWidget) def onEasiSlidesBrowseButtonClicked(self): - self.getFileName( - translate('SongsPlugin.ImportWizardForm', - 'Select EasiSlides songfile'), - self.easiSlidesFilenameEdit - ) + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.ES, + self.easiSlidesFilenameEdit) def onEWBrowseButtonClicked(self): """ Get EasyWorship song database files """ - self.getFileName( - translate('SongsPlugin.ImportWizardForm', - 'Select EasyWorship Database File'), - self.ewFilenameEdit - ) + self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.EW, + self.ewFilenameEdit) def onSongBeamerAddButtonClicked(self): """ Get SongBeamer song database files """ - self.getFiles( - translate('SongsPlugin.ImportWizardForm', - 'Select SongBeamer Files'), + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SB, self.songBeamerFileListWidget, u'%s (*.sng)' % - translate('SongsPlugin.ImportWizardForm', 'SongBeamer files') + translate('SongsPlugin.ImportWizardForm', 'SongBeamer Files') ) def onSongBeamerRemoveButtonClicked(self): @@ -674,11 +595,37 @@ class SongImportForm(OpenLPWizard): """ self.removeSelectedItems(self.songBeamerFileListWidget) - def registerFields(self): + def onSongShowPlusAddButtonClicked(self): """ - Register song import wizard fields. + Get SongShow Plus song database files """ - pass + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SSP, + self.songShowPlusFileListWidget, u'%s (*.sbsong)' + % translate('SongsPlugin.ImportWizardForm', + 'SongShow Plus Song Files') + ) + + def onSongShowPlusRemoveButtonClicked(self): + """ + Remove selected SongShow Plus files from the import list + """ + self.removeSelectedItems(self.songShowPlusFileListWidget) + + def onFoilPresenterAddButtonClicked(self): + """ + Get FoilPresenter song database files + """ + self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.FP, + self.foilPresenterFileListWidget, u'%s (*.foil)' + % translate('SongsPlugin.ImportWizardForm', + 'Foilpresenter Song Files') + ) + + def onFoilPresenterRemoveButtonClicked(self): + """ + Remove selected FoilPresenter files from the import list + """ + self.removeSelectedItems(self.foilPresenterFileListWidget) def setDefaults(self): """ @@ -699,6 +646,8 @@ class SongImportForm(OpenLPWizard): self.easiSlidesFilenameEdit.setText(u'') self.ewFilenameEdit.setText(u'') self.songBeamerFileListWidget.clear() + self.songShowPlusFileListWidget.clear() + self.foilPresenterFileListWidget.clear() #self.csvFilenameEdit.setText(u'') def preWizard(self): @@ -706,8 +655,7 @@ class SongImportForm(OpenLPWizard): Perform pre import tasks """ OpenLPWizard.preWizard(self) - self.progressLabel.setText( - translate('SongsPlugin.ImportWizardForm', 'Starting import...')) + self.progressLabel.setText(WizardStrings.StartingImport) Receiver.send_message(u'openlp_process_events') def performWizard(self): @@ -756,7 +704,7 @@ class SongImportForm(OpenLPWizard): self.songsOfFellowshipFileListWidget) ) elif source_format == SongFormat.Generic: - # Import a generic document or presentatoin + # Import a generic document or presentation importer = self.plugin.importSongs(SongFormat.Generic, filenames=self.getListOfFiles(self.genericFileListWidget) ) @@ -775,9 +723,18 @@ class SongImportForm(OpenLPWizard): importer = self.plugin.importSongs(SongFormat.SongBeamer, filenames=self.getListOfFiles(self.songBeamerFileListWidget) ) + elif source_format == SongFormat.SongShowPlus: + # Import ShongShow Plus songs + importer = self.plugin.importSongs(SongFormat.SongShowPlus, + filenames=self.getListOfFiles(self.songShowPlusFileListWidget) + ) + elif source_format == SongFormat.FoilPresenter: + # Import Foilpresenter songs + importer = self.plugin.importSongs(SongFormat.FoilPresenter, + filenames=self.getListOfFiles(self.foilPresenterFileListWidget) + ) if importer.do_import(): - self.progressLabel.setText( - translate('SongsPlugin.SongImportForm', 'Finished import.')) + self.progressLabel.setText(WizardStrings.FinishedImport) else: self.progressLabel.setText( translate('SongsPlugin.SongImportForm', diff --git a/openlp/plugins/songs/forms/songmaintenancedialog.py b/openlp/plugins/songs/forms/songmaintenancedialog.py index 51fafcc7a..42ec16352 100644 --- a/openlp/plugins/songs/forms/songmaintenancedialog.py +++ b/openlp/plugins/songs/forms/songmaintenancedialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,7 +26,9 @@ from PyQt4 import QtCore, QtGui -from openlp.core.lib import build_icon, translate +from openlp.core.lib import build_icon +from openlp.core.lib.ui import UiStrings +from openlp.plugins.songs.lib.ui import SongStrings class Ui_SongMaintenanceDialog(object): def setupUi(self, songMaintenanceDialog): @@ -143,34 +145,21 @@ class Ui_SongMaintenanceDialog(object): QtCore.QMetaObject.connectSlotsByName(songMaintenanceDialog) def retranslateUi(self, songMaintenanceDialog): - songMaintenanceDialog.setWindowTitle( - translate('SongsPlugin.SongMaintenanceForm', 'Song Maintenance')) - authorsString = translate('SongsPlugin.SongMaintenanceForm', 'Authors') - topicsString = translate('SongsPlugin.SongMaintenanceForm', 'Topics') - booksString = translate('SongsPlugin.SongMaintenanceForm', 'Song Books') - self.listItemAuthors.setText(authorsString) - self.listItemTopics.setText(topicsString) - self.listItemBooks.setText(booksString) - self.authorsAddButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Add')) - self.authorsEditButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Edit')) - self.authorsDeleteButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Delete')) - self.topicsAddButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Add')) - self.topicsEditButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Edit')) - self.topicsDeleteButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Delete')) - self.booksAddButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Add')) - self.booksEditButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Edit')) - self.booksDeleteButton.setText( - translate('SongsPlugin.SongMaintenanceForm', '&Delete')) - typeListWidth = max(self.fontMetrics().width(authorsString), - self.fontMetrics().width(topicsString), - self.fontMetrics().width(booksString)) + songMaintenanceDialog.setWindowTitle(SongStrings.SongMaintenance) + self.listItemAuthors.setText(SongStrings.Authors) + self.listItemTopics.setText(SongStrings.Topics) + self.listItemBooks.setText(SongStrings.SongBooks) + self.authorsAddButton.setText(UiStrings.Add) + self.authorsEditButton.setText(UiStrings.Edit) + self.authorsDeleteButton.setText(UiStrings.Delete) + self.topicsAddButton.setText(UiStrings.Add) + self.topicsEditButton.setText(UiStrings.Edit) + self.topicsDeleteButton.setText(UiStrings.Delete) + self.booksAddButton.setText(UiStrings.Add) + self.booksEditButton.setText(UiStrings.Edit) + self.booksDeleteButton.setText(UiStrings.Delete) + typeListWidth = max(self.fontMetrics().width(SongStrings.Authors), + self.fontMetrics().width(SongStrings.Topics), + self.fontMetrics().width(SongStrings.SongBooks)) self.typeListWidget.setFixedWidth(typeListWidth + self.typeListWidget.iconSize().width() + 32) diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 1eb63fbf4..d5f432c2b 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,7 +29,7 @@ from PyQt4 import QtGui, QtCore from sqlalchemy.sql import and_ from openlp.core.lib import Receiver, translate -from openlp.core.lib.ui import critical_error_message_box +from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.plugins.songs.forms import AuthorsForm, TopicsForm, SongBookForm from openlp.plugins.songs.lib.db import Author, Book, Topic, Song from songmaintenancedialog import Ui_SongMaintenanceDialog @@ -103,19 +103,19 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): return -1 def _deleteItem(self, item_class, list_widget, reset_func, dlg_title, - del_text, err_text, sel_text): + del_text, err_text): item_id = self._getCurrentItemId(list_widget) if item_id != -1: item = self.manager.get_object(item_class, item_id) if item and len(item.songs) == 0: - if critical_error_message_box(title=dlg_title, message=del_text, - parent=self, question=True) == QtGui.QMessageBox.Yes: + if critical_error_message_box(dlg_title, del_text, self, + True) == QtGui.QMessageBox.Yes: self.manager.delete_object(item_class, item.id) reset_func() else: critical_error_message_box(dlg_title, err_text) else: - critical_error_message_box(dlg_title, sel_text) + critical_error_message_box(dlg_title, UiStrings.NISs) def resetAuthors(self): """ @@ -268,11 +268,9 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): temp_last_name = author.last_name temp_display_name = author.display_name if self.authorform.exec_(False): - author.first_name = unicode( - self.authorform.firstNameEdit.text()) + author.first_name = unicode(self.authorform.firstNameEdit.text()) author.last_name = unicode(self.authorform.lastNameEdit.text()) - author.display_name = unicode( - self.authorform.displayEdit.text()) + author.display_name = unicode(self.authorform.displayEdit.text()) if self.checkAuthor(author, True): if self.manager.save_object(author): self.resetAuthors() @@ -449,37 +447,31 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): self._deleteItem(Author, self.authorsListWidget, self.resetAuthors, translate('SongsPlugin.SongMaintenanceForm', 'Delete Author'), translate('SongsPlugin.SongMaintenanceForm', - 'Are you sure you want to delete the selected author?'), - translate('SongsPlugin.SongMaintenanceForm', - 'This author cannot be deleted, they are currently ' - 'assigned to at least one song.'), - translate('SongsPlugin.SongMaintenanceForm', 'No author selected!')) + 'Are you sure you want to delete the selected author?'), + translate('SongsPlugin.SongMaintenanceForm', 'This author cannot ' + 'be deleted, they are currently assigned to at least one song.')) def onTopicDeleteButtonClick(self): """ - Delete the Book is the Book is not attached to any songs. + Delete the Book if the Book is not attached to any songs. """ self._deleteItem(Topic, self.topicsListWidget, self.resetTopics, translate('SongsPlugin.SongMaintenanceForm', 'Delete Topic'), translate('SongsPlugin.SongMaintenanceForm', - 'Are you sure you want to delete the selected topic?'), - translate('SongsPlugin.SongMaintenanceForm', - 'This topic cannot be deleted, it is currently ' - 'assigned to at least one song.'), - translate('SongsPlugin.SongMaintenanceForm', 'No topic selected!')) + 'Are you sure you want to delete the selected topic?'), + translate('SongsPlugin.SongMaintenanceForm', 'This topic cannot ' + 'be deleted, it is currently assigned to at least one song.')) def onBookDeleteButtonClick(self): """ - Delete the Book is the Book is not attached to any songs. + Delete the Book if the Book is not attached to any songs. """ self._deleteItem(Book, self.booksListWidget, self.resetBooks, translate('SongsPlugin.SongMaintenanceForm', 'Delete Book'), translate('SongsPlugin.SongMaintenanceForm', - 'Are you sure you want to delete the selected book?'), - translate('SongsPlugin.SongMaintenanceForm', - 'This book cannot be deleted, it is currently ' - 'assigned to at least one song.'), - translate('SongsPlugin.SongMaintenanceForm', 'No book selected!')) + 'Are you sure you want to delete the selected book?'), + translate('SongsPlugin.SongMaintenanceForm', 'This book cannot be ' + 'deleted, it is currently assigned to at least one song.')) def onAuthorsListRowChanged(self, row): """ diff --git a/openlp/plugins/songs/forms/topicsdialog.py b/openlp/plugins/songs/forms/topicsdialog.py index 596597034..ee6fc88e7 100644 --- a/openlp/plugins/songs/forms/topicsdialog.py +++ b/openlp/plugins/songs/forms/topicsdialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,7 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import translate -from openlp.core.lib.ui import create_save_cancel_button_box +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_TopicsDialog(object): def setupUi(self, topicsDialog): @@ -45,7 +45,7 @@ class Ui_TopicsDialog(object): self.nameLayout.addRow(self.nameLabel, self.nameEdit) self.dialogLayout.addLayout(self.nameLayout) self.dialogLayout.addWidget( - create_save_cancel_button_box(topicsDialog)) + create_accept_reject_button_box(topicsDialog)) self.retranslateUi(topicsDialog) topicsDialog.setMaximumHeight(topicsDialog.sizeHint().height()) QtCore.QMetaObject.connectSlotsByName(topicsDialog) diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index 792570c93..a191d8156 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songs/lib/__init__.py b/openlp/plugins/songs/lib/__init__.py index af8b71795..507fd02d4 100644 --- a/openlp/plugins/songs/lib/__init__.py +++ b/openlp/plugins/songs/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,7 +25,10 @@ ############################################################################### from PyQt4 import QtGui + from openlp.core.lib import translate +from db import Author +from ui import SongStrings class VerseType(object): """ @@ -40,70 +43,158 @@ class VerseType(object): Ending = 5 Other = 6 - @staticmethod - def to_string(verse_type): - """ - Return a string for a given VerseType + Names = [ + u'Verse', + u'Chorus', + u'Bridge', + u'Pre-Chorus', + u'Intro', + u'Ending', + u'Other'] + Tags = [name[0].lower() for name in Names] - ``verse_type`` - The type to return a string for - """ - if not isinstance(verse_type, int): - verse_type = verse_type.lower() - if verse_type == VerseType.Verse or verse_type == \ - unicode(VerseType.to_string(VerseType.Verse)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Verse') - elif verse_type == VerseType.Chorus or verse_type == \ - unicode(VerseType.to_string(VerseType.Chorus)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Chorus') - elif verse_type == VerseType.Bridge or verse_type == \ - unicode(VerseType.to_string(VerseType.Bridge)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Bridge') - elif verse_type == VerseType.PreChorus or verse_type == \ - unicode(VerseType.to_string(VerseType.PreChorus)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Pre-Chorus') - elif verse_type == VerseType.Intro or verse_type == \ - unicode(VerseType.to_string(VerseType.Intro)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Intro') - elif verse_type == VerseType.Ending or verse_type == \ - unicode(VerseType.to_string(VerseType.Ending)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Ending') - elif verse_type == VerseType.Other or verse_type == \ - unicode(VerseType.to_string(VerseType.Other)).lower()[0]: - return translate('SongsPlugin.VerseType', 'Other') + TranslatedNames = [ + unicode(translate('SongsPlugin.VerseType', 'Verse')), + unicode(translate('SongsPlugin.VerseType', 'Chorus')), + unicode(translate('SongsPlugin.VerseType', 'Bridge')), + unicode(translate('SongsPlugin.VerseType', 'Pre-Chorus')), + unicode(translate('SongsPlugin.VerseType', 'Intro')), + unicode(translate('SongsPlugin.VerseType', 'Ending')), + unicode(translate('SongsPlugin.VerseType', 'Other'))] + TranslatedTags = [name[0].lower() for name in TranslatedNames] @staticmethod - def from_string(verse_type): + def translated_tag(verse_tag, strict=False): + """ + Return the translated UPPERCASE tag for a given tag, + used to show translated verse tags in UI + + ``verse_tag`` + The string to return a VerseType for + + ``strict`` + Determines if the default Other or None should be returned + """ + if strict: + not_found_value = None + else: + not_found_value = VerseType.TranslatedTags[VerseType.Other].upper() + verse_tag = verse_tag[0].lower() + for num, tag in enumerate(VerseType.Tags): + if verse_tag == tag: + return VerseType.TranslatedTags[num].upper() + return not_found_value + + @staticmethod + def translated_name(verse_tag, strict=False): + """ + Return the translated name for a given tag + + ``verse_tag`` + The string to return a VerseType for + + ``strict`` + Determines if the default Other or None should be returned + """ + if strict: + not_found_value = None + else: + not_found_value = VerseType.TranslatedNames[VerseType.Other] + verse_tag = verse_tag[0].lower() + for num, tag in enumerate(VerseType.Tags): + if verse_tag == tag: + return VerseType.TranslatedNames[num] + return not_found_value + + @staticmethod + def from_tag(verse_tag, strict=False): + """ + Return the VerseType for a given tag + + ``verse_tag`` + The string to return a VerseType for + + ``strict`` + Determines if the default Other or None should be returned + """ + if strict: + no_return_value = None + else: + no_return_value = VerseType.Other + verse_tag = verse_tag[0].lower() + for num, tag in enumerate(VerseType.Tags): + if verse_tag == tag: + return num + return no_return_value + + @staticmethod + def from_translated_tag(verse_tag): + """ + Return the VerseType for a given tag + + ``verse_tag`` + The string to return a VerseType for + """ + verse_tag = verse_tag[0].lower() + for num, tag in enumerate(VerseType.TranslatedTags): + if verse_tag == tag: + return num + + @staticmethod + def from_string(verse_name): """ Return the VerseType for a given string - ``verse_type`` + ``verse_name`` The string to return a VerseType for """ - verse_type = verse_type.lower() - if verse_type == unicode(VerseType.to_string(VerseType.Verse)).lower(): - return VerseType.Verse - elif verse_type == \ - unicode(VerseType.to_string(VerseType.Chorus)).lower(): - return VerseType.Chorus - elif verse_type == \ - unicode(VerseType.to_string(VerseType.Bridge)).lower(): - return VerseType.Bridge - elif verse_type == \ - unicode(VerseType.to_string(VerseType.PreChorus)).lower(): - return VerseType.PreChorus - elif verse_type == \ - unicode(VerseType.to_string(VerseType.Intro)).lower(): - return VerseType.Intro - elif verse_type == \ - unicode(VerseType.to_string(VerseType.Ending)).lower(): - return VerseType.Ending - elif verse_type == \ - unicode(VerseType.to_string(VerseType.Other)).lower(): - return VerseType.Other + verse_name = verse_name.lower() + for num, name in enumerate(VerseType.Names): + if verse_name == name.lower(): + return num + @staticmethod + def from_translated_string(verse_name): + """ + Return the VerseType for a given string + + ``verse_name`` + The string to return a VerseType for + """ + verse_name = verse_name.lower() + for num, translation in enumerate(VerseType.TranslatedNames): + if verse_name == translation.lower(): + return num + + @staticmethod + def from_loose_input(verse_name): + """ + Return the VerseType for a given string, Other if not found + + ``verse_name`` + The string to return a VerseType for + """ + verse_index = None + if len(verse_name) > 1: + verse_index = VerseType.from_translated_string(verse_name) + if verse_index is None: + verse_index = VerseType.from_string(verse_name) + if verse_index is None: + verse_index = VerseType.from_translated_tag(verse_name) + if verse_index is None: + verse_index = VerseType.from_tag(verse_name) + return verse_index def retrieve_windows_encoding(recommendation=None): + """ + Determines which encoding to use on an information source. The process uses + both automated detection, which is passed to this method as a + recommendation, and user confirmation to return an encoding. + + ``recommendation`` + A recommended encoding discovered programmatically for the user to + confirm. + """ # map chardet result to compatible windows standard code page codepage_mapping = {'IBM866': u'cp866', 'TIS-620': u'cp874', 'SHIFT_JIS': u'cp932', 'GB2312': u'cp936', 'HZ-GB-2312': u'cp936', @@ -153,6 +244,23 @@ def retrieve_windows_encoding(recommendation=None): return None return filter(lambda item: item[1] == choice[0], encodings)[0][0] +def add_author_unknown(manager, song): + """ + Add the default author *Author Unknown* to the song. + + ``manager`` + The song's manager. + + ``song`` + The song object. + """ + name = SongStrings.AuthorUnknown + author = manager.get_object_filtered(Author, Author.display_name == name) + if author is None: + author = Author.populate( + display_name=name, last_name=u'', first_name=u'') + song.authors.append(author) + from xml import OpenLyrics, SongXML from songstab import SongsTab from mediaitem import SongMediaItem diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index 441391d02..b9236919a 100644 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund, Derek Scotney # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -51,22 +51,17 @@ class CCLIFileImport(SongImport): ``filenames`` The files to be imported. """ - SongImport.__init__(self, manager) - if u'filenames' in kwargs: - self.filenames = kwargs[u'filenames'] - log.debug(self.filenames) - else: - raise KeyError(u'Keyword argument "filenames" not supplied.') + SongImport.__init__(self, manager, **kwargs) def do_import(self): """ Import either a .usr or a .txt SongSelect file """ log.debug(u'Starting CCLI File Import') - song_total = len(self.filenames) + song_total = len(self.import_source) self.import_wizard.progressBar.setMaximum(song_total) song_count = 1 - for filename in self.filenames: + for filename in self.import_source: self.import_wizard.incrementProgressBar(unicode(translate( 'SongsPlugin.CCLIFileImport', 'Importing song %d of %d')) % (song_count, song_total)) @@ -187,7 +182,7 @@ class CCLIFileImport(SongImport): if check_first_verse_line: if verse_lines[0].startswith(u'(PRE-CHORUS'): verse_type = u'P' - log.debug(u'USR verse PRE-CHORUS: %s', verse_lines[0] ) + log.debug(u'USR verse PRE-CHORUS: %s', verse_lines[0]) verse_text = verse_lines[1] elif verse_lines[0].startswith(u'(BRIDGE'): verse_type = u'B' @@ -204,8 +199,11 @@ class CCLIFileImport(SongImport): if len(author_list) < 2: author_list = song_author.split(u'|') for author in author_list: - seperated = author.split(u',') - self.add_author(seperated[1].strip() + u' ' + seperated[0].strip()) + separated = author.split(u',') + if len(separated) > 1: + self.add_author(u' '.join(reversed(separated))) + else: + self.add_author(author) self.title = song_name self.copyright = song_copyright self.ccli_number = song_ccli diff --git a/openlp/plugins/songs/lib/db.py b/openlp/plugins/songs/lib/db.py index 2bbf818b3..a6255476a 100644 --- a/openlp/plugins/songs/lib/db.py +++ b/openlp/plugins/songs/lib/db.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -71,7 +71,6 @@ class Topic(BaseModel): def init_schema(url): - """ Setup the songs database connection and initialise the database schema. diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 0b10ce428..c4683765b 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -30,6 +30,7 @@ from lxml import etree, objectify import re from openlp.core.lib import translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) @@ -45,33 +46,30 @@ class EasiSlidesImport(SongImport): """ Initialise the class. """ - SongImport.__init__(self, manager) - self.filename = kwargs[u'filename'] - self.song = None + SongImport.__init__(self, manager, **kwargs) self.commit = True def do_import(self): """ - Import either each of the files in self.filenames - each element of + Import either each of the files in self.import_sources - each element of which can be either a single opensong file, or a zipfile containing multiple opensong files. If `self.commit` is set False, the 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.filename) + log.info(u'Importing EasiSlides XML file %s', self.import_source) parser = etree.XMLParser(remove_blank_text=True) - file = etree.parse(self.filename, parser) + file = etree.parse(self.import_source, parser) xml = unicode(etree.tostring(file)) song_xml = objectify.fromstring(xml) self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - u'Importing %s...')) % os.path.split(self.filename)[-1]) + WizardStrings.ImportingType % os.path.split(self.import_source)[-1]) self.import_wizard.progressBar.setMaximum(len(song_xml.Item)) for song in song_xml.Item: self.import_wizard.incrementProgressBar( unicode(translate('SongsPlugin.ImportWizardForm', u'Importing %s, song %s...')) % - (os.path.split(self.filename)[-1], song.Title1)) + (os.path.split(self.import_source)[-1], song.Title1)) success = self._parse_song(song) if not success or self.stop_import_flag: return False @@ -81,14 +79,16 @@ class EasiSlidesImport(SongImport): def _parse_song(self, song): self._success = True - self._add_title(self.title, song.Title1, True) - self._add_alttitle(self.alternate_title, song.Title2) - self._add_number(self.song_number, song.SongNumber) + self._add_unicode_attribute(u'title', song.Title1, True) + self._add_unicode_attribute(u'alternate_title', song.Title2) + self._add_unicode_attribute(u'song_number', song.SongNumber) if self.song_number == u'0': self.song_number = u'' self._add_authors(song) - self._add_copyright(song) - self._add_book(self.song_book_name, song.BookReference) + self._add_copyright(song.Copyright) + self._add_copyright(song.LicenceAdmin1) + self._add_copyright(song.LicenceAdmin2) + self._add_unicode_attribute(u'song_book_name', song.BookReference) self._parse_and_add_lyrics(song) return self._success @@ -96,7 +96,7 @@ class EasiSlidesImport(SongImport): mandatory=False): """ Add imported values to the song model converting them to unicode at the - same time. If the unicode decode fails or a mandatory attribute is not + same time. If the unicode decode fails or a mandatory attribute is not present _success is set to False so the importer can react appropriately. @@ -110,7 +110,7 @@ class EasiSlidesImport(SongImport): Signals that this attribute must exist in a valid song. """ try: - self_attribute = unicode(import_attribute).strip() + setattr(self, self_attribute, unicode(import_attribute).strip()) except UnicodeDecodeError: log.exception(u'UnicodeDecodeError decoding %s' % import_attribute) self._success = False @@ -124,7 +124,7 @@ class EasiSlidesImport(SongImport): authors = unicode(song.Writer).split(u',') for author in authors: author = author.strip() - if len(author) > 0: + if len(author): self.authors.append(author) except UnicodeDecodeError: log.exception(u'Unicode decode error while decoding Writer') @@ -132,35 +132,18 @@ class EasiSlidesImport(SongImport): except AttributeError: pass - def _add_copyright(self, song): - """ - Assign the copyright information from the import to the song being - created. - - ``song`` - The current song being imported. - """ - copyright_list = [] - self.__add_copyright_element(copyright_list, song.Copyright) - self.__add_copyright_element(copyright_list, song.LicenceAdmin1) - self.__add_copyright_element(copyright_list, song.LicenceAdmin2) - self.add_copyright(u' '.join(copyright_list)) - - def __add_copyright_element(self, copyright_list, element): + def _add_copyright(self, element): """ Add a piece of copyright to the total copyright information for the song. - ``copyright_list`` - The array to add the information to. - ``element`` The imported variable to get the data from. """ try: - copyright_list.append(unicode(element).strip()) + self.add_copyright(unicode(element).strip()) except UnicodeDecodeError: - log.exception(u'Unicode error decoding %s' % element) + log.exception(u'Unicode error on decoding copyright: %s' % element) self._success = False except AttributeError: pass @@ -285,10 +268,12 @@ class EasiSlidesImport(SongImport): # as these appeared originally in the file for [reg, vt, vn, inst] in our_verse_order: if self._listHas(verses, [reg, vt, vn, inst]): + # this is false, but needs user input + lang = None versetag = u'%s%s' % (vt, vn) versetags.append(versetag) lines = u'\n'.join(verses[reg][vt][vn][inst]) - self.verses.append([versetag, lines]) + self.verses.append([versetag, lines, lang]) SeqTypes = { u'p': u'P1', diff --git a/openlp/plugins/songs/lib/ewimport.py b/openlp/plugins/songs/lib/ewimport.py index 312e3b759..880c7f547 100644 --- a/openlp/plugins/songs/lib/ewimport.py +++ b/openlp/plugins/songs/lib/ewimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund, Jeffrey Smith # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,6 +32,7 @@ import os import struct from openlp.core.lib import translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import retrieve_windows_encoding from songimport import SongImport @@ -71,7 +72,7 @@ def strip_rtf(blob, encoding): elif control_str == 'tab': clear_text.append(u'\t') # Prefer the encoding specified by the RTF data to that - # specified by the Paradox table header + # specified by the Paradox table header # West European encoding elif control_str == 'fcharset0': encoding = u'cp1252' @@ -128,14 +129,14 @@ class FieldDescEntry: self.type = type self.size = size + class EasyWorshipSongImport(SongImport): """ The :class:`EasyWorshipSongImport` class provides OpenLP with the ability to import EasyWorship song files. """ def __init__(self, manager, **kwargs): - self.import_source = kwargs[u'filename'] - SongImport.__init__(self, manager) + SongImport.__init__(self, manager, **kwargs) def do_import(self): # Open the DB and MB files if they exist @@ -163,7 +164,7 @@ class EasyWorshipSongImport(SongImport): if code_page == 852: self.encoding = u'cp1250' # The following codepage to actual encoding mappings have not been - # observed, but merely guessed. Actual example files are needed. + # observed, but merely guessed. Actual example files are needed. elif code_page == 737: self.encoding = u'cp1253' elif code_page == 775: @@ -231,8 +232,7 @@ class EasyWorshipSongImport(SongImport): title = self.get_field(fi_title) if title: self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - 'Importing "%s"...')) % title, 0) + WizardStrings.ImportingType % title, 0) self.title = title # Get remaining fields copy = self.get_field(fi_copy) diff --git a/openlp/plugins/songs/lib/foilpresenterimport.py b/openlp/plugins/songs/lib/foilpresenterimport.py new file mode 100644 index 000000000..0d81e6f41 --- /dev/null +++ b/openlp/plugins/songs/lib/foilpresenterimport.py @@ -0,0 +1,574 @@ + # -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The XML of `Foilpresenter `_ songs is of the format:: + + + + 2004.6.18.18.44.37.0767 + 2011.1.21.8.53.5 + + Above all + + 1 + + + 0 + Notiz + 1.0 + + 0,0,0 + 255,255,255 + + + Standard + 0 + + + + 0 + Verdana + 14 + 0 + 0 + 0 + 1 + Above all powers, above all kings, + above all nature an all created things; + above all wisdom and all the ways of man, + You were here before the world began. + 1 + + + + Herr du bist maechtig.foil + + + Arial + 7 + 3 + 0 + 1 + 0 + Text und Musik: Lenny LeBlanc/Paul Baloche + + + + Feiert Jesus 3 + 10 + + + + Worship + + +""" + +import logging +import re +import os + +from lxml import etree, objectify + +from openlp.core.ui.wizard import WizardStrings +from openlp.plugins.songs.lib import add_author_unknown, VerseType +from openlp.plugins.songs.lib.songimport import SongImport +from openlp.plugins.songs.lib.db import Author, Book, Song, Topic +from openlp.plugins.songs.lib.xml import SongXML + +log = logging.getLogger(__name__) + +class FoilPresenterImport(SongImport): + """ + This provides the Foilpresenter import. + """ + def __init__(self, manager, **kwargs): + """ + Initialise the import. + """ + log.debug(u'initialise FoilPresenterImport') + SongImport.__init__(self, manager, **kwargs) + self.FoilPresenter = FoilPresenter(self.manager) + + def do_import(self): + """ + Imports the songs. + """ + self.import_wizard.progressBar.setMaximum(len(self.import_source)) + parser = etree.XMLParser(remove_blank_text=True) + for file_path in self.import_source: + if self.stop_import_flag: + return False + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % os.path.basename(file_path)) + try: + parsed_file = etree.parse(file_path, parser) + xml = unicode(etree.tostring(parsed_file)) + if self.FoilPresenter.xml_to_song(xml) is None: + log.debug(u'File could not be imported: %s' % file_path) + except etree.XMLSyntaxError: + log.exception(u'XML syntax error in file %s' % file_path) + return True + + +class FoilPresenter(object): + """ + This class represents the converter for Foilpresenter XML from a song. + + As Foilpresenter has a rich set of different features, we cannot support + them all. The following features are supported by the :class:`Foilpresenter` + + OpenPL does not support styletype and font attributes like "align, font, + textsize, bold, italic, underline" + + ** + This property is currently not supported. + + ** + As OpenLP does only support one title, the first titlestring becomes + title, all other titlestrings will be alternate titles + + *<sprache>* + This property is not supported. + + *<ccliid>* + The *<ccliid>* property is fully supported. + + *<tonart>* + This property is currently not supported. + + *<valign>* + This property is not supported. + + *<notiz>* + The *<notiz>* property is fully supported. + + *<versionsinfo>* + This property is not supported. + + *<farben>* + This property is not supported. + + *<reihenfolge>* = verseOrder + OpenLP supports this property. + + *<strophen>* + Only the attributes *key* and *text* are supported. + + *<verkn>* + This property is not supported. + + *<verkn>* + This property is not supported. + + *<copyright>* + Only the attribute *text* is supported. => Done + + *<buch>* = songbooks + As OpenLP does only support one songbook, we cannot consider more than + one songbook. + + *<kategorien>* + This property is not supported. + + The tag *<author>* is not support by foilpresenter, mostly the author is + named in the <copyright> tag. We try to extract the authors from the + <copyright> tag. + + """ + def __init__(self, manager): + self.manager = manager + + def xml_to_song(self, xml): + """ + Create and save a song from Foilpresenter format xml to the database. + + ``xml`` + The XML to parse (unicode). + """ + # No xml get out of here. + if not xml: + return None + song = Song() + if xml[:5] == u'<?xml': + xml = xml[38:] + # Because "text" seems to be an reserverd word, we have to recompile it. + xml = re.compile(u'<text>').sub(u'<text_>', xml) + xml = re.compile(u'</text>').sub(u'</text_>', xml) + song_xml = objectify.fromstring(xml) + foilpresenterfolie = song_xml + self._process_copyright(foilpresenterfolie, song) + self._process_cclinumber(foilpresenterfolie, song) + self._process_titles(foilpresenterfolie, song) + # The verse order is processed with the lyrics! + self._process_lyrics(foilpresenterfolie, song) + self._process_comments(foilpresenterfolie, song) + self._process_authors(foilpresenterfolie, song) + self._process_songbooks(foilpresenterfolie, song) + self._process_topics(foilpresenterfolie, song) + self.manager.save_object(song) + return song.id + + def _child(self, element): + """ + This returns the text of an element as unicode string. + + ``element`` + The element. + """ + if element is not None: + return unicode(element) + return u'' + + def _process_authors(self, foilpresenterfolie, song): + """ + Adds the authors specified in the XML to the song. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + authors = [] + try: + copyright = self._child(foilpresenterfolie.copyright.text_) + except AttributeError: + copyright = None + if copyright: + strings = [] + if copyright.find(u'Copyright') != -1: + temp = copyright.partition(u'Copyright') + copyright = temp[0] + elif copyright.find(u'copyright') != -1: + temp = copyright.partition(u'copyright') + copyright = temp[0] + elif copyright.find(u'©') != -1: + temp = copyright.partition(u'©') + copyright = temp[0] + elif copyright.find(u'(c)') != -1: + temp = copyright.partition(u'(c)') + copyright = temp[0] + elif copyright.find(u'(C)') != -1: + temp = copyright.partition(u'(C)') + copyright = temp[0] + elif copyright.find(u'c)') != -1: + temp = copyright.partition(u'c)') + copyright = temp[0] + elif copyright.find(u'C)') != -1: + temp = copyright.partition(u'C)') + copyright = temp[0] + elif copyright.find(u'C:') != -1: + temp = copyright.partition(u'C:') + copyright = temp[0] + elif copyright.find(u'C,)') != -1: + temp = copyright.partition(u'C,)') + copyright = temp[0] + copyright = re.compile(u'\\n').sub(u' ', copyright) + copyright = re.compile(u'\(.*\)').sub(u'', copyright) + if copyright.find(u'Rechte') != -1: + temp = copyright.partition(u'Rechte') + copyright = temp[0] + markers = [u'Text +u\.?n?d? +Melodie[\w\,\. ]*:', + u'Text +u\.?n?d? +Musik', u'T & M', u'Melodie und Satz', + u'Text[\w\,\. ]*:', u'Melodie', u'Musik', u'Satz', + u'Weise', u'[dD]eutsch', u'[dD]t[\.\:]', u'Englisch', + u'[oO]riginal', u'Bearbeitung', u'[R|r]efrain'] + for marker in markers: + copyright = re.compile(marker).sub(u'<marker>', copyright, re.U) + copyright = re.compile(u'(?<=<marker>) *:').sub(u'', copyright) + i = 0 + x = 0 + while i != 1: + if copyright.find(u'<marker>') != -1: + temp = copyright.partition(u'<marker>') + if temp[0].strip() and x > 0: + strings.append(temp[0]) + copyright = temp[2] + x += 1 + elif x > 0: + strings.append(copyright) + i = 1 + else: + i = 1 + author_temp = [] + for author in strings: + temp = re.split(u',(?=\D{2})|(?<=\D),|\/(?=\D{3,})|(?<=\D);', + author) + for tempx in temp: + author_temp.append(tempx) + for author in author_temp: + regex = u'^[\/,;\-\s\.]+|[\/,;\-\s\.]+$|'\ + '\s*[0-9]{4}\s*[\-\/]?\s*([0-9]{4})?[\/,;\-\s\.]*$' + author = re.compile(regex).sub(u'', author) + author = re.compile( + u'[0-9]{1,2}\.\s?J(ahr)?h\.|um\s*$|vor\s*$').sub(u'', + author) + author = re.compile(u'[N|n]ach.*$').sub(u'', author) + author = author.strip() + if re.search( + u'\w+\.?\s+\w{3,}\s+[a|u]nd\s|\w+\.?\s+\w{3,}\s+&\s', + author, re.U): + temp = re.split(u'\s[a|u]nd\s|\s&\s', author) + for tempx in temp: + tempx = tempx.strip() + authors.append(tempx) + elif len(author) > 2: + authors.append(author) + for display_name in authors: + author = self.manager.get_object_filtered(Author, + Author.display_name == display_name) + if author is None: + # We need to create a new author, as the author does not exist. + author = Author.populate(display_name=display_name, + last_name = display_name.split(u' ')[-1], + first_name = u' '.join(display_name.split(u' ')[:-1])) + self.manager.save_object(author) + song.authors.append(author) + if not song.authors: + add_author_unknown(self.manager, song) + + def _process_cclinumber(self, foilpresenterfolie, song): + """ + Adds the CCLI number to the song. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + song.ccli_number = self._child(foilpresenterfolie.ccliid) + except AttributeError: + song.ccli_number = u'' + + def _process_comments(self, foilpresenterfolie, song): + """ + Joins the comments specified in the XML and add it to the song. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + song.comments = self._child(foilpresenterfolie.notiz) + except AttributeError: + song.comments = u'' + + def _process_copyright(self, foilpresenterfolie, song): + """ + Adds the copyright to the song. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + song.copyright = self._child(foilpresenterfolie.copyright.text_) + except AttributeError: + song.copyright = u'' + + def _process_lyrics(self, foilpresenterfolie, song): + """ + Processes the verses and search_lyrics for the song. + + ``foilpresenterfolie`` + The foilpresenterfolie object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + sxml = SongXML() + search_text = u'' + temp_verse_order = {} + temp_verse_order_backup = [] + temp_sortnr_backup = 1 + temp_sortnr_liste = [] + versenumber = {u'V': 1, u'C': 1, u'B': 1, u'E': 1, u'O': 1, u'I': 1, + u'P': 1} + for strophe in foilpresenterfolie.strophen.strophe: + text = self._child(strophe.text_) + verse_name = self._child(strophe.key) + children = strophe.getchildren() + sortnr = False + for child in children: + if child.tag == u'sortnr': + verse_sortnr = self._child(strophe.sortnr) + sortnr = True + # In older Version there is no sortnr, but we need one + if sortnr == False: + verse_sortnr = unicode(temp_sortnr_backup) + temp_sortnr_backup += 1 + # Foilpresenter allows e. g. "Ref" or "1", but we need "C1" or "V1". + temp_sortnr_liste.append(verse_sortnr) + temp_verse_name = re.compile(u'[0-9].*').sub(u'', verse_name) + temp_verse_name = temp_verse_name[:3].lower() + if temp_verse_name == u'ref': + verse_type = u'C' + elif temp_verse_name == u'r': + verse_type = u'C' + elif temp_verse_name == u'': + verse_type = u'V' + elif temp_verse_name == u'v': + verse_type = u'V' + elif temp_verse_name == u'bri': + verse_type = u'B' + elif temp_verse_name == u'cod': + verse_type = u'E' + elif temp_verse_name == u'sch': + verse_type = u'E' + elif temp_verse_name == u'pre': + verse_type = u'P' + elif temp_verse_name == u'int': + verse_type = u'I' + else: + verse_type = u'O' + verse_number = re.compile(u'[a-zA-Z.+-_ ]*').sub(u'', verse_name) + #verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:]) + # Foilpresenter allows e. g. "C", but we need "C1". + if not verse_number: + verse_number = unicode(versenumber[verse_type]) + versenumber[verse_type] += 1 + else: + # test if foilpresenter have the same versenumber two times with + # different parts raise the verse number + for value in temp_verse_order_backup: + if value == (u''.join((verse_type, verse_number))): + verse_number = unicode(int(verse_number) + 1) + verse_type_index = VerseType.from_tag(verse_type[0]) + verse_type = VerseType.Names[verse_type_index] + temp_verse_order[verse_sortnr] = (u''.join((verse_type[0], + verse_number))) + temp_verse_order_backup.append(u''.join((verse_type[0], + verse_number))) + sxml.add_verse_to_lyrics(verse_type, verse_number, text) + search_text = search_text + text + song.search_lyrics = search_text.lower() + song.lyrics = unicode(sxml.extract_xml(), u'utf-8') + # Process verse order + verse_order = [] + verse_strophenr = [] + for strophennummer in foilpresenterfolie.reihenfolge.strophennummer: + verse_strophenr.append(strophennummer) + # Currently we do not support different "parts"! + if u'0' in temp_verse_order: + for vers in temp_verse_order_backup: + verse_order.append(vers) + else: + for number in verse_strophenr: + numberx = temp_sortnr_liste[int(number)] + verse_order.append(temp_verse_order[unicode(numberx)]) + song.verse_order = u' '.join(verse_order) + + def _process_songbooks(self, foilpresenterfolie, song): + """ + Adds the song book and song number specified in the XML to the song. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + song.song_book_id = 0 + song.song_number = u'' + try: + for bucheintrag in foilpresenterfolie.buch.bucheintrag: + bookname = self._child(bucheintrag.name) + if bookname: + book = self.manager.get_object_filtered(Book, + Book.name == bookname) + if book is None: + # We need to create a book, because it does not exist. + book = Book.populate(name=bookname, publisher=u'') + self.manager.save_object(book) + song.song_book_id = book.id + try: + if self._child(bucheintrag.nummer): + song.song_number = self._child(bucheintrag.nummer) + except AttributeError: + pass + # We only support one song book, so take the first one. + break + except AttributeError: + pass + + def _process_titles(self, foilpresenterfolie, song): + """ + Processes the titles specified in the song's XML. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + for titelstring in foilpresenterfolie.titel.titelstring: + if not song.title: + song.title = self._child(titelstring) + song.search_title = unicode(song.title) + song.alternate_title = u'' + else: + song.alternate_title = self._child(titelstring) + song.search_title += u'@' + song.alternate_title + song.search_title = re.sub(r'[\'"`,;:(){}?]+', u'', + unicode(song.search_title)).lower() + + def _process_topics(self, foilpresenterfolie, song): + """ + Adds the topics to the song. + + ``foilpresenterfolie`` + The property object (lxml.objectify.ObjectifiedElement). + + ``song`` + The song object. + """ + try: + for name in foilpresenterfolie.kategorien.name: + topictext = self._child(name) + if topictext: + topic = self.manager.get_object_filtered(Topic, + Topic.name == topictext) + if topic is None: + # We need to create a topic, because it does not exist. + topic = Topic.populate(name=topictext) + self.manager.save_object(topic) + song.topics.append(topic) + except AttributeError: + pass + + def _dump_xml(self, xml): + """ + Debugging aid to dump XML so that we can see what we have. + """ + return etree.tostring(xml, encoding=u'UTF-8', + xml_declaration=True, pretty_print=True) diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 6f566ff4f..773be2fd7 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -34,6 +34,8 @@ from wowimport import WowImport from cclifileimport import CCLIFileImport from ewimport import EasyWorshipSongImport from songbeamerimport import SongBeamerImport +from songshowplusimport import SongShowPlusImport +from foilpresenterimport import FoilPresenterImport # Imports that might fail try: from olp1import import OpenLP1SongImport @@ -67,10 +69,12 @@ class SongFormat(object): CCLI = 5 SongsOfFellowship = 6 Generic = 7 - #CSV = 8 EasiSlides = 8 EasyWorship = 9 SongBeamer = 10 + SongShowPlus = 11 + FoilPresenter = 12 + #CSV = 13 @staticmethod def get_class(format): @@ -102,6 +106,10 @@ class SongFormat(object): return EasyWorshipSongImport elif format == SongFormat.SongBeamer: return SongBeamerImport + elif format == SongFormat.SongShowPlus: + return SongShowPlusImport + elif format == SongFormat.FoilPresenter: + return FoilPresenterImport return None @staticmethod @@ -120,7 +128,9 @@ class SongFormat(object): SongFormat.Generic, SongFormat.EasiSlides, SongFormat.EasyWorship, - SongFormat.SongBeamer + SongFormat.SongBeamer, + SongFormat.SongShowPlus, + SongFormat.FoilPresenter ] @staticmethod diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 95337b29f..d29e18c1d 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -31,20 +31,27 @@ import re from PyQt4 import QtCore, QtGui from sqlalchemy.sql import or_ -from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \ - ItemCapabilities, translate, check_item_selected -from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ - SongImportForm -from openlp.plugins.songs.lib import OpenLyrics, SongXML -from openlp.plugins.songs.lib.db import Author, Song +from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \ + translate, check_item_selected, PluginStatus from openlp.core.lib.searchedit import SearchEdit +from openlp.core.lib.ui import UiStrings +from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ + SongImportForm, SongExportForm +from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType +from openlp.plugins.songs.lib.db import Author, Song +from openlp.plugins.songs.lib.ui import SongStrings log = logging.getLogger(__name__) -class SongListView(BaseListWithDnD): - def __init__(self, parent=None): - self.PluginName = u'Songs' - BaseListWithDnD.__init__(self, parent) +class SongSearch(object): + """ + An enumeration for song search methods. + """ + Entire = 1 + Titles = 2 + Lyrics = 3 + Authors = 4 + Themes = 5 class SongMediaItem(MediaManagerItem): @@ -55,7 +62,6 @@ class SongMediaItem(MediaManagerItem): def __init__(self, parent, plugin, icon): self.IconPath = u'songs/song' - self.ListViewWithDnD_class = SongListView MediaManagerItem.__init__(self, parent, self, icon) self.edit_song_form = EditSongForm(self, self.parent.manager) self.openLyrics = OpenLyrics(self.parent.manager) @@ -130,27 +136,23 @@ class SongMediaItem(MediaManagerItem): QtCore.QVariant(u'True')).toBool() def retranslateUi(self): - self.searchTextLabel.setText( - translate('SongsPlugin.MediaItem', 'Search:')) - self.searchTextButton.setText( - translate('SongsPlugin.MediaItem', 'Search')) - self.maintenanceAction.setText( - translate('SongsPlugin.MediaItem', 'Song Maintenance')) + self.searchTextLabel.setText(u'%s:' % UiStrings.Search) + self.searchTextButton.setText(UiStrings.Search) + self.maintenanceAction.setText(SongStrings.SongMaintenance) self.maintenanceAction.setToolTip(translate('SongsPlugin.MediaItem', 'Maintain the lists of authors, topics and books')) def initialise(self): self.searchTextEdit.setSearchTypes([ - (1, u':/songs/song_search_all.png', + (SongSearch.Entire, u':/songs/song_search_all.png', translate('SongsPlugin.MediaItem', 'Entire Song')), - (2, u':/songs/song_search_title.png', + (SongSearch.Titles, u':/songs/song_search_title.png', translate('SongsPlugin.MediaItem', 'Titles')), - (3, u':/songs/song_search_lyrics.png', + (SongSearch.Lyrics, u':/songs/song_search_lyrics.png', translate('SongsPlugin.MediaItem', 'Lyrics')), - (4, u':/songs/song_search_author.png', - translate('SongsPlugin.MediaItem', 'Authors')), - (5, u':/slides/slide_theme.png', - translate('SongsPlugin.MediaItem', 'Themes')) + (SongSearch.Authors, u':/songs/song_search_author.png', + SongStrings.Authors), + (SongSearch.Themes, u':/slides/slide_theme.png', UiStrings.Themes) ]) self.configUpdated() @@ -159,7 +161,7 @@ class SongMediaItem(MediaManagerItem): search_results = [] # search_type = self.searchTypeComboBox.currentIndex() search_type = self.searchTextEdit.currentSearchType() - if search_type == 1: + if search_type == SongSearch.Entire: log.debug(u'Entire Song Search') search_results = self.parent.manager.get_all_objects(Song, or_(Song.search_title.like(u'%' + self.whitespace.sub(u' ', @@ -167,25 +169,25 @@ class SongMediaItem(MediaManagerItem): Song.search_lyrics.like(u'%' + search_keywords.lower() + \ u'%')), Song.search_title.asc()) self.displayResultsSong(search_results) - if search_type == 2: + elif search_type == SongSearch.Titles: log.debug(u'Titles Search') search_results = self.parent.manager.get_all_objects(Song, Song.search_title.like(u'%' + self.whitespace.sub(u' ', search_keywords.lower()) + u'%'), Song.search_title.asc()) self.displayResultsSong(search_results) - elif search_type == 3: + elif search_type == SongSearch.Lyrics: log.debug(u'Lyrics Search') search_results = self.parent.manager.get_all_objects(Song, Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'), Song.search_lyrics.asc()) self.displayResultsSong(search_results) - elif search_type == 4: + elif search_type == SongSearch.Authors: log.debug(u'Authors Search') search_results = self.parent.manager.get_all_objects(Author, Author.display_name.like(u'%' + search_keywords + u'%'), Author.display_name.asc()) self.displayResultsAuthor(search_results) - elif search_type == 5: + elif search_type == SongSearch.Themes: log.debug(u'Theme Search') search_results = self.parent.manager.get_all_objects(Song, Song.theme_name == search_keywords, Song.search_lyrics.asc()) @@ -198,7 +200,7 @@ class SongMediaItem(MediaManagerItem): """ log.debug(u'onSongListLoad') # Called to redisplay the song list screen edit from a search - # or from the exit of the Song edit dialog. If remote editing is active + # or from the exit of the Song edit dialog. If remote editing is active # Trigger it and clean up so it will not update again. if self.remoteTriggered == u'L': self.onAddClick() @@ -217,13 +219,9 @@ class SongMediaItem(MediaManagerItem): self.listView.clear() searchresults.sort(cmp=self.collateSongTitles) for song in searchresults: - author_list = u'' - for author in song.authors: - if author_list != u'': - author_list = author_list + u', ' - author_list = author_list + author.display_name + author_list = [author.display_name for author in song.authors] song_title = unicode(song.title) - song_detail = u'%s (%s)' % (song_title, author_list) + song_detail = u'%s (%s)' % (song_title, u', '.join(author_list)) song_name = QtGui.QListWidgetItem(song_detail) song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id)) self.listView.addItem(song_name) @@ -253,9 +251,9 @@ class SongMediaItem(MediaManagerItem): """ if self.searchAsYouType: search_length = 1 - if self.searchTextEdit.currentSearchType() == 1: + if self.searchTextEdit.currentSearchType() == SongSearch.Entire: search_length = 3 - elif self.searchTextEdit.currentSearchType() == 3: + elif self.searchTextEdit.currentSearchType() == SongSearch.Lyrics: search_length = 7 if len(text) > search_length: self.onSearchTextButtonClick() @@ -266,6 +264,11 @@ class SongMediaItem(MediaManagerItem): if self.import_wizard.exec_() == QtGui.QDialog.Accepted: Receiver.send_message(u'songs_load_list') + def onExportClick(self): + if not hasattr(self, u'export_wizard'): + self.export_wizard = SongExportForm(self, self.parent) + self.export_wizard.exec_() + def onNewClick(self): log.debug(u'onNewClick') self.edit_song_form.newSong() @@ -299,9 +302,7 @@ class SongMediaItem(MediaManagerItem): Edit a song """ log.debug(u'onEditClick') - if check_item_selected(self.listView, - translate('SongsPlugin.MediaItem', - 'You must select an item to edit.')): + if check_item_selected(self.listView, UiStrings.SelectEdit): self.editItem = self.listView.currentItem() item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0] self.edit_song_form.loadSong(item_id, False) @@ -311,9 +312,7 @@ class SongMediaItem(MediaManagerItem): """ Remove a song from the list and database """ - if check_item_selected(self.listView, - translate('SongsPlugin.MediaItem', - 'You must select an item to delete.')): + if check_item_selected(self.listView, UiStrings.SelectDelete): items = self.listView.selectedIndexes() if QtGui.QMessageBox.question(self, translate('SongsPlugin.MediaItem', 'Delete Song(s)?'), @@ -332,9 +331,6 @@ class SongMediaItem(MediaManagerItem): def generateSlideData(self, service_item, item=None, xmlVersion=False): log.debug(u'generateSlideData (%s:%s)' % (service_item, item)) raw_footer = [] - author_list = u'' - author_audit = [] - ccli = u'' item_id = self._getIdOfItemToGenerate(item, self.remoteSong) service_item.add_capability(ItemCapabilities.AllowsEdit) service_item.add_capability(ItemCapabilities.AllowsPreview) @@ -347,47 +343,70 @@ class SongMediaItem(MediaManagerItem): if song.lyrics.startswith(u'<?xml version='): verseList = SongXML().get_verses(song.lyrics) # no verse list or only 1 space (in error) - if not song.verse_order or not song.verse_order.strip(): + verse_tags_translated = False + if VerseType.from_translated_string(unicode( + verseList[0][0][u'type'])) is not None: + verse_tags_translated = True + if not song.verse_order.strip(): for verse in verseList: - verseTag = u'%s:%s' % ( - verse[0][u'type'], verse[0][u'label']) + # We cannot use from_loose_input() here, because database + # is supposed to contain English lowercase singlechar tags. + verse_tag = verse[0][u'type'] + verse_index = None + if len(verse_tag) > 1: + verse_index = \ + VerseType.from_translated_string(verse_tag) + if verse_index is None: + verse_index = VerseType.from_string(verse_tag) + if verse_index is None: + verse_index = VerseType.from_tag(verse_tag) + verse_tag = VerseType.TranslatedTags[verse_index].upper() + verse_def = u'%s%s' % (verse_tag, verse[0][u'label']) service_item.add_from_text( - verse[1][:30], unicode(verse[1]), verseTag) + verse[1][:30], unicode(verse[1]), verse_def) else: # Loop through the verse list and expand the song accordingly. - for order in song.verse_order.upper().split(): + for order in song.verse_order.lower().split(): if len(order) == 0: break for verse in verseList: - if verse[0][u'type'][0] == order[0] and \ - (verse[0][u'label'] == order[1:] or not order[1:]): - verseTag = u'%s:%s' % \ - (verse[0][u'type'], verse[0][u'label']) + if verse[0][u'type'][0].lower() == order[0] and \ + (verse[0][u'label'].lower() == order[1:] or \ + not order[1:]): + if verse_tags_translated: + verse_index = VerseType.from_translated_tag( + verse[0][u'type']) + else: + verse_index = VerseType.from_tag( + verse[0][u'type']) + if verse_index is None: + verse_index = VerseType.Other + verse_tag = VerseType.TranslatedTags[verse_index] + verse_def = u'%s%s' % (verse_tag, + verse[0][u'label']) service_item.add_from_text( - verse[1][:30], verse[1], verseTag) + verse[1][:30], verse[1], verse_def) else: verses = song.lyrics.split(u'\n\n') for slide in verses: service_item.add_from_text(slide[:30], unicode(slide)) service_item.title = song.title - for author in song.authors: - if len(author_list) > 1: - author_list = author_list + u', ' - author_list = author_list + unicode(author.display_name) - author_audit.append(unicode(author.display_name)) + author_list = [unicode(author.display_name) for author in song.authors] raw_footer.append(song.title) - raw_footer.append(author_list) + raw_footer.append(u', '.join(author_list)) raw_footer.append(song.copyright) - raw_footer.append(unicode( - translate('SongsPlugin.MediaItem', 'CCLI License: ') + - QtCore.QSettings().value(u'general/ccli number', - QtCore.QVariant(u'')).toString())) + if QtCore.QSettings().value(u'general/ccli number', + QtCore.QVariant(u'')).toString(): + raw_footer.append(unicode( + translate('SongsPlugin.MediaItem', 'CCLI License: ') + + QtCore.QSettings().value(u'general/ccli number', + QtCore.QVariant(u'')).toString())) service_item.raw_footer = raw_footer service_item.audit = [ - song.title, author_audit, song.copyright, unicode(song.ccli_number) + song.title, author_list, song.copyright, unicode(song.ccli_number) ] service_item.data_string = {u'title': song.search_title, - u'authors': author_list} + u'authors': u', '.join(author_list)} service_item.xml_version = self.openLyrics.song_to_xml(song) return True @@ -396,46 +415,46 @@ class SongMediaItem(MediaManagerItem): Triggered by a song being loaded by the service item """ log.debug(u'serviceLoad') - if item.data_string: - search_results = self.parent.manager.get_all_objects(Song, - Song.search_title == re.compile(r'\W+', re.UNICODE).sub(u' ', - item.data_string[u'title'].split(u'@')[0].lower()).strip(), - Song.search_title.asc()) - author_list = item.data_string[u'authors'].split(u', ') - # The service item always has an author (at least it has u'' as - # author). However, songs saved in the database do not have to have - # an author. - if u'' in author_list: - author_list.remove(u'') - editId = 0 - add_song = True - if search_results: - for song in search_results: - same_authors = True - # If the author counts are different, we do not have to do - # any further checking. This is also important when a song - # does not have any author (because we can not loop over an - # empty list). - if len(song.authors) == len(author_list): - for author in song.authors: - if author.display_name not in author_list: - same_authors = False - else: - same_authors = False - # All authors are the same, so we can stop here and the song - # does not have to be saved. - if same_authors: - add_song = False - editId = song.id - break - if add_song: - if self.addSongFromService: - editId = self.openLyrics.xml_to_song(item.xml_version) - self.onSearchTextButtonClick() - # Update service with correct song id. - if editId: - Receiver.send_message(u'service_item_update', - u'%s:%s' % (editId, item._uuid)) + if self.plugin.status != PluginStatus.Active or not item.data_string: + return + search_results = self.parent.manager.get_all_objects(Song, + Song.search_title == re.compile(r'\W+', re.UNICODE).sub(u' ', + item.data_string[u'title'].split(u'@')[0].lower()).strip(), + Song.search_title.asc()) + author_list = item.data_string[u'authors'].split(u', ') + # The service item always has an author (at least it has u'' as + # author). However, songs saved in the database do not have to have + # an author. + if u'' in author_list: + author_list.remove(u'') + editId = 0 + add_song = True + if search_results: + for song in search_results: + same_authors = True + # If the author counts are different, we do not have to do any + # further checking. This is also important when a song does not + # have any author (because we can not loop over an empty list). + if len(song.authors) == len(author_list): + for author in song.authors: + if author.display_name not in author_list: + same_authors = False + else: + same_authors = False + # All authors are the same, so we can stop here and the song + # does not have to be saved. + if same_authors: + add_song = False + editId = song.id + break + if add_song: + if self.addSongFromService: + editId = self.openLyrics.xml_to_song(item.xml_version) + self.onSearchTextButtonClick() + # Update service with correct song id. + if editId: + Receiver.send_message(u'service_item_update', + u'%s:%s' % (editId, item._uuid)) def collateSongTitles(self, song_1, song_2): """ diff --git a/openlp/plugins/songs/lib/olp1import.py b/openlp/plugins/songs/lib/olp1import.py index c3e1ca6b4..989b7df8a 100644 --- a/openlp/plugins/songs/lib/olp1import.py +++ b/openlp/plugins/songs/lib/olp1import.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -32,7 +32,7 @@ import logging from chardet.universaldetector import UniversalDetector import sqlite -from openlp.core.lib import translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib import retrieve_windows_encoding from songimport import SongImport @@ -55,8 +55,7 @@ class OpenLP1SongImport(SongImport): ``filename`` The database providing the data to import. """ - SongImport.__init__(self, manager) - self.import_source = kwargs[u'filename'] + SongImport.__init__(self, manager, **kwargs) def do_import(self): """ @@ -103,8 +102,7 @@ class OpenLP1SongImport(SongImport): lyrics = song[2].replace(u'\r\n', u'\n') copyright = song[3] self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - 'Importing "%s"...')) % title) + WizardStrings.ImportingType % title) self.title = title verses = lyrics.split(u'\n\n') for verse in verses: diff --git a/openlp/plugins/songs/lib/olpimport.py b/openlp/plugins/songs/lib/olpimport.py index d2a00447f..fe010b501 100644 --- a/openlp/plugins/songs/lib/olpimport.py +++ b/openlp/plugins/songs/lib/olpimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -36,6 +36,7 @@ from sqlalchemy.orm.exc import UnmappedClassError from openlp.core.lib import translate from openlp.core.lib.db import BaseModel +from openlp.plugins.songs.lib import add_author_unknown from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile from songimport import SongImport @@ -47,30 +48,35 @@ class OldAuthor(BaseModel): """ pass + class OldBook(BaseModel): """ Book model """ pass + class OldMediaFile(BaseModel): """ MediaFile model """ pass + class OldSong(BaseModel): """ Song model """ pass + class OldTopic(BaseModel): """ Topic model """ pass + class OpenLPSongImport(SongImport): """ The :class:`OpenLPSongImport` class provides OpenLP with the ability to @@ -86,9 +92,8 @@ class OpenLPSongImport(SongImport): ``source_db`` The database providing the data to import. """ - SongImport.__init__(self, manager) - self.import_source = u'sqlite:///%s' % kwargs[u'filename'] - log.debug(self.import_source) + SongImport.__init__(self, manager, **kwargs) + self.import_source = u'sqlite:///%s' % self.import_source self.source_session = None def do_import(self): @@ -171,25 +176,18 @@ class OpenLPSongImport(SongImport): new_song.comments = song.comments new_song.theme_name = song.theme_name new_song.ccli_number = song.ccli_number - if song.authors: - for author in song.authors: - existing_author = self.manager.get_object_filtered( - Author, Author.display_name == author.display_name) - if existing_author: - new_song.authors.append(existing_author) - else: - new_song.authors.append(Author.populate( - first_name=author.first_name, - last_name=author.last_name, - display_name=author.display_name)) - else: - au = self.manager.get_object_filtered(Author, - Author.display_name == u'Author Unknown') - if au: - new_song.authors.append(au) + for author in song.authors: + existing_author = self.manager.get_object_filtered( + Author, Author.display_name == author.display_name) + if existing_author: + new_song.authors.append(existing_author) else: new_song.authors.append(Author.populate( - display_name=u'Author Unknown')) + first_name=author.first_name, + last_name=author.last_name, + display_name=author.display_name)) + if not new_song.authors: + add_author_unknown(self.manager, new_song) if song.book: existing_song_book = self.manager.get_object_filtered( Book, Book.name == song.book.name) diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 32315130a..22e36b716 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -28,7 +28,6 @@ import os from PyQt4 import QtCore -from openlp.core.lib import Receiver from openlp.core.utils import get_uno_command, get_uno_instance from songimport import SongImport @@ -51,25 +50,20 @@ class OooImport(SongImport): """ Import songs from Impress/Powerpoint docs using Impress """ - def __init__(self, master_manager, **kwargs): + def __init__(self, manager, **kwargs): """ Initialise the class. Requires a songmanager class which is passed to SongImport for writing song to disk """ - SongImport.__init__(self, master_manager) - self.song = None - self.master_manager = master_manager + SongImport.__init__(self, manager, **kwargs) self.document = None self.process_started = False - self.filenames = kwargs[u'filenames'] - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): self.stop_import_flag = False self.import_wizard.progressBar.setMaximum(0) self.start_ooo() - for filename in self.filenames: + for filename in self.import_source: if self.stop_import_flag: self.import_wizard.incrementProgressBar(u'Import cancelled', 0) return diff --git a/openlp/plugins/songs/lib/openlyricsexport.py b/openlp/plugins/songs/lib/openlyricsexport.py new file mode 100644 index 000000000..c2b58980b --- /dev/null +++ b/openlp/plugins/songs/lib/openlyricsexport.py @@ -0,0 +1,74 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`openlyricsexport` module provides the functionality for exporting +songs from the database to the OpenLyrics format. +""" +import logging +import os + +from lxml import etree + +from openlp.core.lib import Receiver, translate +from openlp.plugins.songs.lib import OpenLyrics + +log = logging.getLogger(__name__) + +class OpenLyricsExport(object): + """ + This provides the Openlyrics export. + """ + def __init__(self, parent, songs, save_path): + """ + Initialise the export. + """ + log.debug(u'initialise OpenLyricsExport') + self.parent = parent + self.manager = parent.plugin.manager + self.songs = songs + self.save_path = save_path + if not os.path.exists(self.save_path): + os.mkdir(self.save_path) + + def do_export(self): + """ + Export the songs. + """ + log.debug(u'started OpenLyricsExport') + openLyrics = OpenLyrics(self.manager) + self.parent.progressBar.setMaximum(len(self.songs)) + for song in self.songs: + Receiver.send_message(u'openlp_process_events') + if self.parent.stop_export_flag: + return False + self.parent.incrementProgressBar(unicode(translate( + 'SongsPlugin.OpenLyricsExport', 'Exporting "%s"...')) % + song.title) + xml = openLyrics.song_to_xml(song) + tree = etree.ElementTree(etree.fromstring(xml)) + tree.write(os.path.join(self.save_path, song.title + u'.xml'), + encoding=u'utf-8', xml_declaration=True, pretty_print=True) + return True diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index 37407c75c..31b2bc959 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -5,10 +5,10 @@ # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,7 +33,7 @@ import os from lxml import etree -from openlp.core.lib import translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport from openlp.plugins.songs.lib import OpenLyrics @@ -43,18 +43,13 @@ class OpenLyricsImport(SongImport): """ This provides the Openlyrics import. """ - def __init__(self, master_manager, **kwargs): + def __init__(self, manager, **kwargs): """ - Initialise the import. + Initialise the Open Lyrics importer. """ log.debug(u'initialise OpenLyricsImport') - SongImport.__init__(self, master_manager) - self.master_manager = master_manager - self.openLyrics = OpenLyrics(master_manager) - if kwargs.has_key(u'filename'): - self.import_source = kwargs[u'filename'] - if kwargs.has_key(u'filenames'): - self.import_source = kwargs[u'filenames'] + SongImport.__init__(self, manager, **kwargs) + self.openLyrics = OpenLyrics(self.manager) def do_import(self): """ @@ -65,9 +60,8 @@ class OpenLyricsImport(SongImport): for file_path in self.import_source: if self.stop_import_flag: return False - self.import_wizard.incrementProgressBar(unicode(translate( - 'SongsPlugin.OpenLyricsImport', 'Importing %s...')) % - os.path.basename(file_path)) + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % os.path.basename(file_path)) try: parsed_file = etree.parse(file_path, parser) xml = unicode(etree.tostring(parsed_file)) diff --git a/openlp/plugins/songs/lib/opensongimport.py b/openlp/plugins/songs/lib/opensongimport.py index eb16f4ba4..4da1234a5 100644 --- a/openlp/plugins/songs/lib/opensongimport.py +++ b/openlp/plugins/songs/lib/opensongimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -31,14 +31,11 @@ from lxml import objectify from lxml.etree import Error, LxmlError import re -from openlp.core.lib import translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) -class OpenSongImportError(Exception): - pass - class OpenSongImport(SongImport): """ Import songs exported from OpenSong @@ -107,21 +104,19 @@ class OpenSongImport(SongImport): """ Initialise the class. """ - SongImport.__init__(self, manager) - self.filenames = kwargs[u'filenames'] - self.song = None + SongImport.__init__(self, manager, **kwargs) self.commit = True def do_import(self): """ - Import either each of the files in self.filenames - 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 multiple opensong files. If `self.commit` is set False, the import will not be committed to the database (useful for test scripts). """ success = True numfiles = 0 - for filename in self.filenames: + for filename in self.import_source: ext = os.path.splitext(filename)[1] if ext.lower() == u'.zip': z = ZipFile(filename, u'r') @@ -130,7 +125,7 @@ class OpenSongImport(SongImport): numfiles += 1 log.debug(u'Total number of files: %d', numfiles) self.import_wizard.progressBar.setMaximum(numfiles) - for filename in self.filenames: + for filename in self.import_source: if self.stop_import_flag: success = False break @@ -148,26 +143,26 @@ class OpenSongImport(SongImport): continue log.info(u'Zip importing %s', parts[-1]) self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - 'Importing %s...')) % parts[-1]) + WizardStrings.ImportingType % parts[-1]) songfile = z.open(song) - self.do_import_file(songfile) - if self.commit: + if self.do_import_file(songfile) and self.commit and \ + not self.stop_import_flag: self.finish() - if self.stop_import_flag: - success = False - break + else: + success = False + break else: # not a zipfile log.info(u'Direct import %s', filename) self.import_wizard.incrementProgressBar( - unicode(translate('SongsPlugin.ImportWizardForm', - 'Importing %s...')) % os.path.split(filename)[-1]) - file = open(filename) - self.do_import_file(file) - if self.commit: + WizardStrings.ImportingType % os.path.split(filename)[-1]) + song_file = open(filename) + if self.do_import_file(song_file) and self.commit and \ + not self.stop_import_flag: self.finish() - + else: + success = False + break return success def do_import_file(self, file): @@ -180,7 +175,7 @@ class OpenSongImport(SongImport): tree = objectify.parse(file) except (Error, LxmlError): log.exception(u'Error parsing XML') - return + return False root = tree.getroot() fields = dir(root) decode = { @@ -198,112 +193,103 @@ class OpenSongImport(SongImport): setattr(self, fn_or_string, ustring) else: 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: self.topics.append(unicode(root.theme)) if u'alttheme' in fields and unicode(root.alttheme) not in self.topics: self.topics.append(unicode(root.alttheme)) # data storage while importing verses = {} - # keep track of a "default" verse order, in case none is specified + # keep track of verses appearance order our_verse_order = [] - verses_seen = {} - # in the absence of any other indication, verses are the default, - # erm, versetype! - versetype = u'V' - versenum = None + # default verse + verse_tag = u'v' + verse_num = u'1' + # for the case where song has several sections with same marker + inst = 1 lyrics = unicode(root.lyrics) - for thisline in lyrics.split(u'\n'): + for this_line in lyrics.split(u'\n'): # remove comments - semicolon = thisline.find(u';') + semicolon = this_line.find(u';') if semicolon >= 0: - thisline = thisline[:semicolon] - thisline = thisline.strip() - if len(thisline) == 0: + this_line = this_line[:semicolon] + this_line = this_line.strip() + if not len(this_line): continue - # skip inthisline guitar chords and page and column breaks - if thisline[0] == u'.' or thisline.startswith(u'---') \ - or thisline.startswith(u'-!!'): + # skip guitar chords and page and column breaks + if this_line.startswith(u'.') or this_line.startswith(u'---') \ + or this_line.startswith(u'-!!'): continue # verse/chorus/etc. marker - if thisline[0] == u'[': + if this_line.startswith(u'['): # drop the square brackets - right_bracket = thisline.find(u']') - content = thisline[1:right_bracket].upper() + right_bracket = this_line.find(u']') + content = this_line[1:right_bracket].lower() # have we got any digits? - # If so, versenumber 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) match = re.match(u'(.*)(\d+.*)', content) if match is not None: - versetype = match.group(1) - versenum = match.group(2) + verse_tag = match.group(1) + verse_num = match.group(2) else: # otherwise we assume number 1 and take the whole prefix as - # the versetype - versetype = content - versenum = u'1' + # the verse tag + verse_tag = content + verse_num = u'1' + inst = 1 + if [verse_tag, verse_num, inst] in our_verse_order \ + and verses.has_key(verse_tag) \ + and verses[verse_tag].has_key(verse_num): + inst = len(verses[verse_tag][verse_num])+1 + our_verse_order.append([verse_tag, verse_num, inst]) continue - words = None # number at start of line.. it's verse number - if thisline[0].isdigit(): - versenum = thisline[0] - words = thisline[1:].strip() - if words is None: - words = thisline - if not versenum: - versenum = u'1' - if versenum is not None: - versetag = u'%s%s' % (versetype, versenum) - if not verses.has_key(versetype): - verses[versetype] = {} - if not verses[versetype].has_key(versenum): - # storage for lines in this verse - verses[versetype][versenum] = [] - if not verses_seen.has_key(versetag): - verses_seen[versetag] = 1 - our_verse_order.append(versetag) - if words: - # Tidy text and remove the ____s from extended words - words = self.tidy_text(words) - words = words.replace('_', '') - verses[versetype][versenum].append(words) + if this_line[0].isdigit(): + verse_num = this_line[0] + this_line = this_line[1:].strip() + our_verse_order.append([verse_tag, verse_num, inst]) + if not verses.has_key(verse_tag): + verses[verse_tag] = {} + if not verses[verse_tag].has_key(verse_num): + verses[verse_tag][verse_num] = {} + if not verses[verse_tag][verse_num].has_key(inst): + verses[verse_tag][verse_num][inst] = [] + # Tidy text and remove the ____s from extended words + this_line = self.tidy_text(this_line) + this_line = this_line.replace(u'_', u'') + this_line = this_line.replace(u'|', u'\n') + verses[verse_tag][verse_num][inst].append(this_line) # done parsing - versetypes = verses.keys() - versetypes.sort() - versetags = {} - for versetype in versetypes: - our_verse_type = versetype - if our_verse_type == u'': - our_verse_type = u'V' - versenums = verses[versetype].keys() - versenums.sort() - for num in versenums: - versetag = u'%s%s' % (our_verse_type, num) - lines = u'\n'.join(verses[versetype][num]) - self.verses.append([versetag, lines]) - # Keep track of what we have for error checking later - versetags[versetag] = 1 - # now figure out the presentation order - order = [] + # add verses in original order + for (verse_tag, verse_num, inst) in our_verse_order: + verse_def = u'%s%s' % (verse_tag, verse_num) + lines = u'\n'.join(verses[verse_tag][verse_num][inst]) + self.add_verse(lines, verse_def) + # figure out the presentation order, if present if u'presentation' in fields and root.presentation != u'': order = unicode(root.presentation) - # We make all the tags in the lyrics upper 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 - order = order.upper().split() - else: - if len(our_verse_order) > 0: - order = our_verse_order - else: - log.warn(u'No verse order available for %s, skipping.', - self.title) - for tag in order: - if tag[0].isdigit(): - # Assume it's a verse if it has no prefix - tag = u'V' + tag - elif not re.search('\d+', tag): - # Assume it's no.1 if there's no digits - tag = tag + u'1' - if not versetags.has_key(tag): - log.info(u'Got order %s but not in versetags, dropping this' - u'item from presentation order', tag) - else: - self.verse_order_list.append(tag) + order = order.lower().split() + for verse_def in order: + match = re.match(u'(.*)(\d+.*)', verse_def) + if match is not None: + verse_tag = match.group(1) + verse_num = match.group(2) + if not len(verse_tag): + verse_tag = u'v' + else: + # Assume it's no.1 if there are no digits + verse_tag = verse_def + verse_num = u'1' + verse_def = u'%s%s' % (verse_tag, verse_num) + if verses.has_key(verse_tag) \ + and verses[verse_tag].has_key(verse_num): + self.verse_order_list.append(verse_def) + else: + log.info(u'Got order %s but not in verse tags, dropping' + u'this item from presentation order', verse_def) + return True diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index cfb80caa3..711761114 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -66,12 +66,12 @@ class SofImport(OooImport): It attempts to detect italiced verses, and treats these as choruses in the verse ordering. Again not perfect, but a start. """ - def __init__(self, master_manager, **kwargs): + def __init__(self, manager, **kwargs): """ Initialise the class. Requires a songmanager class which is passed to SongImport for writing song to disk """ - OooImport.__init__(self, master_manager, **kwargs) + OooImport.__init__(self, manager, **kwargs) def process_ooo_document(self): """ diff --git a/openlp/plugins/songs/lib/songbeamerimport.py b/openlp/plugins/songs/lib/songbeamerimport.py index 47290bfbd..c7fc3d3cf 100644 --- a/openlp/plugins/songs/lib/songbeamerimport.py +++ b/openlp/plugins/songs/lib/songbeamerimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -33,7 +33,7 @@ import logging import os import re -from openlp.core.lib import translate +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport log = logging.getLogger(__name__) @@ -67,19 +67,11 @@ class SongBeamerImport(SongImport): Song Beamer file format is text based in the beginning are one or more control tags written """ - def __init__(self, master_manager, **kwargs): + def __init__(self, manager, **kwargs): """ - Initialise the import. - - ``master_manager`` - The song manager for the running OpenLP installation. + Initialise the Song Beamer importer. """ - SongImport.__init__(self, master_manager) - if kwargs.has_key(u'filename'): - self.import_source = kwargs[u'filename'] - if kwargs.has_key(u'filenames'): - self.import_source = kwargs[u'filenames'] - log.debug(self.import_source) + SongImport.__init__(self, manager, **kwargs) def do_import(self): """ @@ -96,7 +88,7 @@ class SongBeamerImport(SongImport): read_verses = False file_name = os.path.split(file)[1] self.import_wizard.incrementProgressBar( - u'Importing %s' % (file_name), 0) + WizardStrings.ImportingType % file_name, 0) if os.path.isfile(file): detect_file = open(file, u'r') details = chardet.detect(detect_file.read(2048)) @@ -134,9 +126,8 @@ class SongBeamerImport(SongImport): self.add_verse(self.current_verse, self.current_verse_type) if self.check_complete(): self.finish() - self.import_wizard.incrementProgressBar(unicode(translate( - 'SongsPlugin.SongBeamerImport', 'Importing %s...')) % - file_name) + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name) return True def replace_html_tags(self): @@ -251,6 +242,8 @@ class SongBeamerImport(SongImport): self.song_number = u'' elif tag_val[0] == u'#Speed': pass + elif tag_val[0] == u'Tempo': + pass elif tag_val[0] == u'#TextAlign': pass elif tag_val[0] == u'#Title': diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 592aa7ac1..5bfba9b77 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -29,8 +29,9 @@ import re from PyQt4 import QtCore from openlp.core.lib import Receiver, translate -from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib import add_author_unknown, VerseType 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.xml import SongXML log = logging.getLogger(__name__) @@ -43,15 +44,25 @@ class SongImport(QtCore.QObject): whether the authors etc already exist and add them or refer to them as necessary """ - def __init__(self, manager): + def __init__(self, manager, **kwargs): """ Initialise and create defaults for properties ``manager`` An instance of a SongManager, through which all database access is performed. + """ self.manager = manager + QtCore.QObject.__init__(self) + if kwargs.has_key(u'filename'): + self.import_source = kwargs[u'filename'] + elif kwargs.has_key(u'filenames'): + self.import_source = kwargs[u'filenames'] + else: + raise KeyError(u'Keyword arguments "filename[s]" not supplied.') + log.debug(self.import_source) + self.song = None self.stop_import_flag = False self.set_defaults() QtCore.QObject.connect(Receiver.get_receiver(), @@ -74,13 +85,13 @@ class SongImport(QtCore.QObject): self.media_files = [] self.song_book_name = u'' self.song_book_pub = u'' + self.verse_order_list_generated_useful = False + self.verse_order_list_generated = [] self.verse_order_list = [] self.verses = [] - self.versecounts = {} + self.verse_counts = {} self.copyright_string = unicode(translate( 'SongsPlugin.SongImport', 'copyright')) - self.copyright_symbol = unicode(translate( - 'SongsPlugin.SongImport', '\xa9')) def stop_import(self): """ @@ -127,20 +138,20 @@ class SongImport(QtCore.QObject): return text def process_song_text(self, text): - versetexts = text.split(u'\n\n') - for versetext in versetexts: - if versetext.strip() != u'': - self.process_verse_text(versetext.strip()) + verse_texts = text.split(u'\n\n') + for verse_text in verse_texts: + if verse_text.strip() != u'': + self.process_verse_text(verse_text.strip()) def process_verse_text(self, text): lines = text.split(u'\n') if text.lower().find(self.copyright_string) >= 0 \ - or text.lower().find(self.copyright_symbol) >= 0: + or text.find(SongStrings.CopyrightSymbol) >= 0: copyright_found = False for line in lines: if (copyright_found or line.lower().find(self.copyright_string) >= 0 or - line.lower().find(self.copyright_symbol) >= 0): + line.find(SongStrings.CopyrightSymbol) >= 0): copyright_found = True self.add_copyright(line) else: @@ -197,44 +208,46 @@ class SongImport(QtCore.QObject): return self.media_files.append(filename) - def add_verse(self, versetext, versetag=u'V', lang=None): + def add_verse(self, verse_text, verse_def=u'v', lang=None): """ - Add a verse. This is the whole verse, lines split by \n. It will also + Add a verse. This is the whole verse, lines split by \\n. It will also attempt to detect duplicates. In this case it will just add to the verse order. - ``versetext`` + ``verse_text`` The text of the verse. - ``versetag`` - The verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the + ``verse_def`` + The verse tag can be v1/c1/b etc, or 'v' and 'c' (will count the verses/choruses itself) or None, where it will assume verse. ``lang`` The language code (ISO-639) of the verse, for example *en* or *de*. + """ - for (oldversetag, oldverse, oldlang) in self.verses: - if oldverse.strip() == versetext.strip(): - self.verse_order_list.append(oldversetag) + for (old_verse_def, old_verse, old_lang) in self.verses: + if old_verse.strip() == verse_text.strip(): + self.verse_order_list_generated.append(old_verse_def) + self.verse_order_list_generated_useful = True return - if versetag[0] in self.versecounts: - self.versecounts[versetag[0]] += 1 + if verse_def[0] in self.verse_counts: + self.verse_counts[verse_def[0]] += 1 else: - self.versecounts[versetag[0]] = 1 - if len(versetag) == 1: - versetag += unicode(self.versecounts[versetag[0]]) - elif int(versetag[1:]) > self.versecounts[versetag[0]]: - self.versecounts[versetag[0]] = int(versetag[1:]) - self.verses.append([versetag, versetext.rstrip(), lang]) - self.verse_order_list.append(versetag) - if versetag.startswith(u'V') and u'C1' in self.verse_order_list: - self.verse_order_list.append(u'C1') + self.verse_counts[verse_def[0]] = 1 + if len(verse_def) == 1: + verse_def += unicode(self.verse_counts[verse_def[0]]) + elif int(verse_def[1:]) > self.verse_counts[verse_def[0]]: + self.verse_counts[verse_def[0]] = int(verse_def[1:]) + self.verses.append([verse_def, verse_text.rstrip(), lang]) + self.verse_order_list_generated.append(verse_def) def repeat_verse(self): """ Repeat the previous verse in the verse order """ - self.verse_order_list.append(self.verse_order_list[-1]) + self.verse_order_list_generated.append( + self.verse_order_list_generated[-1]) + self.verse_order_list_generated_useful = True def check_complete(self): """ @@ -257,10 +270,7 @@ class SongImport(QtCore.QObject): """ All fields have been set to this song. Write the song to disk. """ - if not self.authors: - self.authors.append(unicode(translate('SongsPlugin.SongImport', - 'Author unknown'))) - log.info(u'commiting song %s to database', self.title) + log.info(u'committing song %s to database', self.title) song = Song() song.title = self.title song.alternate_title = self.alternate_title @@ -271,34 +281,29 @@ class SongImport(QtCore.QObject): verses_changed_to_other = {} sxml = SongXML() other_count = 1 - for (versetag, versetext, lang) in self.verses: - if versetag[0] == u'C': - versetype = VerseType.to_string(VerseType.Chorus) - elif versetag[0] == u'V': - versetype = VerseType.to_string(VerseType.Verse) - elif versetag[0] == u'B': - versetype = VerseType.to_string(VerseType.Bridge) - elif versetag[0] == u'I': - versetype = VerseType.to_string(VerseType.Intro) - elif versetag[0] == u'P': - versetype = VerseType.to_string(VerseType.PreChorus) - elif versetag[0] == u'E': - versetype = VerseType.to_string(VerseType.Ending) + for (verse_def, verse_text, lang) in self.verses: + if verse_def[0].lower() in VerseType.Tags: + verse_tag = verse_def[0].lower() else: - newversetag = u'O%d' % other_count - verses_changed_to_other[versetag] = newversetag + new_verse_def = u'%s%d' % (VerseType.Tags[VerseType.Other], + other_count) + verses_changed_to_other[verse_def] = new_verse_def other_count += 1 - versetype = VerseType.to_string(VerseType.Other) - log.info(u'Versetype %s changing to %s' , versetag, newversetag) - versetag = newversetag - sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext, lang) - song.search_lyrics += u' ' + self.remove_punctuation(versetext) + verse_tag = VerseType.Tags[VerseType.Other] + log.info(u'Versetype %s changing to %s' , verse_def, + new_verse_def) + verse_def = new_verse_def + sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text, lang) + song.search_lyrics += u' ' + self.remove_punctuation(verse_text) song.search_lyrics = song.search_lyrics.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') - for i, current_verse_tag in enumerate(self.verse_order_list): - if verses_changed_to_other.has_key(current_verse_tag): + if not len(self.verse_order_list) and \ + self.verse_order_list_generated_useful: + self.verse_order_list = self.verse_order_list_generated + for i, current_verse_def in enumerate(self.verse_order_list): + if verses_changed_to_other.has_key(current_verse_def): self.verse_order_list[i] = \ - verses_changed_to_other[current_verse_tag] + verses_changed_to_other[current_verse_def] song.verse_order = u' '.join(self.verse_order_list) song.copyright = self.copyright song.comments = self.comments @@ -308,10 +313,13 @@ class SongImport(QtCore.QObject): author = self.manager.get_object_filtered(Author, Author.display_name == authortext) if not author: - author = Author.populate(display_name = authortext, + author = Author.populate(display_name=authortext, last_name=authortext.split(u' ')[-1], first_name=u' '.join(authortext.split(u' ')[:-1])) song.authors.append(author) + # No author, add the default author. + if not song.authors: + add_author_unknown(self.manager, song) for filename in self.media_files: media_file = self.manager.get_object_filtered(MediaFile, MediaFile.file_name == filename) @@ -339,13 +347,14 @@ class SongImport(QtCore.QObject): """ For debugging """ - print u'========================================' \ + print u'========================================' \ + u'========================================' print u'TITLE: ' + self.title print u'ALT TITLE: ' + self.alternate_title - for (versetag, versetext, lang) in self.verses: - print u'VERSE ' + versetag + u': ' + versetext + for (verse_def, verse_text, lang) in self.verses: + print u'VERSE ' + verse_def + u': ' + verse_text print u'ORDER: ' + u' '.join(self.verse_order_list) + print u'GENERATED ORDER: ' + u' '.join(self.verse_order_list_generated) for author in self.authors: print u'AUTHOR: ' + author if self.copyright: diff --git a/openlp/plugins/songs/lib/songshowplusimport.py b/openlp/plugins/songs/lib/songshowplusimport.py new file mode 100644 index 000000000..2e2410d1b --- /dev/null +++ b/openlp/plugins/songs/lib/songshowplusimport.py @@ -0,0 +1,203 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`wowimport` module provides the functionality for importing Words of +Worship songs into the OpenLP database. +""" +import os +import logging +import struct + +from openlp.core.ui.wizard import WizardStrings +from openlp.plugins.songs.lib.songimport import SongImport + +TITLE = 1 +AUTHOR = 2 +COPYRIGHT = 3 +CCLI_NO = 5 +VERSE = 12 +CHORUS = 20 +TOPIC = 29 +COMMENTS = 30 +VERSE_ORDER = 31 +SONG_BOOK = 35 +SONG_NUMBER = 36 +CUSTOM_VERSE = 37 + +log = logging.getLogger(__name__) + +class SongShowPlusImport(SongImport): + """ + The :class:`SongShowPlusImport` class provides the ability to import song + files from SongShow Plus. + + **SongShow Plus Song File Format:** + + The SongShow Plus song file format is as follows: + + * Each piece of data in the song file has some information that precedes + it. + * The general format of this data is as follows: + 4 Bytes, forming a 32 bit number, a key if you will, this describes what + the data is (see blockKey below) + 4 Bytes, forming a 32 bit number, which is the number of bytes until the + next block starts + 1 Byte, which tells how namy bytes follows + 1 or 4 Bytes, describes how long the string is, if its 1 byte, the string + is less than 255 + The next bytes are the actuall data. + The next block of data follows on. + + This description does differ for verses. Which includes extra bytes + stating the verse type or number. In some cases a "custom" verse is used, + in that case, this block will in include 2 strings, with the associated + string length descriptors. The first string is the name of the verse, the + second is the verse content. + + The file is ended with four null bytes. + + Valid extensions for a SongShow Plus song file are: + + * .sbsong + """ + otherList = {} + otherCount = 0 + + def __init__(self, manager, **kwargs): + """ + Initialise the SongShow Plus importer. + """ + SongImport.__init__(self, manager, **kwargs) + + def do_import(self): + """ + 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)) + for file in self.import_source: + author = u'' + self.sspVerseOrderList = [] + otherCount = 0 + otherList = {} + file_name = os.path.split(file)[1] + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name, 0) + songData = open(file, 'rb') + while (1): + blockKey, = struct.unpack("I", songData.read(4)) + # The file ends with 4 NUL's + if blockKey == 0: + break + nextBlockStarts, = struct.unpack("I", songData.read(4)) + if blockKey == VERSE or blockKey == CHORUS: + null, verseNo, = struct.unpack("BB", songData.read(2)) + elif blockKey == CUSTOM_VERSE: + null, verseNameLength, = struct.unpack("BB", + songData.read(2)) + verseName = songData.read(verseNameLength) + lengthDescriptorSize, = struct.unpack("B", songData.read(1)) + # Detect if/how long the length descriptor is + if lengthDescriptorSize == 12: + lengthDescriptor, = struct.unpack("I", songData.read(4)) + elif lengthDescriptorSize == 2: + lengthDescriptor = 1 + elif lengthDescriptorSize == 9: + lengthDescriptor = 0 + else: + lengthDescriptor, = struct.unpack("B", songData.read(1)) + data = songData.read(lengthDescriptor) + if blockKey == TITLE: + self.title = unicode(data, u'cp1252') + elif blockKey == AUTHOR: + authors = data.split(" / ") + for author in authors: + if author.find(",") !=-1: + authorParts = author.split(", ") + author = authorParts[1] + " " + authorParts[0] + self.parse_author(unicode(author, u'cp1252')) + elif blockKey == COPYRIGHT: + self.add_copyright(unicode(data, u'cp1252')) + elif blockKey == CCLI_NO: + self.ccli_number = int(data) + elif blockKey == VERSE: + self.add_verse(unicode(data, u'cp1252'), + "V%s" % verseNo) + elif blockKey == CHORUS: + self.add_verse(unicode(data, u'cp1252'), + "C%s" % verseNo) + elif blockKey == TOPIC: + self.topics.append(unicode(data, u'cp1252')) + elif blockKey == COMMENTS: + self.comments = unicode(data, u'cp1252') + elif blockKey == VERSE_ORDER: + verseTag = self.toOpenLPVerseTag(data) + self.sspVerseOrderList.append(unicode(verseTag, + u'cp1252')) + elif blockKey == SONG_BOOK: + self.song_book_name = unicode(data, u'cp1252') + elif blockKey == SONG_NUMBER: + self.song_number = ord(data) + elif blockKey == CUSTOM_VERSE: + verseTag = self.toOpenLPVerseTag(verseName) + self.add_verse(unicode(data, u'cp1252'), verseTag) + else: + log.debug("Unrecognised blockKey: %s, data: %s" + %(blockKey, data)) + self.verse_order_list = self.sspVerseOrderList + songData.close() + self.finish() + self.import_wizard.incrementProgressBar( + WizardStrings.ImportingType % file_name) + return True + + def toOpenLPVerseTag(self, verseName): + if verseName.find(" ") != -1: + verseParts = verseName.split(" ") + verseType = verseParts[0] + verseNumber = verseParts[1] + else: + verseType = verseName + verseNumber = "1" + verseType = verseType.lower() + if verseType == "verse": + verseTag = "V" + elif verseType == "chorus": + verseTag = "C" + elif verseType == "bridge": + verseTag = "B" + elif verseType == "pre-chorus": + verseTag = "P" + elif verseType == "bridge": + verseTag = "B" + else: + if not self.otherList.has_key(verseName): + self.otherCount = self.otherCount + 1 + self.otherList[verseName] = str(self.otherCount) + verseTag = "O" + verseNumber = self.otherList[verseName] + verseTag = verseTag + verseNumber + return verseTag diff --git a/openlp/plugins/songs/lib/songstab.py b/openlp/plugins/songs/lib/songstab.py index 9ed8ace94..2848208d2 100644 --- a/openlp/plugins/songs/lib/songstab.py +++ b/openlp/plugins/songs/lib/songstab.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songs/lib/test/test_import_file.py b/openlp/plugins/songs/lib/test/test_import_file.py index 0a0228317..4c3460426 100644 --- a/openlp/plugins/songs/lib/test/test_import_file.py +++ b/openlp/plugins/songs/lib/test/test_import_file.py @@ -4,11 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songs/lib/test/test_importing_lots.py b/openlp/plugins/songs/lib/test/test_importing_lots.py index 75982da92..4fa5dc7c1 100644 --- a/openlp/plugins/songs/lib/test/test_importing_lots.py +++ b/openlp/plugins/songs/lib/test/test_importing_lots.py @@ -1,3 +1,29 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + from openlp.plugins.songs.lib.opensongimport import OpenSongImport from openlp.plugins.songs.lib.db import init_schema from openlp.core.lib.db import Manager diff --git a/openlp/plugins/songs/lib/test/test_opensongimport.py b/openlp/plugins/songs/lib/test/test_opensongimport.py index fd1d37e3e..cd85cad3b 100644 --- a/openlp/plugins/songs/lib/test/test_opensongimport.py +++ b/openlp/plugins/songs/lib/test/test_opensongimport.py @@ -4,11 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songs/lib/ui.py b/openlp/plugins/songs/lib/ui.py new file mode 100644 index 000000000..fe4aab988 --- /dev/null +++ b/openlp/plugins/songs/lib/ui.py @@ -0,0 +1,45 @@ +# -*- 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, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### +""" +The :mod:`openlp.plugins.songs.lib.ui` module provides standard UI components +for the songs plugin. +""" +from openlp.core.lib import translate + +class SongStrings(object): + """ + Provide standard strings for use throughout the songs plugin. + """ + # These strings should need a good reason to be retranslated elsewhere. + Author = translate('OpenLP.Ui', 'Author', 'Singular') + Authors = translate('OpenLP.Ui', 'Authors', 'Plural') + AuthorUnknown = u'Author Unknown' # Used to populate the database. + CopyrightSymbol = translate('OpenLP.Ui', '\xa9', 'Copyright symbol.') + SongBook = translate('OpenLP.Ui', 'Song Book', 'Singular') + SongBooks = translate('OpenLP.Ui', 'Song Books', 'Plural') + SongMaintenance = translate('OpenLP.Ui', 'Song Maintenance') + Topic = translate('OpenLP.Ui', 'Topic', 'Singular') + Topics = translate('OpenLP.Ui', 'Topics', 'Plural') diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index b90a47de6..b4bddd4d3 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -30,6 +30,7 @@ Worship songs into the OpenLP database. import os import logging +from openlp.core.ui.wizard import WizardStrings from openlp.plugins.songs.lib.songimport import SongImport BLOCK_TYPES = (u'V', u'C', u'B') @@ -91,19 +92,11 @@ class WowImport(SongImport): * .wow-song """ - def __init__(self, master_manager, **kwargs): + def __init__(self, manager, **kwargs): """ - Initialise the import. - - ``master_manager`` - The song manager for the running OpenLP installation. + Initialise the Words of Worship importer. """ - SongImport.__init__(self, master_manager) - if kwargs.has_key(u'filename'): - self.import_source = kwargs[u'filename'] - if kwargs.has_key(u'filenames'): - self.import_source = kwargs[u'filenames'] - log.debug(self.import_source) + SongImport.__init__(self, manager, **kwargs) def do_import(self): """ @@ -116,7 +109,7 @@ class WowImport(SongImport): copyright = u'' file_name = os.path.split(file)[1] self.import_wizard.incrementProgressBar( - u'Importing %s' % (file_name), 0) + WizardStrings.ImportingType % file_name, 0) # Get the song title self.title = file_name.rpartition(u'.')[0] songData = open(file, 'rb') @@ -162,5 +155,5 @@ class WowImport(SongImport): songData.close() self.finish() self.import_wizard.incrementProgressBar( - u'Importing %s' % (file_name)) + WizardStrings.ImportingType % file_name) return True diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 91bfdb025..a2a73ec97 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -26,7 +26,7 @@ """ The :mod:`xml` module provides the XML functionality. -The basic XML for storing the lyrics in the song database is of the format:: +The basic XML for storing the lyrics in the song database looks like this:: <?xml version="1.0" encoding="UTF-8"?> <song version="1.0"> @@ -38,7 +38,7 @@ The basic XML for storing the lyrics in the song database is of the format:: </song> -The XML of `OpenLyrics <http://openlyrics.info/>`_ songs is of the format:: +The XML of an `OpenLyrics <http://openlyrics.info/>`_ song looks like this:: <song xmlns="http://openlyrics.info/namespace/2009/song" version="0.7" @@ -60,13 +60,13 @@ The XML of `OpenLyrics <http://openlyrics.info/>`_ songs is of the format:: </song> """ +import datetime import logging import re from lxml import etree, objectify -from openlp.core.lib import translate -from openlp.plugins.songs.lib import VerseType +from openlp.plugins.songs.lib import add_author_unknown, VerseType from openlp.plugins.songs.lib.db import Author, Book, Song, Topic log = logging.getLogger(__name__) @@ -86,11 +86,13 @@ class SongXML(object): def add_verse_to_lyrics(self, type, number, content, lang=None): """ - Add a verse to the *<lyrics>* tag. + Add a verse to the ``<lyrics>`` tag. ``type`` - A string denoting the type of verse. Possible values are "V", - "C", "B", "P", "I", "E" and "O". + A string denoting the type of verse. Possible values are *Verse*, + *Chorus*, *Bridge*, *Pre-Chorus*, *Intro*, *Ending* and *Other*. + Any other type is **not** allowed, this also includes translated + types. ``number`` An integer denoting the number of the item, for example: verse 1. @@ -126,8 +128,8 @@ class SongXML(object): The returned list has the following format:: - [[{'lang': 'en', 'type': 'V', 'label': '1'}, u"The English verse."], - [{'lang': 'en', 'type': 'C', 'label': '1'}, u"The English chorus."]] + [[{'lang': 'en', 'type': 'Verse', 'label': '1'}, u"English verse"], + [{'lang': 'en', 'type': 'Chorus', 'label': '1'}, u"English chorus"]] """ self.song_xml = None if xml[:5] == u'<?xml': @@ -158,60 +160,63 @@ class OpenLyrics(object): to/from a song. As OpenLyrics has a rich set of different features, we cannot support them - all. The following features are supported by the :class:`OpenLyrics`:: + all. The following features are supported by the :class:`OpenLyrics` class: - *<authors>* + ``<authors>`` OpenLP does not support the attribute *type* and *lang*. - *<chord>* + ``<chord>`` This property is not supported. - *<comments>* - The *<comments>* property is fully supported. But comments in lyrics + ``<comments>`` + The ``<comments>`` property is fully supported. But comments in lyrics are not supported. - *<copyright>* + ``<copyright>`` This property is fully supported. - *<customVersion>* + ``<customVersion>`` This property is not supported. - *<key>* + ``<key>`` This property is not supported. - *<keywords>* + ``<keywords>`` This property is not supported. - *<lines>* + ``<lines>`` The attribute *part* is not supported. - *<publisher>* + ``<publisher>`` This property is not supported. - *<songbooks>* + ``<songbooks>`` As OpenLP does only support one songbook, we cannot consider more than one songbook. - *<tempo>* + ``<tempo>`` This property is not supported. - *<themes>* + ``<themes>`` Topics, as they are called in OpenLP, are fully supported, whereby only the topic text (e. g. Grace) is considered, but neither the *id* nor *lang*. - *<transposition>* + ``<transposition>`` This property is not supported. - *<variant>* + ``<variant>`` This property is not supported. - *<verse name="v1a" lang="he" translit="en">* - The attribute *translit* is not supported. + ``<verse name="v1a" lang="he" translit="en">`` + The attribute *translit* is not supported. Note, the attribute *lang* is + considered, but there is not further functionality implemented yet. - *<verseOrder>* + ``<verseOrder>`` OpenLP supports this property. + """ + IMPLEMENTED_VERSION = u'0.7' def __init__(self, manager): self.manager = manager @@ -221,8 +226,14 @@ class OpenLyrics(object): """ sxml = SongXML() verse_list = sxml.get_verses(song.lyrics) - song_xml = objectify.fromstring( - u'<song version="0.7" createdIn="OpenLP 2.0"/>') + song_xml = objectify.fromstring(u'<song/>') + # Append the necessary meta data to the song. + song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song') + song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION) + song_xml.set(u'createdIn', u'OpenLP 1.9.4') # Use variable + song_xml.set(u'modifiedIn', u'OpenLP 1.9.4') # Use variable + song_xml.set(u'modifiedDate', + datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S')) properties = etree.SubElement(song_xml, u'properties') titles = etree.SubElement(properties, u'titles') self._add_text_to_element(u'title', titles, song.title.strip()) @@ -236,7 +247,7 @@ class OpenLyrics(object): self._add_text_to_element(u'copyright', properties, song.copyright) if song.verse_order: self._add_text_to_element( - u'verseOrder', properties, song.verse_order) + u'verseOrder', properties, song.verse_order.lower()) if song.ccli_number: self._add_text_to_element(u'ccliNo', properties, song.ccli_number) if song.authors: @@ -251,7 +262,8 @@ class OpenLyrics(object): songbooks = etree.SubElement(properties, u'songbooks') element = self._add_text_to_element( u'songbook', songbooks, None, book) - element.set(u'entry', song.song_number) + if song.song_number: + element.set(u'entry', song.song_number) if song.topics: themes = etree.SubElement(properties, u'themes') for topic in song.topics: @@ -262,6 +274,8 @@ class OpenLyrics(object): verse[0][u'type'][0].lower(), verse[0][u'label']) element = \ self._add_text_to_element(u'verse', lyrics, None, verse_tag) + if verse[0].has_key(u'lang'): + element.set(u'lang', verse[0][u'lang']) element = self._add_text_to_element(u'lines', element) for line in unicode(verse[1]).split(u'\n'): self._add_text_to_element(u'line', element, line) @@ -284,9 +298,9 @@ class OpenLyrics(object): # Remove chords from xml. xml = re.compile(u'<chord name=".*?"/>').sub(u'', xml) song_xml = objectify.fromstring(xml) - try: + if hasattr(song_xml, u'properties'): properties = song_xml.properties - except AttributeError: + else: return None song = Song() self._process_copyright(properties, song) @@ -354,17 +368,11 @@ class OpenLyrics(object): The song object. """ authors = [] - try: + if hasattr(properties, u'authors'): for author in properties.authors.author: display_name = self._text(author) if display_name: authors.append(display_name) - except AttributeError: - pass - if not authors: - # Add "Author unknown" (can be translated). - authors.append((unicode(translate('SongsPlugin.XML', - 'Author unknown')))) for display_name in authors: author = self.manager.get_object_filtered(Author, Author.display_name == display_name) @@ -373,8 +381,9 @@ class OpenLyrics(object): author = Author.populate(display_name=display_name, last_name=display_name.split(u' ')[-1], first_name=u' '.join(display_name.split(u' ')[:-1])) - self.manager.save_object(author) song.authors.append(author) + if not song.authors: + add_author_unknown(self.manager, song) def _process_cclinumber(self, properties, song): """ @@ -386,10 +395,8 @@ class OpenLyrics(object): ``song`` The song object. """ - try: + if hasattr(properties, u'ccliNo'): song.ccli_number = self._text(properties.ccliNo) - except AttributeError: - song.ccli_number = u'' def _process_comments(self, properties, song): """ @@ -401,15 +408,13 @@ class OpenLyrics(object): ``song`` The song object. """ - try: + if hasattr(properties, u'comments'): comments_list = [] for comment in properties.comments.comment: commenttext = self._text(comment) if commenttext: comments_list.append(commenttext) song.comments = u'\n'.join(comments_list) - except AttributeError: - song.comments = u'' def _process_copyright(self, properties, song): """ @@ -421,10 +426,8 @@ class OpenLyrics(object): ``song`` The song object. """ - try: + if hasattr(properties, u'copyright'): song.copyright = self._text(properties.copyright) - except AttributeError: - song.copyright = u'' def _process_lyrics(self, properties, lyrics, song): """ @@ -449,7 +452,8 @@ class OpenLyrics(object): text += u'\n' text += u'\n'.join([unicode(line) for line in lines.line]) verse_name = self._get(verse, u'name') - verse_type = unicode(VerseType.to_string(verse_name[0]))[0] + verse_type_index = VerseType.from_tag(verse_name[0]) + verse_type = VerseType.Names[verse_type_index] verse_number = re.compile(u'[a-zA-Z]*').sub(u'', verse_name) verse_part = re.compile(u'[0-9]*').sub(u'', verse_name[1:]) # OpenLyrics allows e. g. "c", but we need "c1". @@ -464,9 +468,9 @@ class OpenLyrics(object): song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') # Process verse order - try: + if hasattr(properties, u'verseOrder'): song.verse_order = self._text(properties.verseOrder) - except AttributeError: + else: # We have to process the temp_verse_order, as the verseOrder # property is not present. previous_type = u'' @@ -477,9 +481,9 @@ class OpenLyrics(object): for name in temp_verse_order: if name[0] == previous_type: if name[1] != previous_number: - verse_order.append(u''.join((name[0], name[1]))) + verse_order.append(u''.join((name[0][0], name[1]))) else: - verse_order.append(u''.join((name[0], name[1]))) + verse_order.append(u''.join((name[0][0], name[1]))) previous_type = name[0] previous_number = name[1] previous_part = name[2] @@ -497,7 +501,7 @@ class OpenLyrics(object): """ song.song_book_id = 0 song.song_number = u'' - try: + if hasattr(properties, u'songbooks'): for songbook in properties.songbooks.songbook: bookname = self._get(songbook, u'name') if bookname: @@ -508,15 +512,10 @@ class OpenLyrics(object): book = Book.populate(name=bookname, publisher=u'') self.manager.save_object(book) song.song_book_id = book.id - try: - if self._get(songbook, u'entry'): - song.song_number = self._get(songbook, u'entry') - except AttributeError: - pass + if hasattr(songbook, u'entry'): + song.song_number = self._get(songbook, u'entry') # We only support one song book, so take the first one. break - except AttributeError: - pass def _process_titles(self, properties, song): """ @@ -549,7 +548,7 @@ class OpenLyrics(object): ``song`` The song object. """ - try: + if hasattr(properties, u'themes'): for topictext in properties.themes.theme: topictext = self._text(topictext) if topictext: @@ -560,8 +559,6 @@ class OpenLyrics(object): topic = Topic.populate(name=topictext) self.manager.save_object(topic) song.topics.append(topic) - except AttributeError: - pass def _dump_xml(self, xml): """ diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 7efe73db2..0335b3a6e 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -31,7 +31,9 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import Plugin, StringContent, build_icon, translate from openlp.core.lib.db import Manager -from openlp.plugins.songs.lib import SongMediaItem, SongsTab, SongXML +from openlp.core.lib.ui import UiStrings +from openlp.plugins.songs.lib import add_author_unknown, SongMediaItem, \ + SongsTab, SongXML from openlp.plugins.songs.lib.db import init_schema, Song from openlp.plugins.songs.lib.importer import SongFormat @@ -51,17 +53,14 @@ class SongsPlugin(Plugin): """ Create and set up the Songs plugin. """ - Plugin.__init__(self, u'Songs', u'1.9.4', plugin_helpers) + Plugin.__init__(self, u'Songs', u'1.9.4', plugin_helpers, + SongMediaItem, SongsTab) self.weight = -10 self.manager = Manager(u'songs', init_schema) self.icon_path = u':/plugins/plugin_songs.png' self.icon = build_icon(self.icon_path) self.whitespace = re.compile(r'\W+', re.UNICODE) - def getSettingsTab(self): - visible_name = self.getString(StringContent.VisibleName) - return SongsTab(self.name, visible_name[u'title']) - def initialise(self): log.info(u'Songs Initialising') Plugin.initialise(self) @@ -69,13 +68,6 @@ class SongsPlugin(Plugin): self.mediaItem.displayResultsSong( self.manager.get_all_objects(Song, order_by_ref=Song.search_title)) - def getMediaManagerItem(self): - """ - Create the MediaManagerItem object, which is displaed in the - Media Manager. - """ - return SongMediaItem(self, self, self.icon) - def addImportMenuItem(self, import_menu): """ Give the Songs plugin the opportunity to add items to the @@ -106,8 +98,17 @@ class SongsPlugin(Plugin): The actual **Export** menu item, so that your actions can use it as their parent. """ - # No menu items for now. - pass + # Main song import menu item - will eventually be the only one + self.SongExportItem = QtGui.QAction(export_menu) + self.SongExportItem.setObjectName(u'SongExportItem') + self.SongExportItem.setText(translate( + 'SongsPlugin', '&Song')) + self.SongExportItem.setToolTip(translate('SongsPlugin', + 'Exports songs using the export wizard.')) + export_menu.addAction(self.SongExportItem) + # Signals and slots + QtCore.QObject.connect(self.SongExportItem, + QtCore.SIGNAL(u'triggered()'), self.onSongExportItemClicked) def addToolsMenuItem(self, tools_menu): """ @@ -138,14 +139,16 @@ class SongsPlugin(Plugin): """ maxSongs = self.manager.get_object_count(Song) progressDialog = QtGui.QProgressDialog( - translate('SongsPlugin', 'Reindexing songs...'), - translate('SongsPlugin', 'Cancel'), + translate('SongsPlugin', 'Reindexing songs...'), UiStrings.Cancel, 0, maxSongs + 1, self.formparent) progressDialog.setWindowModality(QtCore.Qt.WindowModal) songs = self.manager.get_all_objects(Song) counter = 0 for song in songs: counter += 1 + # The song does not have any author, add one. + if not song.authors: + add_author_unknown(self.manager, song) if song.title is None: song.title = u'' if song.alternate_title is None: @@ -172,6 +175,10 @@ class SongsPlugin(Plugin): if self.mediaItem: self.mediaItem.onImportClick() + def onSongExportItemClicked(self): + if self.mediaItem: + self.mediaItem.onExportClick() + def about(self): about_text = translate('SongsPlugin', '<strong>Songs Plugin</strong>' '<br />The songs plugin provides the ability to display and ' @@ -225,42 +232,18 @@ class SongsPlugin(Plugin): u'title': translate('SongsPlugin', 'Songs', 'container title') } # Middle Header Bar - ## New Action ## - self.textStrings[StringContent.New] = { - u'title': translate('SongsPlugin', 'Add'), - u'tooltip': translate('SongsPlugin', - 'Add a new Song') - } - ## Edit Action ## - self.textStrings[StringContent.Edit] = { - u'title': translate('SongsPlugin', 'Edit'), - u'tooltip': translate('SongsPlugin', - 'Edit the selected Song') - } - ## Delete Action ## - self.textStrings[StringContent.Delete] = { - u'title': translate('SongsPlugin', 'Delete'), - u'tooltip': translate('SongsPlugin', - 'Delete the selected Song') - } - ## Preview Action ## - self.textStrings[StringContent.Preview] = { - u'title': translate('SongsPlugin', 'Preview'), - u'tooltip': translate('SongsPlugin', - 'Preview the selected Song') - } - ## Send Live Action ## - self.textStrings[StringContent.Live] = { - u'title': translate('SongsPlugin', 'Live'), - u'tooltip': translate('SongsPlugin', - 'Send the selected Song live') - } - ## Add to Service Action ## - self.textStrings[StringContent.Service] = { - u'title': translate('SongsPlugin', 'Service'), - u'tooltip': translate('SongsPlugin', + tooltips = { + u'load': u'', + u'import': u'', + u'new': translate('SongsPlugin', 'Add a new Song'), + u'edit': translate('SongsPlugin', 'Edit the selected Song'), + u'delete': translate('SongsPlugin', 'Delete the selected Song'), + u'preview': translate('SongsPlugin', 'Preview the selected Song'), + u'live': translate('SongsPlugin', 'Send the selected Song live'), + u'service': translate('SongsPlugin', 'Add the selected Song to the service') } + self.setPluginUiTextStrings(tooltips) def finalise(self): """ diff --git a/openlp/plugins/songusage/__init__.py b/openlp/plugins/songusage/__init__.py index 7f532aada..5a58a5a81 100644 --- a/openlp/plugins/songusage/__init__.py +++ b/openlp/plugins/songusage/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,4 +27,4 @@ The :mod:`songusage` module contains the Song Usage plugin. The Song Usage plugin provides auditing capabilities for reporting the songs you are using to copyright license organisations. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/songusage/forms/__init__.py b/openlp/plugins/songusage/forms/__init__.py index ef99bce89..c95384e5e 100644 --- a/openlp/plugins/songusage/forms/__init__.py +++ b/openlp/plugins/songusage/forms/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### from songusagedeleteform import SongUsageDeleteForm -from songusagedetailform import SongUsageDetailForm \ No newline at end of file +from songusagedetailform import SongUsageDetailForm diff --git a/openlp/plugins/songusage/forms/songusagedeletedialog.py b/openlp/plugins/songusage/forms/songusagedeletedialog.py index af85ad5a9..879056e16 100644 --- a/openlp/plugins/songusage/forms/songusagedeletedialog.py +++ b/openlp/plugins/songusage/forms/songusagedeletedialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,7 +25,9 @@ ############################################################################### from PyQt4 import QtCore, QtGui + from openlp.core.lib import translate +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_SongUsageDeleteDialog(object): def setupUi(self, songUsageDeleteDialog): @@ -43,22 +45,14 @@ class Ui_SongUsageDeleteDialog(object): QtGui.QCalendarWidget.NoVerticalHeader) self.deleteCalendar.setObjectName(u'deleteCalendar') self.verticalLayout.addWidget(self.deleteCalendar) - self.buttonBox = QtGui.QDialogButtonBox(songUsageDeleteDialog) + self.buttonBox = create_accept_reject_button_box( + songUsageDeleteDialog, True) self.buttonBox.setGeometry(QtCore.QRect(30, 210, 245, 25)) - self.buttonBox.setStandardButtons( - QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) self.buttonBox.setObjectName(u'buttonBox') - self.retranslateUi(songUsageDeleteDialog) - QtCore.QObject.connect( - self.buttonBox, QtCore.SIGNAL(u'accepted()'), - songUsageDeleteDialog.accept) - QtCore.QObject.connect( - self.buttonBox, QtCore.SIGNAL(u'rejected()'), - songUsageDeleteDialog.close) QtCore.QMetaObject.connectSlotsByName(songUsageDeleteDialog) def retranslateUi(self, songUsageDeleteDialog): songUsageDeleteDialog.setWindowTitle( translate('SongUsagePlugin.SongUsageDeleteForm', - 'Delete Song Usage Data')) \ No newline at end of file + 'Delete Song Usage Data')) diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py index c03fe15a3..a96aacccd 100644 --- a/openlp/plugins/songusage/forms/songusagedeleteform.py +++ b/openlp/plugins/songusage/forms/songusagedeleteform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py index ec1f69d7e..7c812efeb 100644 --- a/openlp/plugins/songusage/forms/songusagedetaildialog.py +++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -27,6 +27,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import build_icon, translate +from openlp.core.lib.ui import create_accept_reject_button_box class Ui_SongUsageDetailDialog(object): def setupUi(self, songUsageDetailDialog): @@ -71,17 +72,10 @@ class Ui_SongUsageDetailDialog(object): self.verticalLayout4.addLayout(self.horizontalLayout) self.verticalLayout2.addWidget(self.fileGroupBox) self.verticalLayout.addWidget(self.dateRangeGroupBox) - self.buttonBox = QtGui.QDialogButtonBox(songUsageDetailDialog) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | - QtGui.QDialogButtonBox.Ok) - self.buttonBox.setObjectName(u'buttonBox') + self.buttonBox = create_accept_reject_button_box( + songUsageDetailDialog, True) self.verticalLayout.addWidget(self.buttonBox) - self.retranslateUi(songUsageDetailDialog) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), - songUsageDetailDialog.accept) - QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'), - songUsageDetailDialog.close) QtCore.QObject.connect(self.saveFilePushButton, QtCore.SIGNAL(u'pressed()'), songUsageDetailDialog.defineOutputLocation) diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index ff8ec4858..ee37b2a9c 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/openlp/plugins/songusage/lib/__init__.py b/openlp/plugins/songusage/lib/__init__.py index c981e023b..860b25463 100644 --- a/openlp/plugins/songusage/lib/__init__.py +++ b/openlp/plugins/songusage/lib/__init__.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -25,4 +25,4 @@ ############################################################################### """ The :mod:`lib` module contains the library functions for the songusage plugin. -""" \ No newline at end of file +""" diff --git a/openlp/plugins/songusage/lib/db.py b/openlp/plugins/songusage/lib/db.py index 80079bf85..2508ddc14 100644 --- a/openlp/plugins/songusage/lib/db.py +++ b/openlp/plugins/songusage/lib/db.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -61,4 +61,4 @@ def init_schema(url): mapper(SongUsageItem, songusage_table) metadata.create_all(checkfirst=True) - return session \ No newline at end of file + return session diff --git a/openlp/plugins/songusage/songusageplugin.py b/openlp/plugins/songusage/songusageplugin.py index ec37dc65e..e1dc0f1a8 100644 --- a/openlp/plugins/songusage/songusageplugin.py +++ b/openlp/plugins/songusage/songusageplugin.py @@ -6,9 +6,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/resources/forms/displaytabdialog.ui b/resources/forms/displaytabdialog.ui new file mode 100644 index 000000000..b181635be --- /dev/null +++ b/resources/forms/displaytabdialog.ui @@ -0,0 +1,206 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>displayTagEdit</class> + <widget class="QWidget" name="displayTagEdit"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>725</width> + <height>548</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <widget class="QWidget" name=""> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>701</width> + <height>521</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QTableWidget" name="tagTableWidget"> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="cornerButtonEnabled"> + <bool>false</bool> + </property> + <column> + <property name="text"> + <string>Description</string> + </property> + </column> + <column> + <property name="text"> + <string>Key</string> + </property> + <property name="textAlignment"> + <set>AlignHCenter|AlignVCenter|AlignCenter</set> + </property> + </column> + <column> + <property name="text"> + <string>Start Tag</string> + </property> + </column> + <column> + <property name="text"> + <string>End Tag</string> + </property> + </column> + </widget> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="defaultPushButton"> + <property name="text"> + <string>Default</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="deletePushButton"> + <property name="text"> + <string>Delete</string> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0"> + <widget class="QGroupBox" name="editGroupBox"> + <property name="title"> + <string>Edit Selection</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="descriptionLabel"> + <property name="text"> + <string>Description</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="0" column="1" rowspan="2"> + <widget class="QLineEdit" name="descriptionLineEdit"/> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="addPushButton"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item row="1" column="2" rowspan="2"> + <widget class="QPushButton" name="newPushButton"> + <property name="text"> + <string>New</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="tagLabel"> + <property name="text"> + <string>Tag</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="tagLineEdit"> + <property name="maximumSize"> + <size> + <width>50</width> + <height>16777215</height> + </size> + </property> + <property name="maxLength"> + <number>5</number> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="startTagLabel"> + <property name="text"> + <string>Start tag</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="startTagLineEdit"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="endTagLabel"> + <property name="text"> + <string>End tag</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="endTagLineEdit"/> + </item> + <item row="4" column="2"> + <widget class="QPushButton" name="updatePushButton"> + <property name="text"> + <string>Update</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item row="3" column="0"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/resources/forms/displaytabeditdialog.ui b/resources/forms/displaytabeditdialog.ui deleted file mode 100644 index 3c748594f..000000000 --- a/resources/forms/displaytabeditdialog.ui +++ /dev/null @@ -1,209 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>displayTagEdit</class> - <widget class="QWidget" name="displayTagEdit"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>717</width> - <height>554</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <widget class="QGroupBox" name="editGroupBox"> - <property name="geometry"> - <rect> - <x>10</x> - <y>320</y> - <width>691</width> - <height>181</height> - </rect> - </property> - <property name="title"> - <string>Edit Selection</string> - </property> - <widget class="QPushButton" name="updatePushButton"> - <property name="geometry"> - <rect> - <x>600</x> - <y>140</y> - <width>73</width> - <height>26</height> - </rect> - </property> - <property name="text"> - <string>Update</string> - </property> - </widget> - <widget class="QWidget" name="layoutWidget"> - <property name="geometry"> - <rect> - <x>20</x> - <y>50</y> - <width>571</width> - <height>114</height> - </rect> - </property> - <layout class="QFormLayout" name="formLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="descriptionLabel"> - <property name="text"> - <string>Description</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="descriptionLineEdit"/> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="tagLabel"> - <property name="text"> - <string>Tag</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="tagLineEdit"> - <property name="maximumSize"> - <size> - <width>50</width> - <height>16777215</height> - </size> - </property> - <property name="maxLength"> - <number>5</number> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="startTagLabel"> - <property name="text"> - <string>Start tag</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QLineEdit" name="startTagLineEdit"/> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="endTagLabel"> - <property name="text"> - <string>End tag</string> - </property> - <property name="alignment"> - <set>Qt::AlignCenter</set> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QLineEdit" name="endTagLineEdit"/> - </item> - </layout> - </widget> - </widget> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="geometry"> - <rect> - <x>540</x> - <y>510</y> - <width>162</width> - <height>26</height> - </rect> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - <widget class="QPushButton" name="deletePushButton"> - <property name="geometry"> - <rect> - <x>530</x> - <y>280</y> - <width>71</width> - <height>26</height> - </rect> - </property> - <property name="text"> - <string>Delete</string> - </property> - </widget> - <widget class="QPushButton" name="addPushButton"> - <property name="geometry"> - <rect> - <x>610</x> - <y>280</y> - <width>71</width> - <height>26</height> - </rect> - </property> - <property name="text"> - <string>Add</string> - </property> - </widget> - <widget class="QTableWidget" name="tagTableWidget"> - <property name="geometry"> - <rect> - <x>10</x> - <y>10</y> - <width>691</width> - <height>271</height> - </rect> - </property> - <property name="horizontalScrollBarPolicy"> - <enum>Qt::ScrollBarAlwaysOff</enum> - </property> - <property name="editTriggers"> - <set>QAbstractItemView::NoEditTriggers</set> - </property> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::SingleSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - <property name="cornerButtonEnabled"> - <bool>false</bool> - </property> - <column> - <property name="text"> - <string>Description</string> - </property> - </column> - <column> - <property name="text"> - <string>Key</string> - </property> - <property name="textAlignment"> - <set>AlignHCenter|AlignVCenter|AlignCenter</set> - </property> - </column> - <column> - <property name="text"> - <string>Start Tag</string> - </property> - </column> - <column> - <property name="text"> - <string>End Tag</string> - </property> - </column> - </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/resources/forms/printserviceorderdialog.ui b/resources/forms/printserviceorderdialog.ui new file mode 100644 index 000000000..f95aff17b --- /dev/null +++ b/resources/forms/printserviceorderdialog.ui @@ -0,0 +1,230 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Dialog</class> + <widget class="QDialog" name="Dialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>494</width> + <height>434</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <widget class="QWidget" name=""> + <property name="geometry"> + <rect> + <x>4</x> + <y>4</y> + <width>491</width> + <height>432</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="dialogLayout"> + <item row="0" column="3"> + <layout class="QVBoxLayout" name="settingsLayout"> + <item> + <layout class="QGridLayout" name="serviceTitleLayout"> + <item row="1" column="1"> + <widget class="QLineEdit" name="serviceTitleLineEdit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="serviceTitleLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Service Title:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="printSlideTextCheckBox"> + <property name="text"> + <string>Include slide text if avaialbe</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="printNotesCheckBox"> + <property name="text"> + <string>Include service item notes</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="printMetaDataCheckBox"> + <property name="text"> + <string>Include play lenght of media items</string> + </property> + </widget> + </item> + <item> + <spacer name="spacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="customNotesLabel"> + <property name="text"> + <string><b>Custom Notes:</b></string> + </property> + </widget> + </item> + <item> + <widget class="QTextEdit" name="customNoteEdit"/> + </item> + </layout> + </item> + <item row="1" column="0"> + <layout class="QHBoxLayout" name="zoomButtonLayout"> + <item> + <spacer name="spacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QToolButton" name="zoomOutButton"> + <property name="text"> + <string>...</string> + </property> + <property name="icon"> + <iconset resource="../images/openlp-2.qrc"> + <normaloff>:/general/general_zoom_out.png</normaloff>:/general/general_zoom_out.png</iconset> + </property> + </widget> + </item> + <item> + <widget class="QToolButton" name="zoomInButton"> + <property name="icon"> + <iconset resource="../images/openlp-2.qrc"> + <normaloff>:/general/general_zoom_in.png</normaloff>:/general/general_zoom_in.png</iconset> + </property> + </widget> + </item> + </layout> + </item> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="perviewLayout"> + <item> + <widget class="QLabel" name="previewLabel"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Preview:</string> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="previewWidget" native="true"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <zorder>spacer_3</zorder> + </widget> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="buttonLayout"> + <item> + <spacer name="spacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="cancelButton_3"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelButton_2"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelButton"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="printButton"> + <property name="text"> + <string>Print</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + <resources> + <include location="../images/openlp-2.qrc"/> + </resources> + <connections/> +</ui> diff --git a/resources/forms/songexport.ui b/resources/forms/songexport.ui deleted file mode 100644 index 9830db3ef..000000000 --- a/resources/forms/songexport.ui +++ /dev/null @@ -1,241 +0,0 @@ -<ui version="4.0" > - <class>SongExportDialog</class> - <widget class="QDialog" name="SongExportDialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>641</width> - <height>607</height> - </rect> - </property> - <property name="windowTitle" > - <string>Dialog</string> - </property> - <layout class="QVBoxLayout" name="SongExportLayout" > - <property name="spacing" > - <number>8</number> - </property> - <property name="margin" > - <number>8</number> - </property> - <item> - <widget class="QWidget" native="1" name="SongListsWidget" > - <layout class="QHBoxLayout" name="SongListsLayout" > - <property name="spacing" > - <number>8</number> - </property> - <property name="margin" > - <number>0</number> - </property> - <item> - <widget class="QGroupBox" name="AvailableGroupBox" > - <property name="title" > - <string>Available Songs</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout" > - <item> - <widget class="QListWidget" name="AvailableListWidget" /> - </item> - <item> - <widget class="QToolButton" name="AvailableAllToolButton" > - <property name="text" > - <string>Select All</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QWidget" native="1" name="SelectionWidget" > - <property name="sizePolicy" > - <sizepolicy vsizetype="Minimum" hsizetype="Minimum" > - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize" > - <size> - <width>30</width> - <height>16777215</height> - </size> - </property> - <layout class="QVBoxLayout" name="SelectionLayout" > - <property name="spacing" > - <number>8</number> - </property> - <property name="sizeConstraint" > - <enum>QLayout::SetMinimumSize</enum> - </property> - <property name="margin" > - <number>0</number> - </property> - <item> - <spacer name="TopVerticalSpacer" > - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType" > - <enum>QSizePolicy::MinimumExpanding</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>20</width> - <height>132</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QToolButton" name="SelectToolButton" > - <property name="text" > - <string>Select Songs</string> - </property> - <property name="icon" > - <iconset resource="../images/openlp-2.qrc" > - <normaloff>:/exports/export_move_to_list.png</normaloff>:/exports/export_move_to_list.png</iconset> - </property> - <property name="iconSize" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </widget> - </item> - <item> - <widget class="QToolButton" name="DeselectToolButton" > - <property name="text" > - <string>Deselect Songs</string> - </property> - <property name="icon" > - <iconset resource="../images/openlp-2.qrc" > - <normaloff>:/exports/export_remove.png</normaloff>:/exports/export_remove.png</iconset> - </property> - <property name="iconSize" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </widget> - </item> - <item> - <spacer name="BottomVerticalSpacer" > - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType" > - <enum>QSizePolicy::MinimumExpanding</enum> - </property> - <property name="sizeHint" stdset="0" > - <size> - <width>20</width> - <height>131</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="SelectedGroupBox" > - <property name="title" > - <string>Selected Songs</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2" > - <item> - <widget class="QListWidget" name="SelectedListWidget" /> - </item> - <item> - <widget class="QToolButton" name="SelectedAllToolButton" > - <property name="text" > - <string>Select All</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QTabWidget" name="ExportTabWidget" > - <property name="currentIndex" > - <number>0</number> - </property> - <widget class="QWidget" name="OpenLyricTab" > - <attribute name="title" > - <string>OpenLyric Format</string> - </attribute> - </widget> - <widget class="QWidget" name="TextFileTab" > - <attribute name="title" > - <string>Text File</string> - </attribute> - </widget> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="SongExportButtonBox" > - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons" > - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>SongExportButtonBox</tabstop> - <tabstop>AvailableListWidget</tabstop> - <tabstop>AvailableAllToolButton</tabstop> - <tabstop>SelectToolButton</tabstop> - <tabstop>DeselectToolButton</tabstop> - <tabstop>SelectedListWidget</tabstop> - <tabstop>SelectedAllToolButton</tabstop> - <tabstop>ExportTabWidget</tabstop> - </tabstops> - <resources> - <include location="../images/openlp-2.qrc" /> - </resources> - <connections> - <connection> - <sender>SongExportButtonBox</sender> - <signal>accepted()</signal> - <receiver>SongExportDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel" > - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel" > - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>SongExportButtonBox</sender> - <signal>rejected()</signal> - <receiver>SongExportDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel" > - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel" > - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/resources/images/bibles_search_reference.png b/resources/images/bibles_search_reference.png new file mode 100644 index 000000000..f64c0ad78 Binary files /dev/null and b/resources/images/bibles_search_reference.png differ diff --git a/resources/images/bibles_search_text.png b/resources/images/bibles_search_text.png new file mode 100644 index 000000000..1ab7145c6 Binary files /dev/null and b/resources/images/bibles_search_text.png differ diff --git a/resources/images/export_move_to_list.png b/resources/images/export_move_to_list.png deleted file mode 100644 index 5c0005856..000000000 Binary files a/resources/images/export_move_to_list.png and /dev/null differ diff --git a/resources/images/export_remove.png b/resources/images/export_remove.png deleted file mode 100644 index ef8e685e2..000000000 Binary files a/resources/images/export_remove.png and /dev/null differ diff --git a/resources/images/export_selectall.png b/resources/images/export_selectall.png deleted file mode 100644 index 0f0d9f152..000000000 Binary files a/resources/images/export_selectall.png and /dev/null differ diff --git a/resources/images/general_print.png b/resources/images/general_print.png new file mode 100644 index 000000000..8eb1c6741 Binary files /dev/null and b/resources/images/general_print.png differ diff --git a/resources/images/general_zoom_in.png b/resources/images/general_zoom_in.png new file mode 100644 index 000000000..8393e281a Binary files /dev/null and b/resources/images/general_zoom_in.png differ diff --git a/resources/images/general_zoom_original.png b/resources/images/general_zoom_original.png new file mode 100644 index 000000000..a268a9984 Binary files /dev/null and b/resources/images/general_zoom_original.png differ diff --git a/resources/images/general_zoom_out.png b/resources/images/general_zoom_out.png new file mode 100644 index 000000000..f66575efd Binary files /dev/null and b/resources/images/general_zoom_out.png differ diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 6b9d6dd54..794e006d9 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -21,6 +21,10 @@ <file>song_topic_edit.png</file> <file>song_book_edit.png</file> </qresource> + <qresource prefix="bibles"> + <file>bibles_search_text.png</file> + <file>bibles_search_reference.png</file> + </qresource> <qresource prefix="plugins"> <file>plugin_alerts.png</file> <file>plugin_bibles.png</file> @@ -41,6 +45,10 @@ <file>general_export.png</file> <file>general_import.png</file> <file>general_new.png</file> + <file>general_zoom_out.png</file> + <file>general_zoom_in.png</file> + <file>general_zoom_original.png</file> + <file>general_print.png</file> <file>general_open.png</file> <file>general_save.png</file> <file>general_email.png</file> @@ -78,12 +86,10 @@ <file>import_load.png</file> </qresource> <qresource prefix="exports"> - <file>export_selectall.png</file> - <file>export_remove.png</file> <file>export_load.png</file> - <file>export_move_to_list.png</file> </qresource> <qresource prefix="wizards"> + <file>wizard_exportsong.bmp</file> <file>wizard_importsong.bmp</file> <file>wizard_importbible.bmp</file> <file>wizard_createtheme.bmp</file> @@ -110,6 +116,9 @@ <file>system_exit.png</file> <file>settings_plugin_list.png</file> <file>system_settings.png</file> + <file>tag_editor.png</file> + <file>system_configure.png</file> + <file>system_edit_copy.png</file> <file>system_configure_shortcuts.png</file> </qresource> <qresource prefix="media"> diff --git a/resources/images/system_configure.png b/resources/images/system_configure.png new file mode 100644 index 000000000..45b8fae8b Binary files /dev/null and b/resources/images/system_configure.png differ diff --git a/resources/images/system_edit_copy.png b/resources/images/system_edit_copy.png new file mode 100644 index 000000000..d34cdcd32 Binary files /dev/null and b/resources/images/system_edit_copy.png differ diff --git a/resources/images/tag_editor.png b/resources/images/tag_editor.png new file mode 100644 index 000000000..d03963448 Binary files /dev/null and b/resources/images/tag_editor.png differ diff --git a/resources/images/wizard_exportsong.bmp b/resources/images/wizard_exportsong.bmp new file mode 100644 index 000000000..948422dcc Binary files /dev/null and b/resources/images/wizard_exportsong.bmp differ diff --git a/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py b/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py index f99d4feac..2f00db438 100644 --- a/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py +++ b/resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py @@ -4,11 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/resources/pyinstaller/hook-openlp.py b/resources/pyinstaller/hook-openlp.py index 489c633f6..7e954551f 100644 --- a/resources/pyinstaller/hook-openlp.py +++ b/resources/pyinstaller/hook-openlp.py @@ -4,11 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/resources/windows/OpenLP-2.0.iss b/resources/windows/OpenLP-2.0.iss index a85b41187..c64e2b488 100644 --- a/resources/windows/OpenLP-2.0.iss +++ b/resources/windows/OpenLP-2.0.iss @@ -68,6 +68,7 @@ Source: ..\..\dist\OpenLP\*; DestDir: {app}; Flags: ignoreversion recursesubdirs [Icons] Name: {group}\{#AppName}; Filename: {app}\{#AppExeName} +Name: {group}\{#AppName} (Debug); Filename: {app}\{#AppExeName}; Parameters: -l debug Name: {group}\{cm:ProgramOnTheWeb,{#AppName}}; Filename: {#AppURL} Name: {group}\{cm:UninstallProgram,{#AppName}}; Filename: {uninstallexe} Name: {commondesktop}\{#AppName}; Filename: {app}\{#AppExeName}; Tasks: desktopicon diff --git a/scripts/generate_resources.sh b/scripts/generate_resources.sh index c2039a5b6..b363e58b6 100755 --- a/scripts/generate_resources.sh +++ b/scripts/generate_resources.sh @@ -4,10 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin # -# Thompson, Jon Tibble, Carsten Tinggaard # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/scripts/openlp-remoteclient.py b/scripts/openlp-remoteclient.py index 34fef44a8..11868e292 100644 --- a/scripts/openlp-remoteclient.py +++ b/scripts/openlp-remoteclient.py @@ -5,11 +5,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/scripts/resources.patch b/scripts/resources.patch index cfcf4e37e..f80d31d73 100644 --- a/scripts/resources.patch +++ b/scripts/resources.patch @@ -1,9 +1,9 @@ ---- openlp/core/resources.py.old Mon Jun 21 23:16:19 2010 -+++ openlp/core/resources.py Mon Jun 21 23:27:48 2010 +--- openlp/core/resources.py.old Mon Jun 21 23:16:19 2010 ++++ openlp/core/resources.py Mon Jun 21 23:27:48 2010 @@ -1,10 +1,32 @@ # -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 - + -# Resource object code -# -# @@ -12,11 +12,11 @@ +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # -+# Copyright (c) 2008-2010 Raoul Snyman # -+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -+# Carsten Tinggaard, Frode Woldsund # ++# Copyright (c) 2008-2011 Raoul Snyman # ++# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # ++# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # ++# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # ++# Tibble, Carsten Tinggaard, Frode Woldsund # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # @@ -36,11 +36,11 @@ +store for use by OpenLP. +""" from PyQt4 import QtCore - + qt_resource_data = "\ @@ -48643,9 +48664,16 @@ " - + def qInitResources(): - QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + """ @@ -48,7 +48,7 @@ + """ + QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, + qt_resource_data) - + def qCleanupResources(): - QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + """ @@ -56,5 +56,5 @@ + """ + QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, + qt_resource_data) - + -qInitResources() diff --git a/scripts/translation_utils.py b/scripts/translation_utils.py index 495732085..df8d5dc5e 100755 --- a/scripts/translation_utils.py +++ b/scripts/translation_utils.py @@ -5,11 +5,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/scripts/windows-builder.py b/scripts/windows-builder.py index 1af85853d..b4085712f 100644 --- a/scripts/windows-builder.py +++ b/scripts/windows-builder.py @@ -4,11 +4,11 @@ ############################################################################### # OpenLP - Open Source Lyrics Projection # # --------------------------------------------------------------------------- # -# Copyright (c) 2008-2010 Raoul Snyman # -# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Copyright (c) 2008-2011 Raoul Snyman # +# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # diff --git a/setup.py b/setup.py index 205688f1e..98e9d40fd 100755 --- a/setup.py +++ b/setup.py @@ -7,9 +7,9 @@ # --------------------------------------------------------------------------- # # Copyright (c) 2008-2011 Raoul Snyman # # Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael # -# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian # -# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, # -# Carsten Tinggaard, Frode Woldsund # +# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, # +# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon # +# Tibble, Carsten Tinggaard, Frode Woldsund # # --------------------------------------------------------------------------- # # This program is free software; you can redistribute it and/or modify it # # under the terms of the GNU General Public License as published by the Free # @@ -78,4 +78,4 @@ OpenLP (previously openlp.org) is free church presentation software, or lyrics p entry_points=""" # -*- Entry points: -*- """ -) \ No newline at end of file +)