This commit is contained in:
Andreas Preikschat 2011-02-17 15:35:55 +01:00
commit 0bcc877a41
147 changed files with 5063 additions and 3972 deletions

View File

@ -4,8 +4,8 @@
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# 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 #

View File

@ -1,124 +0,0 @@
openlp.org 2.x Song Database Structure
========================================================================
Introduction
------------
The song database in openlp.org 2.x is similar to the 1.x format. The
biggest differences are the addition of extra tables, and the use of
SQLite version 3.
The song database contains the following tables:
- authors
- authors_songs
- song_books
- songs
- songs_topics
- topics
"authors" Table
---------------
This table holds the names of all the authors. It has the following
columns:
* id
* first_name
* last_name
* display_name
"authors_songs" Table
---------------------
This is a bridging table between the "authors" and "songs" tables, which
serves to create a many-to-many relationship between the two tables. It
has the following columns:
* author_id
* song_id
"song_books" Table
------------------
The "song_books" table holds a list of books that a congregation gets
their songs from, or old hymnals now no longer used. This table has the
following columns:
* id
* name
* publisher
"songs" Table
-------------
This table contains the songs, and each song has a list of attributes.
The "songs" table has the following columns:
* id
* song_book_id
* title
* lyrics
* verse_order
* copyright
* comments
* ccli_number
* song_number
* theme_name
* search_title
* search_lyrics
"songs_topics" Table
--------------------
This is a bridging table between the "songs" and "topics" tables, which
serves to create a many-to-many relationship between the two tables. It
has the following columns:
* song_id
* topic_id
"topics" Table
--------------
The topics table holds a selection of topics that songs can cover. This
is useful when a worship leader wants to select songs with a certain
theme. This table has the following columns:
* id
* name
The lyrics definition (more or less similar to interformat to/from ChangingSong
The tags <i></i><b></b><u></u> can also be used within the lyrics test.
! Please note that this format has been checked at http://validator.w3.org/#validate_by_upload
<lyrics lang="en_US">
<title>Amazing Grace</title>
<verse name="v1">
<theme>name of verse specific theme (optional)</theme>
<comment>any text (optional)</comment>
<part name="men">
Amazing grace, how ...
</part>
<part name="women">
A b c
D e f
</part>
...
</verse>
<verse name="c">
<theme>name of verse specific theme (optional)</theme>
<comment>any text (optional)</comment>
...
</verse>
</lyrics>
<lyrics lang="de_DE">
<title>Erstaunliche Anmut</title>
<verse name="v1">
Erstaunliche Anmut, wie
...
</verse>
<verse name="c">
...
</verse>
</lyrics>

View File

@ -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`
-----------------------

View File

@ -1,8 +1,10 @@
.. _core-theme:
:mod:`theme` Module
===================
Theme Function Library
======================
.. automodule:: openlp.core.theme
:members:
.. autoclass:: openlp.core.theme.theme.Theme
:members:

View File

@ -1,7 +0,0 @@
.. _openlp:
:mod:`openlp` Module
====================
.. automodule:: openlp
:members:

View File

@ -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

View File

@ -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
# "<project> v<release> documentation".

View File

@ -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

View File

@ -17,10 +17,3 @@ Contents:
mediamanager
songs
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@ -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() %}
<p>
{%- block openlp_qthelprel1 %}
{%- endblock %}
{%- if prev %}
«&#160;&#160;<a href="{{ prev.link|e }}">{{ prev.title }}</a>
&#160;&#160;::&#160;&#160;
{%- endif %}
<a class="uplink" href="{{ pathto(master_doc) }}">{{ _('Contents') }}</a>
{%- if next %}
&#160;&#160;::&#160;&#160;
<a href="{{ next.link|e }}">{{ next.title }}</a>&#160;&#160;»
{%- endif %}
{%- block openlp_qthelprel2 %}
{%- endblock %}
</p>
{% endmacro %}
{% block content %}
<!-- div class="header">
{%- block openlp_qthelpheader %}
{%- if theme_full_logo != "false" %}
<a href="{{ pathto('index') }}">
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
</a>
{%- else %}
{%- if logo -%}
<img class="rightlogo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
{%- endif -%}
<h1 class="heading"><a href="{{ pathto('index') }}">
<span>{{ shorttitle|e }}</span></a></h1>
<h2 class="heading"><span>{{ title|striptags|e }}</span></h2>
{%- endif %}
{%- endblock %}
</div -->
<div class="topnav">
{{ nav() }}
</div>
<div class="content">
{#{%- if display_toc %}
<div id="toc">
<h3>Table Of Contents</h3>
{{ toc }}
</div>
{%- endif %}#}
{% block body %}{% endblock %}
</div>
<div class="bottomnav">
{{ nav() }}
</div>
{% endblock %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

View File

@ -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 <revol@free.fr>
* Stephan Assmus <superstippi@gmx.de>
* Braden Ewing <brewin@gmail.com>
* Humdinger <humdingerb@gmail.com>
*
* :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;
}

View File

@ -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

View File

@ -76,7 +76,7 @@ class OpenLP(QtGui.QApplication):
"""
Load and store current Application Version
"""
if u'--dev-version' in sys.argv:
if u'--dev-version' in sys.argv or u'-d' in sys.argv:
# If we're running the dev version, let's use bzr to get the version
try:
# If bzrlib is availble, use it
@ -194,7 +194,10 @@ class OpenLP(QtGui.QApplication):
# now kill the splashscreen
self.splash.finish(self.mainWindow)
self.mainWindow.repaint()
VersionThread(self.mainWindow, app_version).start()
update_check = QtCore.QSettings().value(
u'general/update check', QtCore.QVariant(True)).toBool()
if update_check:
VersionThread(self.mainWindow, app_version).start()
return self.exec_()
def hookException(self, exctype, value, traceback):
@ -213,6 +216,7 @@ class OpenLP(QtGui.QApplication):
Sets the Busy Cursor for the Application
"""
self.setOverrideCursor(QtCore.Qt.BusyCursor)
self.processEvents()
def setNormalCursor(self):
"""
@ -280,4 +284,4 @@ if __name__ == u'__main__':
"""
Instantiate and run the application.
"""
main()
main()

View File

@ -315,10 +315,11 @@ def check_directory_exists(dir):
``dir``
Theme directory to make sure exists
"""
log.debug(u'check_directory_exists')
log.debug(u'check_directory_exists %s' % dir)
if not os.path.exists(dir):
os.makedirs(dir)
from listwidgetwithdnd import ListWidgetWithDnD
from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \
BackgroundType, HorizontalType, VerticalType
from displaytags import DisplayTags
@ -339,4 +340,3 @@ from dockwidget import OpenLPDockWidget
from renderer import Renderer
from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem
from baselistwithdnd import BaseListWithDnD

View File

@ -86,10 +86,10 @@ 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):
"""

View File

@ -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)

View File

@ -31,6 +31,8 @@ import logging
from PyQt4 import QtGui
from openlp.core.lib import build_icon
log = logging.getLogger(__name__)
class OpenLPDockWidget(QtGui.QDockWidget):
@ -47,4 +49,4 @@ class OpenLPDockWidget(QtGui.QDockWidget):
if name:
self.setObjectName(name)
if icon:
self.setWindowIcon(icon)
self.setWindowIcon(build_icon(icon))

View File

@ -28,7 +28,8 @@ import logging
from PyQt4 import QtWebKit
from openlp.core.lib import BackgroundType, BackgroundGradientType
from openlp.core.lib import BackgroundType, BackgroundGradientType, \
VerticalType
log = logging.getLogger(__name__)
@ -314,7 +315,7 @@ body {
</html>
"""
def build_html(item, screen, alert, islive):
def build_html(item, screen, alert, islive, background):
"""
Build the full web paged structure for display
@ -332,7 +333,9 @@ def build_html(item, screen, alert, islive):
theme = item.themedata
webkitvers = webkit_version()
# Image generated and poked in
if item.bg_image_bytes:
if background:
image = u'src="data:image/png;base64,%s"' % background
elif item.bg_image_bytes:
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
else:
image = u'style="display:none;"'
@ -534,12 +537,7 @@ def build_lyrics_format_css(theme, width, height):
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'
valign = VerticalType.to_string(theme.display_vertical_align)
if theme.font_main_outline:
left_margin = int(theme.font_main_outline_size) * 2
else:
@ -632,13 +630,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.to_string(alertTab.location)
alert = style % (width, align, alertTab.font_face, alertTab.font_size,
alertTab.font_color, alertTab.bg_color)
return alert

View File

@ -61,10 +61,10 @@ 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')

View File

@ -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)
mimeData.setText(self.mimeDataText)
drag.start(QtCore.Qt.CopyAction)

View File

@ -33,7 +33,7 @@ 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
log = logging.getLogger(__name__)
@ -73,11 +73,6 @@ class MediaManagerItem(QtGui.QWidget):
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
@ -98,16 +93,11 @@ class MediaManagerItem(QtGui.QWidget):
visible_title = self.plugin.getString(StringContent.VisibleName)
self.title = unicode(visible_title[u'title'])
self.settingsSection = self.plugin.name.lower()
if isinstance(icon, QtGui.QIcon):
self.icon = icon
elif isinstance(icon, basestring):
self.icon.addPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(icon)),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
else:
self.icon = None
self.icon = None
if icon:
self.icon = build_icon(icon)
self.toolbar = None
self.remoteTriggered = None
self.serviceItemIconName = None
self.singleServiceItem = True
self.pageLayout = QtGui.QVBoxLayout(self)
self.pageLayout.setSpacing(0)
@ -163,7 +153,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``
@ -207,68 +197,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)
## 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.Preview,
u':/general/general_preview.png', self.onPreviewClick])
## Live Button ##
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.title)
self.listView.uniformItemSizes = True
self.listView.setSpacing(1)
self.listView.setSelectionMode(
@ -280,7 +252,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(
@ -371,33 +342,34 @@ class MediaManagerItem(QtGui.QWidget):
count += 1
return filelist
def validate(self, file, thumb):
def validate(self, image, thumb):
"""
Validates to see if the file still exists or thumbnail is up to date
Validates whether an image still exists and, if it does, is the
thumbnail representation of the image up to date.
"""
if not os.path.exists(file):
if not os.path.exists(image):
return False
if os.path.exists(thumb):
filedate = os.stat(file).st_mtime
thumbdate = os.stat(thumb).st_mtime
# if file updated rebuild icon
if filedate > thumbdate:
self.iconFromFile(file, thumb)
imageDate = os.stat(image).st_mtime
thumbDate = os.stat(thumb).st_mtime
# If image has been updated rebuild icon
if imageDate > thumbDate:
self.iconFromFile(image, thumb)
else:
self.iconFromFile(file, thumb)
self.iconFromFile(image, thumb)
return True
def iconFromFile(self, file, thumb):
def iconFromFile(self, image, thumb):
"""
Create a thumbnail icon from a given file
Create a thumbnail icon from a given image.
``file``
The file to create the icon from
``image``
The image file to create the icon from.
``thumb``
The filename to save the thumbnail to
"""
icon = build_icon(unicode(file))
icon = build_icon(unicode(image))
pixmap = icon.pixmap(QtCore.QSize(88, 50))
ext = os.path.splitext(thumb)[1].lower()
pixmap.save(thumb, ext[1:])
@ -408,12 +380,16 @@ class MediaManagerItem(QtGui.QWidget):
u'defined by the plugin')
def onNewClick(self):
raise NotImplementedError(u'MediaManagerItem.onNewClick needs to be '
u'defined by the plugin')
"""
Hook for plugins to define behaviour for adding new items.
"""
pass
def onEditClick(self):
raise NotImplementedError(u'MediaManagerItem.onEditClick needs to be '
u'defined by the plugin')
"""
Hook for plugins to define behaviour for editing items.
"""
pass
def onDeleteClick(self):
raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to '
@ -500,7 +476,7 @@ class MediaManagerItem(QtGui.QWidget):
"""
if not self.listView.selectedIndexes() and not self.remoteTriggered:
QtGui.QMessageBox.information(self,
translate('OpenLP.MediaManagerItem', 'No items selected'),
translate('OpenLP.MediaManagerItem', 'No Items Selected'),
translate('OpenLP.MediaManagerItem',
'You must select one or more items'))
else:
@ -512,7 +488,7 @@ class MediaManagerItem(QtGui.QWidget):
'No Service Item Selected'),
translate('OpenLP.MediaManagerItem',
'You must select an existing service item to add to.'))
elif self.title.lower() == serviceItem.name.lower():
elif self.plugin.name.lower() == serviceItem.name.lower():
self.generateSlideData(serviceItem)
self.parent.serviceManager.addServiceItem(serviceItem,
replace=True)
@ -529,10 +505,7 @@ class MediaManagerItem(QtGui.QWidget):
Common method for generating a service item
"""
serviceItem = ServiceItem(self.parent)
if self.serviceItemIconName:
serviceItem.add_icon(self.serviceItemIconName)
else:
serviceItem.add_icon(self.parent.icon_path)
serviceItem.add_icon(self.parent.icon_path)
if self.generateSlideData(serviceItem, item, xmlVersion):
return serviceItem
else:
@ -544,3 +517,25 @@ class MediaManagerItem(QtGui.QWidget):
individual service items need to be processed by the plugins
"""
pass
def _getIdOfItemToGenerate(self, item, remoteItem):
"""
Utility method to check items being submitted for slide generation.
``item``
The item to check.
``remoteItem``
The id to assign if the slide generation was remotely triggered.
"""
if item is None:
if self.remoteTriggered is None:
item = self.listView.currentItem()
if item is None:
return False
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
else:
item_id = remoteItem
else:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
return item_id

View File

@ -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__)
@ -42,7 +43,11 @@ class PluginStatus(object):
Inactive = 0
Disabled = -1
class StringContent(object):
"""
Provide standard strings for objects to use.
"""
Name = u'name'
Import = u'import'
Load = u'load'
@ -54,6 +59,7 @@ class StringContent(object):
Service = u'service'
VisibleName = u'visible_name'
class Plugin(QtCore.QObject):
"""
Base class for openlp plugins to inherit from.
@ -108,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*
@ -116,7 +123,7 @@ class Plugin(QtCore.QObject):
class MyPlugin(Plugin):
def __init__(self):
Plugin.__init(self, u'MyPlugin', u'0.1')
Plugin.__init__(self, u'MyPlugin', u'0.1')
``name``
Defaults to *None*. The name of the plugin.
@ -126,6 +133,12 @@ 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
@ -135,6 +148,8 @@ class Plugin(QtCore.QObject):
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
@ -193,7 +208,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):
"""
@ -224,9 +241,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):
"""
@ -314,8 +335,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}

View File

@ -68,7 +68,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):
@ -261,4 +260,4 @@ class RenderManager(object):
log.debug(u'calculate default %d, %d, %f',
self.width, self.height, self.screen_ratio )
# 90% is start of footer
self.footer_start = int(self.height * 0.90)
self.footer_start = int(self.height * 0.90)

View File

@ -93,15 +93,15 @@ class SearchEdit(QtGui.QLineEdit):
``event``
The event that happened.
"""
sz = self.clearButton.size()
size = self.clearButton.size()
frameWidth = self.style().pixelMetric(
QtGui.QStyle.PM_DefaultFrameWidth)
self.clearButton.move(self.rect().right() - frameWidth - sz.width(),
(self.rect().bottom() + 1 - sz.height()) / 2)
self.clearButton.move(self.rect().right() - frameWidth - size.width(),
(self.rect().bottom() + 1 - size.height()) / 2)
if hasattr(self, u'menuButton'):
sz = self.menuButton.size()
size = self.menuButton.size()
self.menuButton.move(self.rect().left() + frameWidth + 2,
(self.rect().bottom() + 1 - sz.height()) / 2)
(self.rect().bottom() + 1 - size.height()) / 2)
def currentSearchType(self):
"""

View File

@ -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__)
@ -59,6 +61,8 @@ class ItemCapabilities(object):
OnLoadUpdate = 8
AddIfNewItem = 9
ProvidesOwnDisplay = 10
AllowsDetailedTitleDisplay = 11
AllowsVarableStartTime = 12
class ServiceItem(object):
@ -104,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):
@ -256,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:
@ -300,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)
@ -314,6 +326,20 @@ class ServiceItem(object):
path, text_image[u'title'], text_image[u'image'] )
self._new_item()
def get_display_title(self):
"""
Returns the title of the service item.
"""
if self.is_text():
return self.title
else:
if ItemCapabilities.AllowsDetailedTitleDisplay in self.capabilities:
return self._raw_frames[0][u'title']
elif len(self._raw_frames) > 1:
return self.title
else:
return self._raw_frames[0][u'title']
def merge(self, other):
"""
Updates the _uuid with the value from the original one
@ -405,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)

View File

@ -47,13 +47,16 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
# Default dictionary based on the current locale.
if ENCHANT_AVAILABLE:
try:
self.dict = enchant.Dict()
self.dictionary = enchant.Dict()
except DictNotFoundError:
self.dict = enchant.Dict(u'en_US')
self.dictionary = enchant.Dict(u'en_US')
self.highlighter = Highlighter(self.document())
self.highlighter.setDict(self.dict)
self.highlighter.spellingDictionary = self.dictionary
def mousePressEvent(self, event):
"""
Handle mouse clicks within the text edit region.
"""
if event.button() == QtCore.Qt.RightButton:
# Rewrite the mouse event to a left button event so the cursor is
# moved to the location of the pointer.
@ -63,6 +66,9 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
QtGui.QPlainTextEdit.mousePressEvent(self, event)
def contextMenuEvent(self, event):
"""
Provide the context menu for the text edit region.
"""
popupMenu = self.createStandardContextMenu()
# Select the word under the cursor.
cursor = self.textCursor()
@ -74,10 +80,10 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
# suggestions if it is.
if ENCHANT_AVAILABLE and self.textCursor().hasSelection():
text = unicode(self.textCursor().selectedText())
if not self.dict.check(text):
if not self.dictionary.check(text):
spell_menu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',
'Spelling Suggestions'))
for word in self.dict.suggest(text):
for word in self.dictionary.suggest(text):
action = SpellAction(word, spell_menu)
action.correct.connect(self.correctWord)
spell_menu.addAction(action)
@ -126,28 +132,32 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
cursor.insertText(html[u'start tag'])
cursor.insertText(html[u'end tag'])
class Highlighter(QtGui.QSyntaxHighlighter):
class Highlighter(QtGui.QSyntaxHighlighter):
"""
Provides a text highlighter for pointing out spelling errors in text.
"""
WORDS = u'(?iu)[\w\']+'
def __init__(self, *args):
QtGui.QSyntaxHighlighter.__init__(self, *args)
self.dict = None
def setDict(self, dict):
self.dict = dict
self.spellingDictionary = None
def highlightBlock(self, text):
if not self.dict:
"""
Highlight misspelt words in a block of text
"""
if not self.spellingDictionary:
return
text = unicode(text)
format = QtGui.QTextCharFormat()
format.setUnderlineColor(QtCore.Qt.red)
format.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline)
charFormat = QtGui.QTextCharFormat()
charFormat.setUnderlineColor(QtCore.Qt.red)
charFormat.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline)
for word_object in re.finditer(self.WORDS, text):
if not self.dict.check(word_object.group()):
if not self.spellingDictionary.check(word_object.group()):
self.setFormat(word_object.start(),
word_object.end() - word_object.start(), format)
word_object.end() - word_object.start(), charFormat)
class SpellAction(QtGui.QAction):
"""

View File

@ -91,21 +91,30 @@ class ThemeLevel(object):
Song = 3
class BackgroundType(object):
"""
Type enumeration for backgrounds.
"""
Solid = 0
Gradient = 1
Image = 2
@staticmethod
def to_string(type):
if type == BackgroundType.Solid:
def to_string(background_type):
"""
Return a string representation of a background type.
"""
if background_type == BackgroundType.Solid:
return u'solid'
elif type == BackgroundType.Gradient:
elif background_type == BackgroundType.Gradient:
return u'gradient'
elif type == BackgroundType.Image:
elif background_type == BackgroundType.Image:
return u'image'
@staticmethod
def from_string(type_string):
"""
Return a background type for the given string.
"""
if type_string == u'solid':
return BackgroundType.Solid
elif type_string == u'gradient':
@ -114,6 +123,9 @@ class BackgroundType(object):
return BackgroundType.Image
class BackgroundGradientType(object):
"""
Type enumeration for background gradients.
"""
Horizontal = 0
Vertical = 1
Circular = 2
@ -121,20 +133,26 @@ class BackgroundGradientType(object):
LeftBottom = 4
@staticmethod
def to_string(type):
if type == BackgroundGradientType.Horizontal:
def to_string(gradient_type):
"""
Return a string representation of a background gradient type.
"""
if gradient_type == BackgroundGradientType.Horizontal:
return u'horizontal'
elif type == BackgroundGradientType.Vertical:
elif gradient_type == BackgroundGradientType.Vertical:
return u'vertical'
elif type == BackgroundGradientType.Circular:
elif gradient_type == BackgroundGradientType.Circular:
return u'circular'
elif type == BackgroundGradientType.LeftTop:
elif gradient_type == BackgroundGradientType.LeftTop:
return u'leftTop'
elif type == BackgroundGradientType.LeftBottom:
elif gradient_type == BackgroundGradientType.LeftBottom:
return u'leftBottom'
@staticmethod
def from_string(type_string):
"""
Return a background gradient type for the given string.
"""
if type_string == u'horizontal':
return BackgroundGradientType.Horizontal
elif type_string == u'vertical':
@ -146,20 +164,53 @@ 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
Center = 2
Right = 1
@staticmethod
def to_string(horizontal_type):
"""
Return a string representation of a horizontal type.
"""
if horizontal_type == HorizontalType.Right:
return u'right'
elif horizontal_type == HorizontalType.Center:
return u'center'
else:
return u'left'
class VerticalType(object):
"""
Type enumeration for vertical alignment.
"""
Top = 0
Middle = 1
Bottom = 2
boolean_list = [u'italics', u'override', u'outline', u'shadow',
@staticmethod
def to_string(vertical_type):
"""
Return a string representation of a vertical type.
"""
if vertical_type == VerticalType.Bottom:
return u'bottom'
elif vertical_type == VerticalType.Middle:
return u'middle'
else:
return u'top'
BOOLEAN_LIST = [u'bold', u'italics', u'override', u'outline', u'shadow',
u'slide_transition']
integer_list = [u'size', u'line_adjustment', u'x', u'height', u'y',
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']
@ -514,9 +565,9 @@ class ThemeXML(object):
return
field = self._de_hump(element)
tag = master + u'_' + field
if field in boolean_list:
if field in BOOLEAN_LIST:
setattr(self, tag, str_to_bool(value))
elif field in integer_list:
elif field in INTEGER_LIST:
setattr(self, tag, int(value))
else:
# make string value unicode
@ -559,8 +610,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,

View File

@ -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``
@ -73,13 +73,13 @@ class OpenLPToolbar(QtGui.QToolBar):
``checkable``
If *True* the button has two, *off* and *on*, states. Default is
*False*, which means the buttons has only one state.
``shortcut``
The primary shortcut for this action
``alternate``
The alternate shortcut for this action
``context``
Specify the context in which this shortcut is valid
"""

285
openlp/core/lib/ui.py Normal file
View File

@ -0,0 +1,285 @@
# -*- 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, 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:`ui` module provides standard UI components for OpenLP.
"""
import logging
from PyQt4 import QtCore, QtGui
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 &amp; attached?
Add = translate('OpenLP.Ui', '&Add')
Advanced = translate('OpenLP.Ui', 'Advanced')
AllFiles = translate('OpenLP.Ui', 'All Files')
Authors = translate('OpenLP.Ui', 'Authors')
CreateService = translate('OpenLP.Ui', 'Create a new service.')
Delete = translate('OpenLP.Ui', '&Delete')
Edit = translate('OpenLP.Ui', '&Edit')
Error = translate('OpenLP.Ui', 'Error')
Import = translate('OpenLP.Ui', 'Import')
LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
Live = translate('OpenLP.Ui', 'Live')
Load = translate('OpenLP.Ui', 'Load')
New = translate('OpenLP.Ui', 'New')
NewService = translate('OpenLP.Ui', 'New Service')
OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0')
OpenService = translate('OpenLP.Ui', 'Open Service')
Preview = translate('OpenLP.Ui', 'Preview')
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')
SaveService = translate('OpenLP.Ui', 'Save Service')
Service = translate('OpenLP.Ui', 'Service')
StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
Theme = translate('OpenLP.Ui', 'Theme')
Themes = translate('OpenLP.Ui', 'Themes')
def add_welcome_page(parent, image):
"""
Generate an opening welcome page for a wizard using a provided image.
``parent``
A ``QWizard`` object to add the welcome page to.
``image``
A splash image for the wizard.
"""
parent.welcomePage = QtGui.QWizardPage()
parent.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap,
QtGui.QPixmap(image))
parent.welcomePage.setObjectName(u'WelcomePage')
parent.welcomeLayout = QtGui.QVBoxLayout(parent.welcomePage)
parent.welcomeLayout.setObjectName(u'WelcomeLayout')
parent.titleLabel = QtGui.QLabel(parent.welcomePage)
parent.titleLabel.setObjectName(u'TitleLabel')
parent.welcomeLayout.addWidget(parent.titleLabel)
parent.welcomeLayout.addSpacing(40)
parent.informationLabel = QtGui.QLabel(parent.welcomePage)
parent.informationLabel.setWordWrap(True)
parent.informationLabel.setObjectName(u'InformationLabel')
parent.welcomeLayout.addWidget(parent.informationLabel)
parent.welcomeLayout.addStretch()
parent.addPage(parent.welcomePage)
def create_accept_reject_button_box(parent, okay=False):
"""
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.
``okay``
If true creates an okay/cancel combination instead of save/cancel.
"""
button_box = QtGui.QDialogButtonBox(parent)
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)
QtCore.QObject.connect(button_box, QtCore.SIGNAL(u'rejected()'),
parent.reject)
return button_box
def critical_error_message_box(title=None, message=None, parent=None,
question=False):
"""
Provides a standard critical message box for errors that OpenLP displays
to users.
``title``
The title for the message box.
``message``
The message to display to the user.
``parent``
The parent UI element to attach the dialog to.
``question``
Should this message box question the user.
"""
if question:
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 UiStrings.Error
return Receiver.send_message(u'openlp_error_message', data)
def media_item_combo_box(parent, name):
"""
Provide a standard combo box for media items.
"""
combo = QtGui.QComboBox(parent)
combo.setObjectName(name)
combo.setSizeAdjustPolicy(QtGui.QComboBox.AdjustToMinimumContentsLength)
combo.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
return combo
def create_delete_push_button(parent, icon=None):
"""
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.
``icon``
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(UiStrings.Delete)
delete_button.setToolTip(
translate('OpenLP.Ui', 'Delete the selected item.'))
QtCore.QObject.connect(delete_button,
QtCore.SIGNAL(u'clicked()'), parent.onDeleteButtonClicked)
return delete_button
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
connected to the parent's ``onUpButtonClicked()`` and
``onDownButtonClicked()`` to handle their respective ``clicked()`` signals.
``parent``
The parent object. This should be a ``QWidget`` descendant.
"""
up_button = QtGui.QPushButton(parent)
up_button.setIcon(build_icon(u':/services/service_up.png'))
up_button.setObjectName(u'upButton')
up_button.setToolTip(
translate('OpenLP.Ui', 'Move selection up one position.'))
down_button = QtGui.QPushButton(parent)
down_button.setIcon(build_icon(u':/services/service_down.png'))
down_button.setObjectName(u'downButton')
down_button.setToolTip(
translate('OpenLP.Ui', 'Move selection down one position.'))
QtCore.QObject.connect(up_button,
QtCore.SIGNAL(u'clicked()'), parent.onUpButtonClicked)
QtCore.QObject.connect(down_button,
QtCore.SIGNAL(u'clicked()'), parent.onDownButtonClicked)
return up_button, down_button
def base_action(parent, name):
"""
Return the most basic action with the object name set.
"""
action = QtGui.QAction(parent)
action.setObjectName(name)
return action
def checkable_action(parent, name, checked=None):
"""
Return a standard action with the checkable attribute set.
"""
action = base_action(parent, name)
action.setCheckable(True)
if checked is not None:
action.setChecked(checked)
return action
def icon_action(parent, name, icon, checked=None):
"""
Return a standard action with an icon.
"""
if checked is not None:
action = checkable_action(parent, name, checked)
else:
action = base_action(parent, name)
action.setIcon(build_icon(icon))
return action
def shortcut_action(parent, text, shortcuts, function):
"""
Return a shortcut enabled action.
"""
action = QtGui.QAction(text, parent)
action.setShortcuts(shortcuts)
action.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
QtCore.QObject.connect(action, QtCore.SIGNAL(u'triggered()'), function)
return action
def add_widget_completer(cache, widget):
"""
Adds a text autocompleter to a widget.
``cache``
The list of items to use as suggestions.
``widget``
The object to use the completer.
"""
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(translate('OpenLP.Ui', 'Top'))
form.verticalComboBox.addItem(translate('OpenLP.Ui', 'Middle'))
form.verticalComboBox.addItem(translate('OpenLP.Ui', 'Bottom'))
verticalLabel.setBuddy(form.verticalComboBox)
layout.addRow(verticalLabel, form.verticalComboBox)

View File

@ -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 = \
'''<?xml version="1.0" encoding="iso-8859-1"?>
@ -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
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
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
* ``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
* ``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

View File

@ -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):
"""
@ -51,36 +51,9 @@ class HideMode(object):
Theme = 2
Screen = 3
def criticalErrorMessageBox(title=None, message=None, parent=None,
question=False):
"""
Provides a standard critical message box for errors that OpenLP displays
to users.
``title``
The title for the message box.
``message``
The message to display to the user.
``parent``
The parent UI element to attach the dialog to.
``question``
Should this message box question the user.
"""
error = translate('OpenLP.Ui', 'Error')
if question:
return QtGui.QMessageBox.critical(parent, error, message,
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
data = {u'message': message}
data[u'title'] = title if title else error
return Receiver.send_message(u'openlp_error_message', data)
from themeform import ThemeForm
from filerenameform import FileRenameForm
from starttimeform import StartTimeForm
from maindisplay import MainDisplay
from servicenoteform import ServiceNoteForm
from serviceitemeditform import ServiceItemEditForm
@ -99,6 +72,6 @@ from mediadockmanager import MediaDockManager
from servicemanager import ServiceManager
from thememanager import ThemeManager
__all__ = ['criticalErrorMessageBox', 'SplashScreen', 'AboutForm',
'SettingsForm', 'MainDisplay', 'SlideController', 'ServiceManager',
'ThemeManager', 'MediaDockManager', 'ServiceItemEditForm']
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm', 'MainDisplay',
'SlideController', 'ServiceManager', 'ThemeManager', 'MediaDockManager',
'ServiceItemEditForm']

View File

@ -164,9 +164,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 '

View File

@ -29,6 +29,7 @@ The :mod:`advancedtab` provides an advanced settings facility.
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, translate
from openlp.core.lib.ui import UiStrings
class AdvancedTab(SettingsTab):
"""
@ -112,7 +113,7 @@ class AdvancedTab(SettingsTab):
"""
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',

View File

@ -23,27 +23,27 @@
# 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.ui import criticalErrorMessageBox
from openlp.core.lib.ui import UiStrings, critical_error_message_box
class DisplayTagTab(SettingsTab):
'''
"""
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):
@ -67,9 +67,9 @@ class DisplayTagTab(SettingsTab):
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')
@ -164,8 +164,7 @@ class DisplayTagTab(SettingsTab):
self.startTagLabel.setText(
translate('OpenLP.DisplayTagTab', 'Start tag'))
self.endTagLabel.setText(translate('OpenLP.DisplayTagTab', 'End tag'))
self.deletePushButton.setText(
translate('OpenLP.DisplayTagTab', 'Delete'))
self.deletePushButton.setText(UiStrings.Delete)
self.defaultPushButton.setText(
translate('OpenLP.DisplayTagTab', 'Default'))
self.newPushButton.setText(translate('OpenLP.DisplayTagTab', 'New'))
@ -276,7 +275,7 @@ class DisplayTagTab(SettingsTab):
"""
for html in DisplayTags.get_html_tags():
if self._strip(html[u'start tag']) == u'n':
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.DisplayTagTab', 'Update Error'),
translate('OpenLP.DisplayTagTab',
'Tag "n" already defined.'))
@ -317,7 +316,7 @@ class DisplayTagTab(SettingsTab):
for linenumber, html1 in enumerate(html_expands):
if self._strip(html1[u'start tag']) == tag and \
linenumber != self.selected:
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.DisplayTagTab', 'Update Error'),
unicode(translate('OpenLP.DisplayTagTab',
'Tag %s already defined.')) % tag)

View File

@ -46,6 +46,15 @@ class Ui_ExceptionDialog(object):
self.messageLabel.setObjectName(u'messageLabel')
self.messageLayout.addWidget(self.messageLabel)
self.exceptionLayout.addLayout(self.messageLayout)
self.descriptionExplanation = QtGui.QLabel(exceptionDialog)
self.descriptionExplanation.setObjectName(u'descriptionExplanation')
self.exceptionLayout.addWidget(self.descriptionExplanation)
self.descriptionTextEdit = QtGui.QPlainTextEdit(exceptionDialog)
self.descriptionTextEdit.setObjectName(u'descriptionTextEdit')
self.exceptionLayout.addWidget(self.descriptionTextEdit)
self.descriptionWordCount = QtGui.QLabel(exceptionDialog)
self.descriptionWordCount.setObjectName(u'descriptionWordCount')
self.exceptionLayout.addWidget(self.descriptionWordCount)
self.exceptionTextEdit = QtGui.QPlainTextEdit(exceptionDialog)
self.exceptionTextEdit.setReadOnly(True)
self.exceptionTextEdit.setObjectName(u'exceptionTextEdit')
@ -65,19 +74,31 @@ class Ui_ExceptionDialog(object):
self.saveReportButton.setObjectName(u'saveReportButton')
self.exceptionButtonBox.addButton(self.saveReportButton,
QtGui.QDialogButtonBox.ActionRole)
self.attachFileButton = QtGui.QPushButton(exceptionDialog)
self.attachFileButton.setIcon(build_icon(u':/general/general_open.png'))
self.attachFileButton.setObjectName(u'attachFileButton')
self.exceptionButtonBox.addButton(self.attachFileButton,
QtGui.QDialogButtonBox.ActionRole)
self.retranslateUi(exceptionDialog)
QtCore.QObject.connect(self.descriptionTextEdit,
QtCore.SIGNAL(u'textChanged()'), self.onDescriptionUpdated)
QtCore.QObject.connect(self.exceptionButtonBox,
QtCore.SIGNAL(u'rejected()'), exceptionDialog.reject)
QtCore.QObject.connect(self.sendReportButton,
QtCore.SIGNAL(u'pressed()'), self.onSendReportButtonPressed)
QtCore.QObject.connect(self.saveReportButton,
QtCore.SIGNAL(u'pressed()'), self.onSaveReportButtonPressed)
QtCore.QObject.connect(self.attachFileButton,
QtCore.SIGNAL(u'pressed()'), self.onAttachFileButtonPressed)
QtCore.QMetaObject.connectSlotsByName(exceptionDialog)
def retranslateUi(self, exceptionDialog):
exceptionDialog.setWindowTitle(
translate('OpenLP.ExceptionDialog', 'Error Occurred'))
self.descriptionExplanation.setText(translate('OpenLP.ExceptionDialog',
'Please enter a description of what you were doing to cause this '
'error \n(Minimum 20 characters)'))
self.messageLabel.setText(translate('OpenLP.ExceptionDialog', 'Oops! '
'OpenLP hit a problem, and couldn\'t recover. The text in the box '
'below contains information that might be helpful to the OpenLP '
@ -88,3 +109,5 @@ class Ui_ExceptionDialog(object):
'Send E-Mail'))
self.saveReportButton.setText(translate('OpenLP.ExceptionDialog',
'Save to File'))
self.attachFileButton.setText(translate('OpenLP.ExceptionDialog',
'Attach File'))

View File

@ -56,6 +56,7 @@ except ImportError:
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
@ -70,8 +71,15 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
self.setupUi(self)
self.settingsSection = u'crashreport'
def exec_(self):
self.descriptionTextEdit.setPlainText(u'')
self.onDescriptionUpdated()
self.fileAttachment = None
return QtGui.QDialog.exec_(self)
def _createReport(self):
openlp_version = self.parent().applicationVersion[u'full']
description = unicode(self.descriptionTextEdit.toPlainText())
traceback = unicode(self.exceptionTextEdit.toPlainText())
system = unicode(translate('OpenLP.ExceptionForm',
'Platform: %s\n')) % platform.platform()
@ -90,7 +98,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
system = system + u'Desktop: KDE SC\n'
elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'):
system = system + u'Desktop: GNOME\n'
return (openlp_version, traceback, system, libraries)
return (openlp_version, description, traceback, system, libraries)
def onSaveReportButtonPressed(self):
"""
@ -99,6 +107,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
report = unicode(translate('OpenLP.ExceptionForm',
'**OpenLP Bug Report**\n'
'Version: %s\n\n'
'--- Details of the Exception. ---\n\n%s\n\n '
'--- Exception Traceback ---\n%s\n'
'--- System information ---\n%s\n'
'--- Library Versions ---\n%s\n'))
@ -132,18 +141,47 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
body = unicode(translate('OpenLP.ExceptionForm',
'*OpenLP Bug Report*\n'
'Version: %s\n\n'
'--- Please enter the report below this line. ---\n\n\n'
'--- Details of the Exception. ---\n\n%s\n\n '
'--- Exception Traceback ---\n%s\n'
'--- System information ---\n%s\n'
'--- Library Versions ---\n%s\n',
'Please add the information that bug reports are favoured written '
'in English.'))
content = self._createReport()
for line in content[1].split(u'\n'):
for line in content[2].split(u'\n'):
if re.search(r'[/\\]openlp[/\\]', line):
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
if u':' in line:
exception = line.split(u'\n')[-1].split(u':')[0]
subject = u'Bug report: %s in %s' % (exception, source)
mailto(address=u'bugs@openlp.org', subject=subject,
body=body % content)
if self.fileAttachment:
mailto(address=u'bugs@openlp.org', subject=subject,
body=body % content, attach=self.fileAttachment)
else:
mailto(address=u'bugs@openlp.org', subject=subject,
body=body % content)
def onDescriptionUpdated(self):
count = int(20 - len(self.descriptionTextEdit.toPlainText()))
if count < 0:
count = 0
self.__buttonState(True)
else:
self.__buttonState(False)
self.descriptionWordCount.setText(
unicode(translate('OpenLP.ExceptionDialog',
'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 (*.*) (*)' % UiStrings.AllFiles)
log.info(u'New files(s) %s', unicode(files))
if files:
self.fileAttachment = unicode(files)
def __buttonState(self, state):
self.saveReportButton.setEnabled(state)
self.sendReportButton.setEnabled(state)

View File

@ -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:'))

View File

@ -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)

View File

@ -51,6 +51,7 @@ class ValidEdit(QtGui.QLineEdit):
else:
return self.text()
class GeneralTab(SettingsTab):
"""
GeneralTab is the general settings tab in the settings dialog.
@ -113,6 +114,9 @@ class GeneralTab(SettingsTab):
self.showSplashCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.showSplashCheckBox.setObjectName(u'showSplashCheckBox')
self.startupLayout.addWidget(self.showSplashCheckBox)
self.checkForUpdatesCheckBox = QtGui.QCheckBox(self.startupGroupBox)
self.checkForUpdatesCheckBox.setObjectName(u'checkForUpdatesCheckBox')
self.startupLayout.addWidget(self.checkForUpdatesCheckBox)
self.leftLayout.addWidget(self.startupGroupBox)
self.settingsGroupBox = QtGui.QGroupBox(self.leftColumn)
self.settingsGroupBox.setObjectName(u'settingsGroupBox')
@ -249,6 +253,8 @@ class GeneralTab(SettingsTab):
'Automatically open the last service'))
self.showSplashCheckBox.setText(
translate('OpenLP.GeneralTab', 'Show the splash screen'))
self.checkForUpdatesCheckBox.setText(
translate('OpenLP.GeneralTab', 'Check for updates to OpenLP'))
self.settingsGroupBox.setTitle(
translate('OpenLP.GeneralTab', 'Application Settings'))
self.saveCheckServiceCheckBox.setText(translate('OpenLP.GeneralTab',
@ -317,6 +323,8 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(False)).toBool())
self.showSplashCheckBox.setChecked(settings.value(u'show splash',
QtCore.QVariant(True)).toBool())
self.checkForUpdatesCheckBox.setChecked(settings.value(u'update check',
QtCore.QVariant(True)).toBool())
self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview',
QtCore.QVariant(False)).toBool())
self.timeoutSpinBox.setValue(settings.value(u'loop delay',
@ -363,6 +371,8 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(self.autoOpenCheckBox.isChecked()))
settings.setValue(u'show splash',
QtCore.QVariant(self.showSplashCheckBox.isChecked()))
settings.setValue(u'update check',
QtCore.QVariant(self.checkForUpdatesCheckBox.isChecked()))
settings.setValue(u'save prompt',
QtCore.QVariant(self.saveCheckServiceCheckBox.isChecked()))
settings.setValue(u'auto preview',

View File

@ -67,11 +67,12 @@ class MainDisplay(DisplayWidget):
self.isLive = live
self.alertTab = None
self.hideMode = None
self.override = {}
mainIcon = build_icon(u':/icon/openlp-logo-16x16.png')
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(),
@ -105,13 +106,16 @@ 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())
self.page = self.webView.page()
self.frame = self.page.mainFrame()
QtCore.QObject.connect(self.webView,
QtCore.SIGNAL(u'loadFinished(bool)'), self.isLoaded)
QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.frame.setScrollBarPolicy(QtCore.Qt.Vertical,
@ -137,14 +141,14 @@ class MainDisplay(DisplayWidget):
painter_image.begin(initialFrame)
painter_image.fillRect(initialFrame.rect(), QtCore.Qt.white)
painter_image.drawImage(
(self.screens.current[u'size'].width() -
(self.screens.current[u'size'].width() -
splash_image.width()) / 2,
(self.screens.current[u'size'].height()
- splash_image.height()) / 2, splash_image)
serviceItem = ServiceItem()
serviceItem.bg_image_bytes = image_to_byte(initialFrame)
self.webView.setHtml(build_html(serviceItem, self.screen,
self.parent.alertTab, self.isLive))
self.alertTab, self.isLive, None))
self.initialFrame = True
# To display or not to display?
if not self.screen[u'primary']:
@ -162,7 +166,7 @@ class MainDisplay(DisplayWidget):
"""
log.debug(u'text to display')
# Wait for the webview to update before displaying text.
while not self.loaded:
while not self.webLoaded:
Receiver.send_message(u'openlp_process_events')
self.frame.evaluateJavaScript(u'show_text("%s")' % \
slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"'))
@ -204,14 +208,17 @@ class MainDisplay(DisplayWidget):
"""
self.imageManager.add_image(name, path)
self.image(name)
if hasattr(self, u'serviceItem'):
self.override[u'image'] = name
self.override[u'theme'] = self.serviceItem.themedata.theme_name
def image(self, name):
"""
Add an image as the background. The image is converted to a bytestream
on route.
Add an image as the background. The image has already been added
to the cache.
`Image`
The Image to be displayed can be QImage or QPixmap
The name of the image to be displayed
"""
log.debug(u'image to display')
image = self.imageManager.get_image_bytes(name)
@ -244,6 +251,7 @@ class MainDisplay(DisplayWidget):
self.displayImage(self.serviceItem.bg_image_bytes)
else:
self.displayImage(None)
self.override = {}
# Update the preview frame.
Receiver.send_message(u'maindisplay_active')
@ -260,6 +268,7 @@ class MainDisplay(DisplayWidget):
self.phononActive = False
else:
self.frame.evaluateJavaScript(u'show_video("close");')
self.override = {}
# Update the preview frame.
Receiver.send_message(u'maindisplay_active')
@ -313,12 +322,14 @@ class MainDisplay(DisplayWidget):
Loads and starts a video to run with the option of sound
"""
log.debug(u'video')
self.loaded = True
self.webLoaded = True
# We are running a background theme
self.override[u'theme'] = u''
self.override[u'video'] = True
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
@ -333,12 +344,19 @@ class MainDisplay(DisplayWidget):
Receiver.send_message(u'maindisplay_active')
return self.preview()
def isLoaded(self):
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
"""
log.debug(u'loaded')
self.loaded = True
log.debug(u'Webloaded')
self.webLoaded = True
def preview(self):
"""
@ -357,7 +375,7 @@ class MainDisplay(DisplayWidget):
Receiver.send_message(u'openlp_process_events')
# Wait for the webview to update before geting the preview.
# Important otherwise first preview will miss the background !
while not self.loaded:
while not self.webLoaded:
Receiver.send_message(u'openlp_process_events')
# if was hidden keep it hidden
if self.isLive:
@ -379,18 +397,31 @@ class MainDisplay(DisplayWidget):
HTML to the display
"""
log.debug(u'buildHtml')
self.loaded = False
self.webLoaded = False
self.initialFrame = False
self.serviceItem = serviceItem
background = None
# We have an image override so keep the image till the theme changes
if self.override:
# We have an video override so allow it to be stopped
if u'video' in self.override:
Receiver.send_message(u'video_background_replaced')
self.override = {}
elif self.override[u'theme'] != serviceItem.themedata.theme_name:
Receiver.send_message(u'live_theme_changed')
self.override = {}
else:
background = self.imageManager. \
get_image_bytes(self.override[u'image'])
if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.imageManager. \
get_image_bytes(self.serviceItem.themedata.theme_name)
html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
self.isLive)
html = build_html(self.serviceItem, self.screen, self.alertTab,
self.isLive, background)
log.debug(u'buildHtml - pre setHtml')
self.webView.setHtml(html)
log.debug(u'buildHtml - post setHtml')
if serviceItem.foot_text and serviceItem.foot_text:
if serviceItem.foot_text:
self.footer(serviceItem.foot_text)
# if was hidden keep it hidden
if self.hideMode and self.isLive:

View File

@ -28,11 +28,13 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
SettingsManager, PluginManager, Receiver, translate
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
from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
SettingsManager, PluginManager, Receiver, translate
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
ActionList
@ -76,10 +78,10 @@ class Ui_MainWindow(object):
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)
@ -87,10 +89,10 @@ class Ui_MainWindow(object):
self.screens, True)
previewVisible = QtCore.QSettings().value(
u'user interface/preview panel', QtCore.QVariant(True)).toBool()
self.previewController.Panel.setVisible(previewVisible)
self.previewController.panel.setVisible(previewVisible)
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
QtCore.QVariant(True)).toBool()
self.liveController.Panel.setVisible(liveVisible)
self.liveController.panel.setVisible(liveVisible)
# Create menu
self.MenuBar = QtGui.QMenuBar(mainWindow)
self.MenuBar.setObjectName(u'MenuBar')
@ -101,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)
@ -124,135 +126,106 @@ class Ui_MainWindow(object):
self.DefaultThemeLabel.setObjectName(u'DefaultThemeLabel')
self.StatusBar.addPermanentWidget(self.DefaultThemeLabel)
# Create the MediaManager
self.MediaManagerDock = OpenLPDockWidget(
mainWindow, u'MediaManagerDock',
build_icon(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',
build_icon(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',
build_icon(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.themeManagerDock)
self.ThemeManagerContents.setObjectName(u'ThemeManagerContents')
self.ThemeManagerDock.setWidget(self.ThemeManagerContents)
self.themeManagerDock.setWidget(self.ThemeManagerContents)
mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea,
self.ThemeManagerDock)
self.themeManagerDock)
# Create the menu items
self.FileNewItem = QtGui.QAction(mainWindow)
self.FileNewItem.setIcon(build_icon(u':/general/general_new.png'))
self.FileNewItem.setObjectName(u'FileNewItem')
self.FileNewItem = icon_action(mainWindow, u'FileNewItem',
u':/general/general_new.png')
mainWindow.actionList.add_action(self.FileNewItem, u'File')
self.FileOpenItem = QtGui.QAction(mainWindow)
self.FileOpenItem.setIcon(build_icon(u':/general/general_open.png'))
self.FileOpenItem.setObjectName(u'FileOpenItem')
self.FileOpenItem = icon_action(mainWindow, u'FileOpenItem',
u':/general/general_open.png')
mainWindow.actionList.add_action(self.FileOpenItem, u'File')
self.FileSaveItem = QtGui.QAction(mainWindow)
self.FileSaveItem.setIcon(build_icon(u':/general/general_save.png'))
self.FileSaveItem.setObjectName(u'FileSaveItem')
self.FileSaveItem = icon_action(mainWindow, u'FileSaveItem',
u':/general/general_save.png')
mainWindow.actionList.add_action(self.FileSaveItem, u'File')
self.FileSaveAsItem = QtGui.QAction(mainWindow)
self.FileSaveAsItem.setObjectName(u'FileSaveAsItem')
self.FileSaveAsItem = base_action(mainWindow, u'FileSaveAsItem')
mainWindow.actionList.add_action(self.FileSaveAsItem, u'File')
self.FileExitItem = QtGui.QAction(mainWindow)
self.FileExitItem.setIcon(build_icon(u':/system/system_exit.png'))
self.FileExitItem.setObjectName(u'FileExitItem')
self.printServiceOrderItem = base_action(
mainWindow, u'printServiceItem')
mainWindow.actionList.add_action(
self.printServiceOrderItem, u'Print Service Order')
self.FileExitItem = icon_action(mainWindow, u'FileExitItem',
u':/system/system_exit.png')
mainWindow.actionList.add_action(self.FileExitItem, u'File')
self.ImportThemeItem = QtGui.QAction(mainWindow)
self.ImportThemeItem.setObjectName(u'ImportThemeItem')
self.ImportThemeItem = base_action(mainWindow, u'ImportThemeItem')
mainWindow.actionList.add_action(self.ImportThemeItem, u'Import')
self.ImportLanguageItem = QtGui.QAction(mainWindow)
self.ImportLanguageItem.setObjectName(u'ImportLanguageItem')
self.ImportLanguageItem = base_action(mainWindow, u'ImportLanguageItem')
mainWindow.actionList.add_action(self.ImportLanguageItem, u'Import')
self.ExportThemeItem = QtGui.QAction(mainWindow)
self.ExportThemeItem.setObjectName(u'ExportThemeItem')
self.ExportThemeItem = base_action(mainWindow, u'ExportThemeItem')
mainWindow.actionList.add_action(self.ExportThemeItem, u'Export')
self.ExportLanguageItem = QtGui.QAction(mainWindow)
self.ExportLanguageItem.setObjectName(u'ExportLanguageItem')
self.ExportLanguageItem = base_action(mainWindow, u'ExportLanguageItem')
mainWindow.actionList.add_action(self.ExportLanguageItem, u'Export')
self.ViewMediaManagerItem = QtGui.QAction(mainWindow)
self.ViewMediaManagerItem.setCheckable(True)
self.ViewMediaManagerItem.setChecked(self.MediaManagerDock.isVisible())
self.ViewMediaManagerItem.setIcon(
build_icon(u':/system/system_mediamanager.png'))
self.ViewMediaManagerItem.setObjectName(u'ViewMediaManagerItem')
self.ViewThemeManagerItem = QtGui.QAction(mainWindow)
self.ViewThemeManagerItem.setCheckable(True)
self.ViewThemeManagerItem.setChecked(self.ThemeManagerDock.isVisible())
self.ViewThemeManagerItem.setIcon(
build_icon(u':/system/system_thememanager.png'))
self.ViewThemeManagerItem.setObjectName(u'ViewThemeManagerItem')
self.ViewMediaManagerItem = icon_action(mainWindow,
u'ViewMediaManagerItem', u':/system/system_mediamanager.png',
self.mediaManagerDock.isVisible())
self.ViewThemeManagerItem = icon_action(mainWindow,
u'ViewThemeManagerItem', u':/system/system_thememanager.png',
self.themeManagerDock.isVisible())
mainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View')
self.ViewServiceManagerItem = QtGui.QAction(mainWindow)
self.ViewServiceManagerItem.setCheckable(True)
self.ViewServiceManagerItem.setChecked(
self.ServiceManagerDock.isVisible())
self.ViewServiceManagerItem.setIcon(
build_icon(u':/system/system_servicemanager.png'))
self.ViewServiceManagerItem.setObjectName(u'ViewServiceManagerItem')
self.ViewServiceManagerItem = icon_action(mainWindow,
u'ViewServiceManagerItem', u':/system/system_servicemanager.png',
self.serviceManagerDock.isVisible())
mainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View')
self.ViewPreviewPanel = QtGui.QAction(mainWindow)
self.ViewPreviewPanel.setCheckable(True)
self.ViewPreviewPanel.setChecked(previewVisible)
self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel')
self.ViewPreviewPanel = checkable_action(mainWindow,
u'ViewPreviewPanel', previewVisible)
mainWindow.actionList.add_action(self.ViewPreviewPanel, u'View')
self.ViewLivePanel = QtGui.QAction(mainWindow)
self.ViewLivePanel.setCheckable(True)
self.ViewLivePanel.setChecked(liveVisible)
self.ViewLivePanel.setObjectName(u'ViewLivePanel')
self.ViewLivePanel = checkable_action(mainWindow, u'ViewLivePanel',
liveVisible)
mainWindow.actionList.add_action(self.ViewLivePanel, u'View')
self.ModeDefaultItem = QtGui.QAction(mainWindow)
self.ModeDefaultItem.setCheckable(True)
self.ModeDefaultItem.setObjectName(u'ModeDefaultItem')
self.ModeDefaultItem = checkable_action(mainWindow, u'ModeDefaultItem')
mainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode')
self.ModeSetupItem = QtGui.QAction(mainWindow)
self.ModeSetupItem.setCheckable(True)
self.ModeSetupItem.setObjectName(u'ModeLiveItem')
self.ModeSetupItem = checkable_action(mainWindow, u'ModeLiveItem')
mainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode')
self.ModeLiveItem = QtGui.QAction(mainWindow)
self.ModeLiveItem.setCheckable(True)
self.ModeLiveItem.setObjectName(u'ModeLiveItem')
self.ModeLiveItem = checkable_action(mainWindow, u'ModeLiveItem')
mainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode')
self.ModeGroup = QtGui.QActionGroup(mainWindow)
self.ModeGroup.addAction(self.ModeDefaultItem)
self.ModeGroup.addAction(self.ModeSetupItem)
self.ModeGroup.addAction(self.ModeLiveItem)
self.ModeDefaultItem.setChecked(True)
self.ToolsAddToolItem = QtGui.QAction(mainWindow)
self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png'))
self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem')
self.ToolsAddToolItem = icon_action(mainWindow, u'ToolsAddToolItem',
u':/tools/tools_add.png')
mainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools')
self.SettingsPluginListItem = QtGui.QAction(mainWindow)
self.SettingsPluginListItem.setIcon(
build_icon(u':/system/settings_plugin_list.png'))
self.SettingsPluginListItem.setObjectName(u'SettingsPluginListItem')
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 = QtGui.QAction(mainWindow)
self.AutoLanguageItem.setObjectName(u'AutoLanguageItem')
self.AutoLanguageItem.setCheckable(True)
self.AutoLanguageItem = checkable_action(mainWindow,
u'AutoLanguageItem')
mainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings')
self.LanguageGroup = QtGui.QActionGroup(mainWindow)
self.LanguageGroup.setExclusive(True)
@ -262,39 +235,28 @@ class Ui_MainWindow(object):
qmList = LanguageManager.get_qm_list()
savedLanguage = LanguageManager.get_language()
for key in sorted(qmList.keys()):
languageItem = QtGui.QAction(mainWindow)
languageItem.setObjectName(key)
languageItem.setCheckable(True)
languageItem = checkable_action(mainWindow, key)
if qmList[key] == savedLanguage:
languageItem.setChecked(True)
add_actions(self.LanguageGroup, [languageItem])
self.SettingsShortcutsItem = QtGui.QAction(mainWindow)
self.SettingsShortcutsItem.setIcon(
build_icon(u':/system/system_configure_shortcuts.png'))
self.SettingsShortcutsItem.setObjectName(u'SettingsShortcutsItem')
self.SettingsConfigureItem = QtGui.QAction(mainWindow)
self.SettingsConfigureItem.setIcon(
build_icon(u':/system/system_settings.png'))
self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem')
self.SettingsShortcutsItem = icon_action(mainWindow,
u'SettingsShortcutsItem',
u':/system/system_configure_shortcuts.png')
self.SettingsConfigureItem = icon_action(mainWindow,
u'SettingsConfigureItem', u':/system/system_settings.png')
mainWindow.actionList.add_action(self.SettingsShortcutsItem,
u'Settings')
self.HelpDocumentationItem = QtGui.QAction(mainWindow)
self.HelpDocumentationItem.setIcon(
build_icon(u':/system/system_help_contents.png'))
self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem')
self.HelpDocumentationItem = icon_action(mainWindow,
u'HelpDocumentationItem', u':/system/system_help_contents.png')
self.HelpDocumentationItem.setEnabled(False)
mainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help')
self.HelpAboutItem = QtGui.QAction(mainWindow)
self.HelpAboutItem.setIcon(
build_icon(u':/system/system_about.png'))
self.HelpAboutItem.setObjectName(u'HelpAboutItem')
self.HelpAboutItem = icon_action(mainWindow, u'HelpAboutItem',
u':/system/system_about.png')
mainWindow.actionList.add_action(self.HelpAboutItem, u'Help')
self.HelpOnlineHelpItem = QtGui.QAction(mainWindow)
self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem')
self.HelpOnlineHelpItem = base_action(mainWindow, u'HelpOnlineHelpItem')
self.HelpOnlineHelpItem.setEnabled(False)
mainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help')
self.HelpWebSiteItem = QtGui.QAction(mainWindow)
self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem')
self.HelpWebSiteItem = base_action(mainWindow, u'HelpWebSiteItem')
mainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help')
add_actions(self.FileImportMenu,
(self.ImportThemeItem, self.ImportLanguageItem))
@ -302,26 +264,27 @@ class Ui_MainWindow(object):
(self.ExportThemeItem, self.ExportLanguageItem))
self.FileMenuActions = (self.FileNewItem, self.FileOpenItem,
self.FileSaveItem, self.FileSaveAsItem, None,
self.FileImportMenu.menuAction(), self.FileExportMenu.menuAction(),
self.FileExitItem)
self.printServiceOrderItem, None, self.FileImportMenu.menuAction(),
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))
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.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)
@ -337,39 +300,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'))
@ -381,6 +340,12 @@ 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.setStatusTip(translate('OpenLP.MainWindow',
'Print the current Service Order.'))
self.printServiceOrderItem.setShortcut(
translate('OpenLP.MainWindow', 'Ctrl+P'))
self.FileExitItem.setText(
translate('OpenLP.MainWindow', 'E&xit'))
self.FileExitItem.setStatusTip(
@ -439,11 +404,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'))
@ -468,6 +433,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',
@ -537,20 +506,22 @@ 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.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.SettingsConfigureItem,
QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked)
@ -563,10 +534,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.ServiceManagerContents.onLoadServiceClicked)
QtCore.QObject.connect(self.FileSaveItem,
QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.onSaveServiceClicked)
self.ServiceManagerContents.saveFile)
QtCore.QObject.connect(self.FileSaveAsItem,
QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.onSaveServiceAsClicked)
self.ServiceManagerContents.saveFileAs)
QtCore.QObject.connect(self.printServiceOrderItem,
QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.printServiceOrder)
# i18n set signals for languages
QtCore.QObject.connect(self.AutoLanguageItem,
QtCore.SIGNAL(u'toggled(bool)'), self.setAutoLanguage)
@ -735,6 +709,13 @@ 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 onSettingsConfigureItemClicked(self):
"""
Show the Settings dialog
@ -758,37 +739,32 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
Put OpenLP into "Default" view mode.
"""
settings = QtCore.QSettings()
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
u'default')
self.setViewMode(True, True, True, True, True)
self.setViewMode(True, True, True, True, True, u'default')
def onModeSetupItemClicked(self):
"""
Put OpenLP into "Setup" view mode.
"""
settings = QtCore.QSettings()
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
u'setup')
self.setViewMode(True, True, False, True, False)
self.setViewMode(True, True, False, True, False, u'setup')
def onModeLiveItemClicked(self):
"""
Put OpenLP into "Live" view mode.
"""
settings = QtCore.QSettings()
settings.setValue(u'%s/view mode' % self.generalSettingsSection,
u'live')
self.setViewMode(False, True, False, False, True)
self.setViewMode(False, True, False, False, True, u'live')
def setViewMode(self, media=True, service=True, theme=True, preview=True,
live=True):
live=True, mode=u''):
"""
Set OpenLP to a different view mode.
"""
self.MediaManagerDock.setVisible(media)
self.ServiceManagerDock.setVisible(service)
self.ThemeManagerDock.setVisible(theme)
if mode:
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.setPreviewPanelVisibility(preview)
self.setLivePanelVisibility(live)
@ -807,15 +783,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Hook to close the main window and display windows on exit
"""
if self.ServiceManagerContents.isModified():
ret = QtGui.QMessageBox.question(self,
translate('OpenLP.MainWindow', 'Save Changes to Service?'),
translate('OpenLP.MainWindow', 'Your service has changed. '
'Do you want to save those changes?'),
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Cancel |
QtGui.QMessageBox.Discard |
QtGui.QMessageBox.Save),
QtGui.QMessageBox.Save)
ret = self.ServiceManagerContents.saveModifiedService()
if ret == QtGui.QMessageBox.Save:
if self.ServiceManagerContents.saveFile():
self.cleanUp()
@ -847,7 +815,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.cleanUp()
event.accept()
def cleanUp(self):
"""
Runs all the cleanup code before OpenLP shuts down
@ -914,16 +881,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):
"""
@ -935,7 +902,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
True - Visible
False - Hidden
"""
self.previewController.Panel.setVisible(visible)
self.previewController.panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/preview panel',
QtCore.QVariant(visible))
self.ViewPreviewPanel.setChecked(visible)
@ -950,7 +917,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
True - Visible
False - Hidden
"""
self.liveController.Panel.setVisible(visible)
self.liveController.panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/live panel',
QtCore.QVariant(visible))
self.ViewLivePanel.setChecked(visible)
@ -1000,8 +967,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
u'advanced/recent file count', QtCore.QVariant(4)).toInt()[0]
self.FileMenu.clear()
add_actions(self.FileMenu, self.FileMenuActions[:-1])
existingRecentFiles = [file for file in self.recentFiles
if QtCore.QFile.exists(file)]
existingRecentFiles = [recentFile for recentFile in self.recentFiles
if QtCore.QFile.exists(recentFile)]
recentFilesToDisplay = existingRecentFiles[0:recentFileCount]
if recentFilesToDisplay:
self.FileMenu.addSeparator()

View File

@ -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, StringContent, 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
@ -129,7 +131,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(

View File

@ -0,0 +1,137 @@
# -*- 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, 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
class Ui_PrintServiceOrderDialog(object):
def setupUi(self, printServiceOrderDialog):
printServiceOrderDialog.setObjectName(u'printServiceOrderDialog')
self.dialogLayout = QtGui.QGridLayout(printServiceOrderDialog)
self.dialogLayout.setObjectName(u'dialogLayout')
self.perviewLayout = QtGui.QVBoxLayout()
self.perviewLayout.setObjectName(u'perviewLayout')
self.previewLabel = QtGui.QLabel(printServiceOrderDialog)
self.previewLabel.setSizePolicy(
QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
self.previewLabel.setObjectName(u'previewLabel')
self.perviewLayout.addWidget(self.previewLabel)
self.previewWidget = QtGui.QPrintPreviewWidget(
self.printer, self, QtCore.Qt.Widget)
self.previewWidget.setEnabled(True)
self.previewWidget.setSizePolicy(
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding)
self.previewWidget.setObjectName(u'previewWidget')
# Give the previewWidget a fixed size, to prevent resizing when clicking
# the zoom buttons.
self.previewWidget.setFixedWidth(350)
self.perviewLayout.addWidget(self.previewWidget)
self.dialogLayout.addLayout(self.perviewLayout, 0, 0, 1, 1)
self.settingsLayout = QtGui.QVBoxLayout()
self.settingsLayout.setObjectName(u'settingsLayout')
self.serviceTitleLayout = QtGui.QGridLayout()
self.serviceTitleLayout.setObjectName(u'serviceTitleLayout')
self.serviceTitleLineEdit = QtGui.QLineEdit(printServiceOrderDialog)
self.serviceTitleLineEdit.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
self.serviceTitleLineEdit.setObjectName(u'serviceTitleLineEdit')
self.serviceTitleLayout.addWidget(self.serviceTitleLineEdit, 1, 1, 1, 1)
self.serviceTitleLabel = QtGui.QLabel(printServiceOrderDialog)
self.serviceTitleLabel.setSizePolicy(
QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Preferred)
self.serviceTitleLabel.setObjectName(u'serviceTitleLabel')
self.serviceTitleLayout.addWidget(self.serviceTitleLabel, 1, 0, 1, 1)
self.settingsLayout.addLayout(self.serviceTitleLayout)
self.printSlideTextCheckBox = QtGui.QCheckBox(printServiceOrderDialog)
self.printSlideTextCheckBox.setObjectName(u'printSlideTextCheckBox')
self.settingsLayout.addWidget(self.printSlideTextCheckBox)
self.printNotesCheckBox = QtGui.QCheckBox(printServiceOrderDialog)
self.printNotesCheckBox.setObjectName(u'printNotesCheckBox')
self.settingsLayout.addWidget(self.printNotesCheckBox)
self.printMetaDataCheckBox = QtGui.QCheckBox(printServiceOrderDialog)
self.printMetaDataCheckBox.setObjectName(u'printMetaDataCheckBox')
self.settingsLayout.addWidget(self.printMetaDataCheckBox)
spacerItem = QtGui.QSpacerItem(20, 40,
QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.settingsLayout.addItem(spacerItem)
self.customNotesLabel = QtGui.QLabel(self)
self.customNotesLabel.setObjectName(u'customNotesLabel')
self.settingsLayout.addWidget(self.customNotesLabel)
self.customNoteEdit = SpellTextEdit(self)
self.customNoteEdit.setObjectName(u'customNoteEdit')
self.settingsLayout.addWidget(self.customNoteEdit)
self.dialogLayout.addLayout(self.settingsLayout, 0, 3, 1, 1)
self.buttonLayout = QtGui.QHBoxLayout()
self.buttonLayout.setObjectName(u'buttonLayout')
spacerItem = QtGui.QSpacerItem(40, 20,
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.buttonLayout.addItem(spacerItem)
self.cancelButton = QtGui.QPushButton(printServiceOrderDialog)
self.cancelButton.setObjectName(u'cancelButton')
self.buttonLayout.addWidget(self.cancelButton)
self.printButton = QtGui.QPushButton(printServiceOrderDialog)
self.printButton.setObjectName(u'printButton')
self.buttonLayout.addWidget(self.printButton)
self.dialogLayout.addLayout(self.buttonLayout, 1, 3, 1, 1)
self.zoomButtonLayout = QtGui.QHBoxLayout()
self.zoomButtonLayout.setObjectName(u'zoomButtonLayout')
spacerItem = QtGui.QSpacerItem(40, 20,
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.zoomButtonLayout.addItem(spacerItem)
self.zoomOutButton = QtGui.QToolButton(printServiceOrderDialog)
self.zoomOutButton.setIcon(
build_icon(u':/general/general_zoom_out.png'))
self.zoomOutButton.setObjectName(u'zoomOutButton')
self.zoomButtonLayout.addWidget(self.zoomOutButton)
self.zoomInButton = QtGui.QToolButton(printServiceOrderDialog)
self.zoomInButton.setIcon(build_icon(u':/general/general_zoom_in.png'))
self.zoomInButton.setObjectName(u'zoomInButton')
self.zoomButtonLayout.addWidget(self.zoomInButton)
self.dialogLayout.addLayout(self.zoomButtonLayout, 1, 0, 1, 1)
self.retranslateUi(printServiceOrderDialog)
QtCore.QMetaObject.connectSlotsByName(printServiceOrderDialog)
def retranslateUi(self, printServiceOrderDialog):
printServiceOrderDialog.setWindowTitle(
translate('OpenLP.PrintServiceOrderForm', 'Print Service Order'))
self.previewLabel.setText(
translate('OpenLP.ServiceManager', '<b>Preview:</b>'))
self.printSlideTextCheckBox.setText(translate(
'OpenLP.PrintServiceOrderForm', 'Include slide text if available'))
self.printNotesCheckBox.setText(translate(
'OpenLP.PrintServiceOrderForm', 'Include service item notes'))
self.printMetaDataCheckBox.setText(
translate('OpenLP.PrintServiceOrderForm',
'Include play length of media items'))
self.serviceTitleLabel.setText(translate(
'OpenLP.PrintServiceOrderForm', 'Title:'))
self.serviceTitleLineEdit.setText(translate('OpenLP.ServiceManager',
'Service Order Sheet'))
self.printButton.setText(translate('OpenLP.ServiceManager', 'Print'))
self.cancelButton.setText(translate('OpenLP.ServiceManager', 'Cancel'))
self.customNotesLabel.setText(
translate('OpenLP.ServiceManager', '<b>Custom Service Notes:</b>'))

View File

@ -0,0 +1,175 @@
# -*- 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, 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.ui.printserviceorderdialog import Ui_PrintServiceOrderDialog
class PrintServiceOrderForm(QtGui.QDialog, Ui_PrintServiceOrderDialog):
def __init__(self, parent, serviceManager):
"""
Constructor
"""
QtGui.QDialog.__init__(self, parent)
self.serviceManager = serviceManager
self.printer = QtGui.QPrinter()
self.printDialog = QtGui.QPrintDialog(self.printer, self)
self.document = QtGui.QTextDocument()
self.setupUi(self)
# Load the settings for the dialog.
settings = QtCore.QSettings()
settings.beginGroup(u'advanced')
self.printSlideTextCheckBox.setChecked(settings.value(
u'print slide text', QtCore.QVariant(False)).toBool())
self.printMetaDataCheckBox.setChecked(settings.value(
u'print file meta data', QtCore.QVariant(False)).toBool())
self.printNotesCheckBox.setChecked(settings.value(
u'print notes', QtCore.QVariant(False)).toBool())
settings.endGroup()
# Signals
QtCore.QObject.connect(self.printButton,
QtCore.SIGNAL(u'clicked()'), self.printServiceOrder)
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.previewWidget,
QtCore.SIGNAL(u'paintRequested(QPrinter *)'), self.paintRequested)
QtCore.QObject.connect(self.serviceTitleLineEdit,
QtCore.SIGNAL(u'textChanged(const QString)'),
self.updatePreviewText)
QtCore.QObject.connect(self.printSlideTextCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.updatePreviewText)
QtCore.QObject.connect(self.printNotesCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.updatePreviewText)
QtCore.QObject.connect(self.printMetaDataCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.updatePreviewText)
QtCore.QObject.connect(self.customNoteEdit,
QtCore.SIGNAL(u'textChanged()'), self.updatePreviewText)
QtCore.QObject.connect(self.cancelButton,
QtCore.SIGNAL(u'clicked()'), self.reject)
self.updatePreviewText()
def updatePreviewText(self):
"""
Creates the html text and updates the html of *self.document*.
"""
text = u''
if self.serviceTitleLineEdit.text():
text += u'<h2>%s</h2>' % unicode(self.serviceTitleLineEdit.text())
for item in self.serviceManager.serviceItems:
item = item[u'service_item']
# Add the title of the service item.
text += u'<h4><img src="%s" /> %s</h4>' % (item.icon,
item.get_display_title())
# Add slide text of the service item.
if self.printSlideTextCheckBox.isChecked():
if item.is_text():
# Add the text of the service item.
for slide in item.get_frames():
text += u'<p>' + slide[u'text'] + u'</p>'
elif item.is_image():
# Add the image names of the service item.
text += u'<ol>'
for slide in range(len(item.get_frames())):
text += u'<li><p>%s</p></li>' % \
item.get_frame_title(slide)
text += u'</ol>'
if item.foot_text:
# add footer
text += u'<p>%s</p>' % item.foot_text
# Add service items' notes.
if self.printNotesCheckBox.isChecked():
if item.notes:
text += u'<p><b>%s</b></p>%s' % (translate(
'OpenLP.ServiceManager', 'Notes:'),
item.notes.replace(u'\n', u'<br />'))
# Add play length of media files.
if item.is_media() and self.printMetaDataCheckBox.isChecked():
text += u'<p><b>%s</b> %s</p>' % (translate(
'OpenLP.ServiceManager', u'Playing time:'),
unicode(datetime.timedelta(seconds=item.media_length)))
if self.customNoteEdit.toPlainText():
text += u'<h4>%s</h4>%s' % (translate('OpenLP.ServiceManager',
u'Custom Service Notes:'), self.customNoteEdit.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 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)
self.accept()
def zoomIn(self):
"""
Called when *zoomInButton* is clicked.
"""
self.previewWidget.zoomIn()
def zoomOut(self):
"""
Called when *zoomOutButton* is clicked.
"""
self.previewWidget.zoomOut()
def accept(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.printSlideTextCheckBox.isChecked()))
settings.setValue(u'print file meta data',
QtCore.QVariant(self.printMetaDataCheckBox.isChecked()))
settings.setValue(u'print notes',
QtCore.QVariant(self.printNotesCheckBox.isChecked()))
settings.endGroup()
# Close the dialog.
return QtGui.QDialog.accept(self)
def reject(self):
"""
Close the dialog, do not print the service and do not save the settings.
"""
return QtGui.QDialog.reject(self)

View File

@ -26,7 +26,9 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, build_icon
from openlp.core.lib import translate
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):
def setupUi(self, serviceItemEditDialog):
@ -39,30 +41,19 @@ class Ui_ServiceItemEditDialog(object):
self.dialogLayout.addWidget(self.listWidget, 0, 0)
self.buttonLayout = QtGui.QVBoxLayout()
self.buttonLayout.setObjectName(u'buttonLayout')
self.deleteButton = QtGui.QPushButton(serviceItemEditDialog)
self.deleteButton.setObjectName(u'deleteButton')
self.deleteButton = create_delete_push_button(serviceItemEditDialog)
self.buttonLayout.addWidget(self.deleteButton)
self.buttonLayout.addStretch()
self.upButton = QtGui.QPushButton(serviceItemEditDialog)
self.upButton.setIcon(build_icon(u':/services/service_up.png'))
self.upButton.setObjectName(u'upButton')
self.upButton, self.downButton = create_up_down_push_button_set(
serviceItemEditDialog)
self.buttonLayout.addWidget(self.upButton)
self.downButton = QtGui.QPushButton(serviceItemEditDialog)
self.downButton.setIcon(build_icon(u':/services/service_down.png'))
self.downButton.setObjectName(u'downButton')
self.buttonLayout.addWidget(self.downButton)
self.dialogLayout.addLayout(self.buttonLayout, 0, 1)
self.buttonBox = QtGui.QDialogButtonBox(serviceItemEditDialog)
self.buttonBox.setStandardButtons(
QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Save)
self.buttonBox.setObjectName(u'buttonBox')
self.dialogLayout.addWidget(self.buttonBox, 1, 0, 1, 2)
self.dialogLayout.addWidget(
create_accept_reject_button_box(serviceItemEditDialog), 1, 0, 1, 2)
self.retranslateUi(serviceItemEditDialog)
QtCore.QMetaObject.connectSlotsByName(serviceItemEditDialog)
def retranslateUi(self, serviceItemEditDialog):
serviceItemEditDialog.setWindowTitle(
translate('OpenLP.ServiceItemEditForm', 'Reorder Service Item'))
self.deleteButton.setText(translate('OpenLP.ServiceItemEditForm',
'Delete'))

View File

@ -39,17 +39,6 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
self.itemList = []
# enable drop
QtCore.QObject.connect(self.upButton,
QtCore.SIGNAL(u'clicked()'), self.onItemUp)
QtCore.QObject.connect(self.downButton,
QtCore.SIGNAL(u'clicked()'), self.onItemDown)
QtCore.QObject.connect(self.deleteButton,
QtCore.SIGNAL(u'clicked()'), self.onItemDelete)
QtCore.QObject.connect(self.buttonBox,
QtCore.SIGNAL(u'accepted()'), self.accept)
QtCore.QObject.connect(self.buttonBox,
QtCore.SIGNAL(u'rejected()'), self.reject)
QtCore.QObject.connect(self.listWidget,
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
@ -81,7 +70,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
item_name = QtGui.QListWidgetItem(frame[u'title'])
self.listWidget.addItem(item_name)
def onItemDelete(self):
def onDeleteButtonClicked(self):
"""
Delete the current row.
"""
@ -96,33 +85,37 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
else:
self.listWidget.setCurrentRow(row)
def onItemUp(self):
def onUpButtonClicked(self):
"""
Move the current row up in the list.
"""
item = self.listWidget.currentItem()
if not item:
return
row = self.listWidget.row(item)
temp = self.itemList[row]
self.itemList.remove(self.itemList[row])
self.itemList.insert(row - 1, temp)
self.loadData()
self.listWidget.setCurrentRow(row - 1)
self.__moveItem(u'up')
def onItemDown(self):
def onDownButtonClicked(self):
"""
Move the current row down in the list
"""
self.__moveItem(u'down')
def __moveItem(self, direction=u''):
"""
Move the current item.
"""
if not direction:
return
item = self.listWidget.currentItem()
if not item:
return
row = self.listWidget.row(item)
temp = self.itemList[row]
self.itemList.remove(self.itemList[row])
self.itemList.insert(row + 1, temp)
if direction == u'up':
row -= 1
else:
row += 1
self.itemList.insert(row, temp)
self.loadData()
self.listWidget.setCurrentRow(row + 1)
self.listWidget.setCurrentRow(row)
def onCurrentRowChanged(self, row):
"""

View File

@ -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__)
@ -36,8 +35,9 @@ 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.ui import criticalErrorMessageBox, ServiceNoteForm, \
ServiceItemEditForm
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui import ServiceNoteForm, ServiceItemEditForm, StartTimeForm
from openlp.core.ui.printserviceorderform import PrintServiceOrderForm
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,20 +96,16 @@ 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.onSaveServiceClicked)
self.saveFile)
self.toolbar.addSeparator()
self.themeLabel = QtGui.QLabel(translate('OpenLP.ServiceManager',
'Theme:'), self)
@ -178,8 +175,8 @@ class ServiceManager(QtGui.QWidget):
translate('OpenLP.ServiceManager', 'Move &down'),
None,
translate('OpenLP.ServiceManager',
'Moves the selection up the window.'),
self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Up)
'Moves the selection down the window.'),
self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Down)
self.serviceManagerList.down.setVisible(False)
self.serviceManagerList.up = self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', 'Move up'),
@ -270,16 +267,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)
@ -361,12 +361,7 @@ class ServiceManager(QtGui.QWidget):
Create a new service.
"""
if self.isModified():
result = QtGui.QMessageBox.question(self.mainwindow,
translate('OpenLP.ServiceManager', 'Save Changes'),
translate('OpenLP.ServiceManager', 'The current service has '
'been modified, would you like to save it?'),
QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard |
QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save)
result = self.saveModifiedService()
if result == QtGui.QMessageBox.Cancel:
return False
elif result == QtGui.QMessageBox.Save:
@ -376,12 +371,7 @@ class ServiceManager(QtGui.QWidget):
def onLoadServiceClicked(self):
if self.isModified():
result = QtGui.QMessageBox.question(self.mainwindow,
translate('OpenLP.ServiceManager', 'Save Changes'),
translate('OpenLP.ServiceManager', 'The current service has '
'been modified, would you like to save it?'),
QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard |
QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save)
result = self.saveModifiedService()
if result == QtGui.QMessageBox.Cancel:
return False
elif result == QtGui.QMessageBox.Save:
@ -397,11 +387,13 @@ class ServiceManager(QtGui.QWidget):
split_filename(fileName)[0])
self.loadFile(fileName)
def onSaveServiceClicked(self):
self.saveFile()
def onSaveServiceAsClicked(self):
self.saveFileAs()
def saveModifiedService(self):
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?'),
QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard |
QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save)
def onRecentServiceClicked(self):
sender = self.sender()
@ -469,11 +461,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)')))
@ -499,7 +491,7 @@ class ServiceManager(QtGui.QWidget):
for file in zip.namelist():
ucsfile = file_is_unicode(file)
if not ucsfile:
criticalErrorMessageBox(
critical_error_message_box(
message=translate('OpenLP.ServiceManager',
'File is not a valid service.\n'
'The content encoding is not UTF-8.'))
@ -514,6 +506,7 @@ class ServiceManager(QtGui.QWidget):
if filePath.endswith(u'osd'):
p_file = filePath
if 'p_file' in locals():
Receiver.send_message(u'cursor_busy')
fileTo = open(p_file, u'r')
items = cPickle.load(fileTo)
fileTo.close()
@ -528,13 +521,14 @@ class ServiceManager(QtGui.QWidget):
Receiver.send_message(u'%s_service_load' %
serviceItem.name.lower(), serviceItem)
delete_file(p_file)
Receiver.send_message(u'cursor_normal')
else:
criticalErrorMessageBox(
critical_error_message_box(
message=translate('OpenLP.ServiceManager',
'File is not a valid service.'))
log.exception(u'File contains no service data')
except (IOError, NameError):
log.exception(u'Problem loading a service file')
log.exception(u'Problem loading service file %s' % fileName)
finally:
if fileTo:
fileTo.close()
@ -544,9 +538,7 @@ class ServiceManager(QtGui.QWidget):
self.mainwindow.addRecentFile(fileName)
self.setModified(False)
QtCore.QSettings(). \
setValue(u'service/last file',QtCore.QVariant(fileName))
# Refresh Plugin lists
Receiver.send_message(u'plugin_list_refresh')
setValue(u'service/last file', QtCore.QVariant(fileName))
def loadLastFile(self):
"""
@ -571,6 +563,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)
@ -579,6 +572,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)
@ -591,6 +587,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:
@ -603,7 +601,17 @@ class ServiceManager(QtGui.QWidget):
if self.serviceNoteForm.exec_():
self.serviceItems[item][u'service_item'].notes = \
self.serviceNoteForm.textEdit.toPlainText()
self.repaintServiceList(item, 0)
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]
@ -615,8 +623,7 @@ class ServiceManager(QtGui.QWidget):
def nextItem(self):
"""
Called by the SlideController to select the
next service item
Called by the SlideController to select the next service item.
"""
if len(self.serviceManagerList.selectedItems()) == 0:
return
@ -634,8 +641,7 @@ class ServiceManager(QtGui.QWidget):
def previousItem(self):
"""
Called by the SlideController to select the
previous service item
Called by the SlideController to select the previous service item.
"""
if len(self.serviceManagerList.selectedItems()) == 0:
return
@ -654,13 +660,13 @@ class ServiceManager(QtGui.QWidget):
def onSetItem(self, message):
"""
Called by a signal to select a specific item
Called by a signal to select a specific item.
"""
self.setItem(int(message[0]))
def setItem(self, index):
"""
Makes a specific item in the service live
Makes a specific item in the service live.
"""
if index >= 0 and index < self.serviceManagerList.topLevelItemCount:
item = self.serviceManagerList.topLevelItem(index)
@ -669,8 +675,7 @@ class ServiceManager(QtGui.QWidget):
def onMoveSelectionUp(self):
"""
Moves the selection up the window
Called by the up arrow
Moves the selection up the window. Called by the up arrow.
"""
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
tempItem = None
@ -695,8 +700,7 @@ class ServiceManager(QtGui.QWidget):
def onMoveSelectionDown(self):
"""
Moves the selection down the window
Called by the down arrow
Moves the selection down the window. Called by the down arrow.
"""
serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList)
firstItem = None
@ -718,7 +722,7 @@ class ServiceManager(QtGui.QWidget):
def onCollapseAll(self):
"""
Collapse all the service items
Collapse all the service items.
"""
for item in self.serviceItems:
item[u'expanded'] = False
@ -726,15 +730,15 @@ class ServiceManager(QtGui.QWidget):
def collapsed(self, item):
"""
Record if an item is collapsed
Used when repainting the list to get the correct state
Record if an item is collapsed. Used when repainting the list to get the
correct state.
"""
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
self.serviceItems[pos -1 ][u'expanded'] = False
def onExpandAll(self):
"""
Collapse all the service items
Collapse all the service items.
"""
for item in self.serviceItems:
item[u'expanded'] = True
@ -742,70 +746,68 @@ class ServiceManager(QtGui.QWidget):
def expanded(self, item):
"""
Record if an item is collapsed
Used when repainting the list to get the correct state
Record if an item is collapsed. Used when repainting the list to get the
correct state.
"""
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
self.serviceItems[pos -1 ][u'expanded'] = True
def onServiceTop(self):
"""
Move the current ServiceItem to the top of the list
Move the current ServiceItem to the top of the list.
"""
item, count = self.findServiceItem()
item, child = self.findServiceItem()
if item < len(self.serviceItems) and item is not -1:
temp = self.serviceItems[item]
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(0, temp)
self.repaintServiceList(0, count)
self.repaintServiceList(0, child)
self.setModified(True)
def onServiceUp(self):
"""
Move the current ServiceItem up in the list
Note move up means move to top of area ie 0.
Move the current ServiceItem one position up in the list.
"""
item, count = self.findServiceItem()
item, child = self.findServiceItem()
if item > 0:
temp = self.serviceItems[item]
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(item - 1, temp)
self.repaintServiceList(item - 1, count)
self.repaintServiceList(item - 1, child)
self.setModified(True)
def onServiceDown(self):
"""
Move the current ServiceItem down in the list
Note move down means move to bottom of area i.e len().
Move the current ServiceItem one position down in the list.
"""
item, count = self.findServiceItem()
item, child = self.findServiceItem()
if item < len(self.serviceItems) and item is not -1:
temp = self.serviceItems[item]
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(item + 1, temp)
self.repaintServiceList(item + 1, count)
self.repaintServiceList(item + 1, child)
self.setModified(True)
def onServiceEnd(self):
"""
Move the current ServiceItem to the bottom of the list
Move the current ServiceItem to the bottom of the list.
"""
item, count = self.findServiceItem()
item, child = self.findServiceItem()
if item < len(self.serviceItems) and item is not -1:
temp = self.serviceItems[item]
self.serviceItems.remove(self.serviceItems[item])
self.serviceItems.insert(len(self.serviceItems), temp)
self.repaintServiceList(len(self.serviceItems) - 1, count)
self.repaintServiceList(len(self.serviceItems) - 1, child)
self.setModified(True)
def onDeleteFromService(self):
"""
Remove the current ServiceItem from the list
Remove the current ServiceItem from the list.
"""
item = self.findServiceItem()[0]
if item is not -1:
if item != -1:
self.serviceItems.remove(self.serviceItems[item])
self.repaintServiceList(0, 0)
self.repaintServiceList(item - 1, -1)
self.setModified(True)
def repaintServiceList(self, serviceItem, serviceItemChild):
@ -847,7 +849,7 @@ class ServiceManager(QtGui.QWidget):
else:
treewidgetitem.setIcon(0,
build_icon(u':/general/general_delete.png'))
treewidgetitem.setText(0, serviceitem.title)
treewidgetitem.setText(0, serviceitem.get_display_title())
treewidgetitem.setToolTip(0, serviceitem.notes)
treewidgetitem.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(item[u'order']))
@ -857,6 +859,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)
@ -867,16 +874,16 @@ class ServiceManager(QtGui.QWidget):
def validateItem(self, serviceItem):
"""
Validates the service item and if the suffix matches an accepted
one it allows the item to be displayed
one it allows the item to be displayed.
"""
if serviceItem.is_command():
type = serviceItem._raw_frames[0][u'title'].split(u'.')[1]
type = serviceItem._raw_frames[0][u'title'].split(u'.')[-1]
if type not in self.suffixes:
serviceItem.is_valid = False
def cleanUp(self):
"""
Empties the servicePath of temporary files
Empties the servicePath of temporary files.
"""
for file in os.listdir(self.servicePath):
file_path = os.path.join(self.servicePath, file)
@ -884,7 +891,7 @@ class ServiceManager(QtGui.QWidget):
def onThemeComboBoxSelected(self, currentIndex):
"""
Set the theme for the current service
Set the theme for the current service.
"""
log.debug(u'onThemeComboBoxSelected')
self.service_theme = unicode(self.themeComboBox.currentText())
@ -967,12 +974,12 @@ class ServiceManager(QtGui.QWidget):
# if not passed set to config value
if expand is None:
expand = self.expandTabs
sitem = self.findServiceItem()[0]
item.render()
if replace:
sitem, child = self.findServiceItem()
item.merge(self.serviceItems[sitem][u'service_item'])
self.serviceItems[sitem][u'service_item'] = item
self.repaintServiceList(sitem, 0)
self.repaintServiceList(sitem, child)
self.mainwindow.liveController.replaceServiceManagerItem(item)
else:
# nothing selected for dnd
@ -981,17 +988,17 @@ class ServiceManager(QtGui.QWidget):
for inditem in item:
self.serviceItems.append({u'service_item': inditem,
u'order': len(self.serviceItems) + 1,
u'expanded':expand})
u'expanded': expand})
else:
self.serviceItems.append({u'service_item': item,
u'order': len(self.serviceItems) + 1,
u'expanded':expand})
self.repaintServiceList(len(self.serviceItems) + 1, 0)
u'expanded': expand})
self.repaintServiceList(len(self.serviceItems) - 1, -1)
else:
self.serviceItems.insert(self.dropPosition,
{u'service_item': item, u'order': self.dropPosition,
u'expanded':expand})
self.repaintServiceList(self.dropPosition, 0)
u'expanded': expand})
self.repaintServiceList(self.dropPosition, -1)
# if rebuilding list make sure live is fixed.
if rebuild:
self.mainwindow.liveController.replaceServiceManagerItem(item)
@ -1002,15 +1009,15 @@ class ServiceManager(QtGui.QWidget):
"""
Send the current item to the Preview slide controller
"""
item, count = self.findServiceItem()
item, child = self.findServiceItem()
if self.serviceItems[item][u'service_item'].is_valid:
self.mainwindow.previewController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], count)
self.serviceItems[item][u'service_item'], child)
else:
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ServiceManager', 'Missing Display Handler'),
translate('OpenLP.ServiceManager', 'Your item cannot be '
'displayed as there is no handler to display it'))
'displayed as there is no handler to display it'))
def getServiceItem(self):
"""
@ -1026,10 +1033,10 @@ class ServiceManager(QtGui.QWidget):
"""
Send the current item to the Live slide controller
"""
item, count = self.findServiceItem()
item, child = self.findServiceItem()
if self.serviceItems[item][u'service_item'].is_valid:
self.mainwindow.liveController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], count)
self.serviceItems[item][u'service_item'], child)
if QtCore.QSettings().value(
self.mainwindow.generalSettingsSection + u'/auto preview',
QtCore.QVariant(False)).toBool():
@ -1041,7 +1048,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems[item][u'service_item'], 0)
self.mainwindow.liveController.previewListWidget.setFocus()
else:
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ServiceManager', 'Missing Display Handler'),
translate('OpenLP.ServiceManager', 'Your item cannot be '
'displayed as the plugin required to display it is missing '
@ -1060,26 +1067,26 @@ class ServiceManager(QtGui.QWidget):
def findServiceItem(self):
"""
Finds a ServiceItem in the list and returns the position of the
serviceitem and its selected child item. For example, if the third child
item (in the Slidecontroller known as slide) in the second service item
is selected this will return::
Finds the selected ServiceItem in the list and returns the position of
the serviceitem and its selected child item. For example, if the third
child item (in the Slidecontroller known as slide) in the second service
item is selected this will return::
(1, 2)
"""
items = self.serviceManagerList.selectedItems()
pos = 0
count = -1
serviceItem = 0
serviceItemChild = -1
for item in items:
parentitem = item.parent()
if parentitem is None:
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
serviceItem = item.data(0, QtCore.Qt.UserRole).toInt()[0]
else:
pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
count = item.data(0, QtCore.Qt.UserRole).toInt()[0]
# adjust for zero based arrays
pos = pos - 1
return pos, count
serviceItem = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
serviceItemChild = item.data(0, QtCore.Qt.UserRole).toInt()[0]
# Adjust for zero based arrays.
serviceItem -= 1
return serviceItem, serviceItemChild
def dragEnterEvent(self, event):
"""
@ -1105,7 +1112,7 @@ class ServiceManager(QtGui.QWidget):
item = self.serviceManagerList.itemAt(event.pos())
# ServiceManager started the drag and drop
if plugin == u'ServiceManager':
startpos, startCount = self.findServiceItem()
startpos, child = self.findServiceItem()
# If no items selected
if startpos == -1:
return
@ -1116,7 +1123,7 @@ class ServiceManager(QtGui.QWidget):
serviceItem = self.serviceItems[startpos]
self.serviceItems.remove(serviceItem)
self.serviceItems.insert(endpos, serviceItem)
self.repaintServiceList(endpos, startCount)
self.repaintServiceList(endpos, child)
else:
# we are not over anything so drop
replace = False
@ -1182,17 +1189,24 @@ class ServiceManager(QtGui.QWidget):
def listRequest(self, message=None):
data = []
curindex = self.findServiceItem()[0]
if curindex >= 0 and curindex < len(self.serviceItems):
curitem = self.serviceItems[curindex]
item = self.findServiceItem()[0]
if item >= 0 and item < len(self.serviceItems):
curitem = self.serviceItems[item]
else:
curitem = None
for item in self.serviceItems:
service_item = item[u'service_item']
data_item = {}
data_item[u'title'] = unicode(service_item.title)
data_item[u'title'] = unicode(service_item.get_display_title())
data_item[u'plugin'] = unicode(service_item.name)
data_item[u'notes'] = unicode(service_item.notes)
data_item[u'selected'] = (item == curitem)
data.append(data_item)
Receiver.send_message(u'servicemanager_list_response', data)
def printServiceOrder(self):
"""
Print a Service Order Sheet.
"""
settingDialog = PrintServiceOrderForm(self.mainwindow, self)
settingDialog.exec_()

View File

@ -26,9 +26,10 @@
from PyQt4 import QtCore, QtGui
from servicenotedialog import Ui_ServiceNoteEdit
from openlp.core.lib import translate
from openlp.core.lib.ui import create_accept_reject_button_box
class ServiceNoteForm(QtGui.QDialog, Ui_ServiceNoteEdit):
class ServiceNoteForm(QtGui.QDialog):
"""
This is the form that is used to edit the verses of the song.
"""
@ -37,8 +38,19 @@ class ServiceNoteForm(QtGui.QDialog, Ui_ServiceNoteEdit):
Constructor
"""
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
self.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
self.reject)
self.setupUi()
self.retranslateUi()
def setupUi(self):
self.setObjectName(u'serviceNoteEdit')
self.dialogLayout = QtGui.QVBoxLayout(self)
self.dialogLayout.setObjectName(u'verticalLayout')
self.textEdit = QtGui.QTextEdit(self)
self.textEdit.setObjectName(u'textEdit')
self.dialogLayout.addWidget(self.textEdit)
self.dialogLayout.addWidget(create_accept_reject_button_box(self))
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self):
self.setWindowTitle(
translate('OpenLP.ServiceNoteForm', 'Service Item Notes'))

View File

@ -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):

View File

@ -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(

View File

@ -95,8 +95,13 @@ 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)

View File

@ -30,9 +30,10 @@ import os
from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon
from openlp.core.ui import HideMode, MainDisplay
from openlp.core.lib import OpenLPToolbar, Receiver, resize_image, \
ItemCapabilities, translate
from openlp.core.lib.ui import UiStrings, shortcut_action
from openlp.core.ui import HideMode, MainDisplay
log = logging.getLogger(__name__)
@ -77,28 +78,27 @@ 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)
self.panelLayout = QtGui.QVBoxLayout(self.panel)
self.panelLayout.setSpacing(0)
self.panelLayout.setMargin(0)
# Type label for the top of the slide controller
self.typeLabel = QtGui.QLabel(self.Panel)
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;')
self.typeLabel.setAlignment(QtCore.Qt.AlignCenter)
self.panelLayout.addWidget(self.typeLabel)
# Splitter
self.splitter = QtGui.QSplitter(self.Panel)
self.splitter = QtGui.QSplitter(self.panel)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.panelLayout.addWidget(self.splitter)
# Actual controller section
@ -119,6 +119,8 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.isLive = self.isLive
self.previewListWidget.setObjectName(u'PreviewListWidget')
self.previewListWidget.setSelectionBehavior(1)
self.previewListWidget.setSelectionMode(
QtGui.QAbstractItemView.SingleSelection)
self.previewListWidget.setEditTriggers(
QtGui.QAbstractItemView.NoEditTriggers)
self.previewListWidget.setHorizontalScrollBarPolicy(
@ -176,29 +178,33 @@ 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)
self.DelaySpinBox = QtGui.QSpinBox()
self.DelaySpinBox.setMinimum(1)
self.DelaySpinBox.setMaximum(180)
self.toolbar.addToolbarWidget(u'Image SpinBox', self.DelaySpinBox)
self.DelaySpinBox.setSuffix(translate('OpenLP.SlideController',
self.delaySpinBox = QtGui.QSpinBox()
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.setToolTip(translate('OpenLP.SlideController',
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'),
@ -315,18 +321,8 @@ class SlideController(QtGui.QWidget):
self.mediabar.setVisible(False)
if self.isLive:
self.setLiveHotkeys(self)
self.previewListWidget.addActions(
[self.previousItem,
self.nextItem,
self.previousService,
self.nextService,
self.escapeItem])
self.display.addActions(
[self.previousItem,
self.nextItem,
self.previousService,
self.nextService,
self.escapeItem])
self.__addActionsToWidget(self.previewListWidget)
self.__addActionsToWidget(self.display)
else:
self.setPreviewHotkeys()
self.previewListWidget.addActions(
@ -384,32 +380,21 @@ 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')
self.previousService = QtGui.QAction(translate(
'OpenLP.SlideController', 'Previous Service'), parent)
self.previousService.setShortcuts([QtCore.Qt.Key_Left, 0])
self.previousService.setShortcutContext(
QtCore.Qt.WidgetWithChildrenShortcut)
QtCore.QObject.connect(self.previousService,
QtCore.SIGNAL(u'triggered()'), self.servicePrevious)
self.previousService = shortcut_action(parent,
translate('OpenLP.SlideController', 'Previous Service'),
[QtCore.Qt.Key_Left, 0], self.servicePrevious)
actionList.add_action(self.previousService, u'Live')
self.nextService = QtGui.QAction(translate(
'OpenLP.SlideController', 'Next Service'), parent)
self.nextService.setShortcuts([QtCore.Qt.Key_Right, 0])
self.nextService.setShortcutContext(
QtCore.Qt.WidgetWithChildrenShortcut)
QtCore.QObject.connect(self.nextService,
QtCore.SIGNAL(u'triggered()'), self.serviceNext)
self.nextService = shortcut_action(parent,
translate('OpenLP.SlideController', 'Next Service'),
[QtCore.Qt.Key_Right, 0], self.serviceNext)
actionList.add_action(self.nextService, u'Live')
self.escapeItem = QtGui.QAction(translate(
'OpenLP.SlideController', 'Escape Item'), parent)
self.escapeItem.setShortcuts([QtCore.Qt.Key_Escape, 0])
self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut)
QtCore.QObject.connect(self.escapeItem,
QtCore.SIGNAL(u'triggered()'), self.liveEscape)
self.escapeItem = shortcut_action(parent,
translate('OpenLP.SlideController', 'Escape Item'),
[QtCore.Qt.Key_Escape, 0], self.liveEscape)
actionList.add_action(self.escapeItem, u'Live')
def liveEscape(self):
@ -433,12 +418,7 @@ class SlideController(QtGui.QWidget):
self.display.alertTab = self.alertTab
self.display.setup()
if self.isLive:
self.display.addActions(
[self.previousItem,
self.nextItem,
self.previousService,
self.nextService,
self.escapeItem])
self.__addActionsToWidget(self.display)
# The SlidePreview's ratio.
self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height())
@ -446,6 +426,12 @@ class SlideController(QtGui.QWidget):
if self.serviceItem:
self.refreshServiceItem()
def __addActionsToWidget(self, widget):
widget.addActions([
self.previousItem, self.nextItem,
self.previousService, self.nextService,
self.escapeItem])
def previewSizeChanged(self):
"""
Takes care of the SlidePreview's size. Is called when one of the the
@ -472,7 +458,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)
@ -480,18 +466,11 @@ class SlideController(QtGui.QWidget):
def onSongBarHandler(self):
request = unicode(self.sender().text())
slideno = self.slideList[request]
if slideno > self.previewListWidget.rowCount():
self.previewListWidget.selectRow(
self.previewListWidget.rowCount() - 1)
else:
if slideno + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(slideno + 1, 0))
self.previewListWidget.selectRow(slideno)
self.__updatePreviewSelection(slideno)
self.onSlideSelected()
def receiveSpinDelay(self, value):
self.DelaySpinBox.setValue(int(value))
self.delaySpinBox.setValue(int(value))
def enableToolBar(self, item):
"""
@ -580,10 +559,7 @@ class SlideController(QtGui.QWidget):
slideno = 0
# If service item is the same as the current on only change slide
if item.__eq__(self.serviceItem):
if slideno + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(slideno + 1, 0))
self.previewListWidget.selectRow(slideno)
self.__checkUpdateSelectedSlide(slideno)
self.onSlideSelected()
return
self._processItem(item, slideno)
@ -611,7 +587,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)
@ -663,14 +639,7 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.resizeRowsToContents()
self.previewListWidget.setColumnWidth(0,
self.previewListWidget.viewport().size().width())
if slideno > self.previewListWidget.rowCount():
self.previewListWidget.selectRow(
self.previewListWidget.rowCount() - 1)
else:
if slideno + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(slideno + 1, 0))
self.previewListWidget.selectRow(slideno)
self.__updatePreviewSelection(slideno)
self.enableToolBar(serviceItem)
# Pass to display for viewing
self.display.buildHtml(self.serviceItem)
@ -681,6 +650,16 @@ class SlideController(QtGui.QWidget):
Receiver.send_message(u'slidecontroller_%s_started' % self.typePrefix,
[serviceItem])
def __updatePreviewSelection(self, slideno):
"""
Utility method to update the selected slide in the list.
"""
if slideno > self.previewListWidget.rowCount():
self.previewListWidget.selectRow(
self.previewListWidget.rowCount() - 1)
else:
self.__checkUpdateSelectedSlide(slideno)
def onTextRequest(self):
"""
Return the text for the current item in controller
@ -728,10 +707,7 @@ class SlideController(QtGui.QWidget):
[self.serviceItem, self.isLive, index])
self.updatePreview()
else:
if index + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(index + 1, 0))
self.previewListWidget.selectRow(index)
self.__checkUpdateSelectedSlide(index)
self.onSlideSelected()
def mainDisplaySetBackground(self):
@ -890,10 +866,7 @@ class SlideController(QtGui.QWidget):
"""
The slide has been changed. Update the slidecontroller accordingly
"""
if row + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(row + 1, 0))
self.previewListWidget.selectRow(row)
self.__checkUpdateSelectedSlide(row)
self.updatePreview()
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
row)
@ -904,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)
@ -944,10 +918,7 @@ class SlideController(QtGui.QWidget):
else:
Receiver.send_message('servicemanager_next_item')
return
if row + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(row + 1, 0))
self.previewListWidget.selectRow(row)
self.__checkUpdateSelectedSlide(row)
self.onSlideSelected()
def onSlideSelectedPreviousNoloop(self):
@ -970,12 +941,15 @@ class SlideController(QtGui.QWidget):
row = self.previewListWidget.rowCount() - 1
else:
row = 0
if row + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(row + 1, 0))
self.previewListWidget.selectRow(row)
self.__checkUpdateSelectedSlide(row)
self.onSlideSelected()
def __checkUpdateSelectedSlide(self, row):
if row + 1 < self.previewListWidget.rowCount():
self.previewListWidget.scrollToItem(
self.previewListWidget.item(row + 1, 0))
self.previewListWidget.selectRow(row)
def onSlideSelectedLast(self):
"""
Go to the last slide.
@ -997,7 +971,7 @@ class SlideController(QtGui.QWidget):
"""
if self.previewListWidget.rowCount() > 1:
self.timer_id = self.startTimer(
int(self.DelaySpinBox.value()) * 1000)
int(self.delaySpinBox.value()) * 1000)
self.toolbar.actions[u'Stop Loop'].setVisible(True)
self.toolbar.actions[u'Start Loop'].setVisible(False)

View File

@ -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, 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 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(translate('OpenLP.StartTimeForm', 's'))
self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:'))
self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:'))

View File

@ -24,25 +24,29 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
from PyQt4 import QtGui
class Ui_ServiceNoteEdit(object):
def setupUi(self, serviceNoteEdit):
serviceNoteEdit.setObjectName(u'serviceNoteEdit')
self.dialogLayout = QtGui.QVBoxLayout(serviceNoteEdit)
self.dialogLayout.setObjectName(u'verticalLayout')
self.textEdit = QtGui.QTextEdit(serviceNoteEdit)
self.textEdit.setObjectName(u'textEdit')
self.dialogLayout.addWidget(self.textEdit)
self.buttonBox = QtGui.QDialogButtonBox(serviceNoteEdit)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
QtGui.QDialogButtonBox.Save)
self.buttonBox.setObjectName(u'buttonBox')
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(serviceNoteEdit)
QtCore.QMetaObject.connectSlotsByName(serviceNoteEdit)
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)
def retranslateUi(self, serviceNoteEdit):
serviceNoteEdit.setWindowTitle(
translate('OpenLP.ServiceNoteForm', 'Service Item Notes'))

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, BackgroundType, BackgroundGradientType, \
Receiver
from openlp.core.ui import criticalErrorMessageBox
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.utils import get_images_filter
from themewizard import Ui_ThemeWizard
@ -55,7 +55,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.thememanager = parent
self.setupUi(self)
self.registerFields()
self.accepted = False
self.updateThemeAllowed = True
QtCore.QObject.connect(self.backgroundComboBox,
QtCore.SIGNAL(u'currentIndexChanged(int)'),
@ -120,14 +119,12 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
QtCore.QObject.connect(self.mainFontComboBox,
QtCore.SIGNAL(u'activated(int)'),
self.calculateLines)
QtCore.QObject.connect(self, QtCore.SIGNAL(u'accepted()'), self.accept)
def setDefaults(self):
"""
Set up display at start of theme edit.
"""
self.restart()
self.accepted = False
self.setBackgroundPageValues()
self.setMainAreaPageValues()
self.setFooterAreaPageValues()
@ -250,37 +247,43 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
"""
Change state as Outline check box changed
"""
if state == QtCore.Qt.Checked:
self.theme.font_main_outline = True
else:
self.theme.font_main_outline = False
self.outlineColorButton.setEnabled(self.theme.font_main_outline)
self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline)
self.calculateLines()
if self.updateThemeAllowed:
if state == QtCore.Qt.Checked:
self.theme.font_main_outline = True
else:
self.theme.font_main_outline = False
self.outlineColorButton.setEnabled(self.theme.font_main_outline)
self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline)
self.calculateLines()
def onShadowCheckCheckBoxStateChanged(self, state):
"""
Change state as Shadow check box changed
"""
if state == QtCore.Qt.Checked:
self.theme.font_main_shadow = True
else:
self.theme.font_main_shadow = False
self.shadowColorButton.setEnabled(self.theme.font_main_shadow)
self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow)
self.calculateLines()
if self.updateThemeAllowed:
if state == QtCore.Qt.Checked:
self.theme.font_main_shadow = True
else:
self.theme.font_main_shadow = False
self.shadowColorButton.setEnabled(self.theme.font_main_shadow)
self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow)
self.calculateLines()
def onMainPositionCheckBoxStateChanged(self, value):
"""
Change state as Main Area Position check box changed
NOTE the font_main_override is the inverse of the check box value
"""
self.theme.font_main_override = (value == QtCore.Qt.Checked)
if self.updateThemeAllowed:
self.theme.font_main_override = not (value == QtCore.Qt.Checked)
def onFooterPositionCheckBoxStateChanged(self, value):
"""
Change state as Footer Area Position check box changed
NOTE the font_footer_override is the inverse of the check box value
"""
self.theme.font_footer_override = (value == QtCore.Qt.Checked)
if self.updateThemeAllowed:
self.theme.font_footer_override = not (value == QtCore.Qt.Checked)
def exec_(self, edit=False):
"""
@ -446,9 +449,10 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
"""
Background gradient Combo box has changed.
"""
self.theme.background_direction = \
BackgroundGradientType.to_string(index)
self.setBackgroundPageValues()
if self.updateThemeAllowed:
self.theme.background_direction = \
BackgroundGradientType.to_string(index)
self.setBackgroundPageValues()
def onColorButtonClicked(self):
"""
@ -479,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)
@ -560,21 +564,16 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
"""
Lets save the them as Finish has been pressed
"""
# Some reason getting double submission.
# Hack to stop it for now.
if self.accepted:
return
# Save the theme name
self.theme.theme_name = \
unicode(self.field(u'name').toString())
self.theme.theme_name = unicode(self.field(u'name').toString())
if not self.theme.theme_name:
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ThemeForm', 'Theme Name Missing'),
translate('OpenLP.ThemeForm',
'There is no name for this theme. Please enter one.'))
return
if self.theme.theme_name == u'-1' or self.theme.theme_name == u'None':
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ThemeForm', 'Theme Name Invalid'),
translate('OpenLP.ThemeForm',
'Invalid theme name. Please enter one.'))
@ -590,7 +589,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
if not self.edit_mode and \
not self.thememanager.checkIfThemeExists(self.theme.theme_name):
return
self.accepted = True
self.thememanager.saveTheme(self.theme, saveFrom, saveTo)
return QtGui.QDialog.accept(self)

View File

@ -32,11 +32,13 @@ import logging
from xml.etree.ElementTree import ElementTree, XML
from PyQt4 import QtCore, QtGui
from openlp.core.ui import criticalErrorMessageBox, FileRenameForm, ThemeForm
from openlp.core.theme import Theme
from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \
build_icon, Receiver, SettingsManager, translate, check_item_selected, \
BackgroundType, BackgroundGradientType, check_directory_exists
BackgroundType, BackgroundGradientType, check_directory_exists, \
VerticalType
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, \
get_filesystem_encoding
@ -240,7 +242,7 @@ class ThemeManager(QtGui.QWidget):
QtCore.QVariant(self.global_theme))
Receiver.send_message(u'theme_update_global',
self.global_theme)
self.pushThemes()
self._pushThemes()
def onAddTheme(self):
"""
@ -259,7 +261,7 @@ class ThemeManager(QtGui.QWidget):
'You must select a theme to rename.')),
unicode(translate('OpenLP.ThemeManager', 'Rename Confirmation')),
unicode(translate('OpenLP.ThemeManager', 'Rename %s theme?')),
False):
False, False):
item = self.themeListWidget.currentItem()
oldThemeName = unicode(item.data(QtCore.Qt.UserRole).toString())
self.fileRenameForm.fileNameEdit.setText(oldThemeName)
@ -267,11 +269,12 @@ class ThemeManager(QtGui.QWidget):
newThemeName = unicode(self.fileRenameForm.fileNameEdit.text())
if self.checkIfThemeExists(newThemeName):
oldThemeData = self.getThemeData(oldThemeName)
self.deleteTheme(oldThemeName)
self.cloneThemeData(oldThemeData, newThemeName)
self.deleteTheme(oldThemeName)
for plugin in self.mainwindow.pluginManager.plugins:
if plugin.usesTheme(oldThemeName):
plugin.renameTheme(oldThemeName, newThemeName)
self.loadThemes()
def onCopyTheme(self):
"""
@ -299,6 +302,7 @@ class ThemeManager(QtGui.QWidget):
os.path.split(unicode(themeData.background_filename))[1])
saveFrom = themeData.background_filename
themeData.theme_name = newThemeName
themeData.extend_image_filename(self.path)
self.saveTheme(themeData, saveFrom, saveTo)
def onEditTheme(self):
@ -310,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':
@ -331,6 +334,9 @@ 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. Reload the
# list as the internal lists and events need to be triggered.
self._pushThemes()
def deleteTheme(self, theme):
"""
@ -348,10 +354,6 @@ class ThemeManager(QtGui.QWidget):
shutil.rmtree(os.path.join(self.path, theme).encode(encoding))
except OSError:
log.exception(u'Error deleting theme %s', 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
self.pushThemes()
def onExportTheme(self):
"""
@ -359,7 +361,7 @@ class ThemeManager(QtGui.QWidget):
"""
item = self.themeListWidget.currentItem()
if item is None:
criticalErrorMessageBox(message=translate('OpenLP.ThemeManager',
critical_error_message_box(message=translate('OpenLP.ThemeManager',
'You have not selected a theme.'))
return
theme = unicode(item.data(QtCore.Qt.UserRole).toString())
@ -386,7 +388,7 @@ class ThemeManager(QtGui.QWidget):
'Your theme has been successfully exported.'))
except (IOError, OSError):
log.exception(u'Export Theme Failed')
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ThemeManager', 'Theme Export Failed'),
translate('OpenLP.ThemeManager',
'Your theme could not be exported due to an error.'))
@ -403,8 +405,8 @@ class ThemeManager(QtGui.QWidget):
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:
@ -448,9 +450,9 @@ class ThemeManager(QtGui.QWidget):
QtCore.QVariant(textName))
self.themeListWidget.addItem(item_name)
self.themelist.append(textName)
self.pushThemes()
self._pushThemes()
def pushThemes(self):
def _pushThemes(self):
"""
Notify listeners that the theme list has been updated
"""
@ -496,7 +498,7 @@ class ThemeManager(QtGui.QWidget):
for file in zip.namelist():
ucsfile = file_is_unicode(file)
if not ucsfile:
criticalErrorMessageBox(
critical_error_message_box(
message=translate('OpenLP.ThemeManager',
'File is not a valid theme.\n'
'The content encoding is not UTF-8.'))
@ -531,14 +533,14 @@ class ThemeManager(QtGui.QWidget):
theme = self._createThemeFromXml(filexml, self.path)
self.generateAndSaveImage(dir, themename, theme)
else:
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ThemeManager', 'Validation Error'),
translate('OpenLP.ThemeManager',
'File is not a valid theme.'))
log.exception(u'Theme file does not contain XML data %s' %
filename)
except (IOError, NameError):
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ThemeManager', 'Validation Error'),
translate('OpenLP.ThemeManager',
'File is not a valid theme.'))
@ -558,7 +560,7 @@ class ThemeManager(QtGui.QWidget):
"""
theme_dir = os.path.join(self.path, themeName)
if os.path.exists(theme_dir):
criticalErrorMessageBox(
critical_error_message_box(
translate('OpenLP.ThemeManager', 'Validation Error'),
translate('OpenLP.ThemeManager',
'A theme with this name already exists.'))
@ -570,6 +572,14 @@ class ThemeManager(QtGui.QWidget):
Called by thememaintenance Dialog to save the theme
and to trigger the reload of the theme list
"""
self._writeTheme(theme, imageFrom, imageTo)
self.loadThemes()
def _writeTheme(self, theme, imageFrom, imageTo):
"""
Writes the theme to the disk and handles the background image if
necessary
"""
name = theme.theme_name
theme_pretty_xml = theme.extract_formatted_xml()
log.debug(u'saveTheme %s %s', name, theme_pretty_xml)
@ -597,12 +607,9 @@ class ThemeManager(QtGui.QWidget):
except IOError:
log.exception(u'Failed to save theme image')
self.generateAndSaveImage(self.path, name, theme)
self.loadThemes()
self.pushThemes()
def generateAndSaveImage(self, dir, name, theme):
log.debug(u'generateAndSaveImage %s %s', dir, name)
theme_xml = theme.extract_xml()
frame = self.generateImage(theme)
samplepathname = os.path.join(self.path, name + u'.png')
if os.path.exists(samplepathname):
@ -668,7 +675,7 @@ class ThemeManager(QtGui.QWidget):
return theme
def _validate_theme_action(self, select_text, confirm_title, confirm_text,
testPlugin=True):
testPlugin=True, confirm=True):
"""
Check to see if theme has been selected and the destructive action
is allowed.
@ -680,15 +687,16 @@ class ThemeManager(QtGui.QWidget):
item = self.themeListWidget.currentItem()
theme = unicode(item.text())
# confirm deletion
answer = QtGui.QMessageBox.question(self, confirm_title,
confirm_text % theme, QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
if answer == QtGui.QMessageBox.No:
return False
if confirm:
answer = QtGui.QMessageBox.question(self, confirm_title,
confirm_text % theme, QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No),
QtGui.QMessageBox.No)
if answer == QtGui.QMessageBox.No:
return False
# should be the same unless default
if theme != unicode(item.data(QtCore.Qt.UserRole).toString()):
criticalErrorMessageBox(
critical_error_message_box(
message=translate('OpenLP.ThemeManager',
'You are unable to delete the default theme.'))
return False
@ -696,7 +704,8 @@ class ThemeManager(QtGui.QWidget):
if testPlugin:
for plugin in self.mainwindow.pluginManager.plugins:
if plugin.usesTheme(theme):
criticalErrorMessageBox(translate('OpenLP.ThemeManager',
critical_error_message_box(
translate('OpenLP.ThemeManager',
'Validation Error'),
unicode(translate('OpenLP.ThemeManager',
'Theme %s is used in the %s plugin.')) % \
@ -753,11 +762,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()

View File

@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, Receiver, ThemeLevel, translate
from openlp.core.lib.ui import UiStrings
class ThemesTab(SettingsTab):
"""
@ -98,7 +99,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(
@ -165,13 +166,7 @@ class ThemesTab(SettingsTab):
self.global_theme = unicode(self.DefaultComboBox.currentText())
self.parent.renderManager.set_global_theme(
self.global_theme, self.theme_level)
image = self.parent.ThemeManagerContents.getPreviewImage(
self.global_theme)
preview = QtGui.QPixmap(unicode(image))
if not preview.isNull():
preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
self.DefaultListView.setPixmap(preview)
self.__previewGlobalTheme()
def updateThemeList(self, theme_list):
"""
@ -198,10 +193,16 @@ class ThemesTab(SettingsTab):
self.parent.renderManager.set_global_theme(
self.global_theme, self.theme_level)
if self.global_theme is not u'':
image = self.parent.ThemeManagerContents.getPreviewImage(
self.global_theme)
preview = QtGui.QPixmap(unicode(image))
if not preview.isNull():
preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
self.DefaultListView.setPixmap(preview)
self.__previewGlobalTheme()
def __previewGlobalTheme(self):
"""
Utility method to update the global theme preview image.
"""
image = self.parent.ThemeManagerContents.getPreviewImage(
self.global_theme)
preview = QtGui.QPixmap(unicode(image))
if not preview.isNull():
preview = preview.scaled(300, 255, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
self.DefaultListView.setPixmap(preview)

View File

@ -27,32 +27,19 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, build_icon
from openlp.core.lib.ui import add_welcome_page, create_valign_combo
class Ui_ThemeWizard(object):
def setupUi(self, ThemeWizard):
ThemeWizard.setObjectName(u'OpenLP.ThemeWizard')
ThemeWizard.setModal(True)
ThemeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
ThemeWizard.setOptions(
QtGui.QWizard.IndependentPages |
def setupUi(self, themeWizard):
themeWizard.setObjectName(u'OpenLP.ThemeWizard')
themeWizard.setModal(True)
themeWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
themeWizard.setOptions(QtGui.QWizard.IndependentPages |
QtGui.QWizard.NoBackButtonOnStartPage)
self.spacer = QtGui.QSpacerItem(10, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
# Welcome Page
self.welcomePage = QtGui.QWizardPage()
self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap,
QtGui.QPixmap(u':/wizards/wizard_createtheme.bmp'))
self.welcomePage.setObjectName(u'WelcomePage')
self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage)
self.welcomeLayout.setObjectName(u'WelcomeLayout')
self.titleLabel = QtGui.QLabel(self.welcomePage)
self.titleLabel.setObjectName(u'TitleLabel')
self.welcomeLayout.addWidget(self.titleLabel)
self.welcomeLayout.addSpacing(40)
self.informationLabel = QtGui.QLabel(self.welcomePage)
self.informationLabel.setWordWrap(True)
self.informationLabel.setObjectName(u'InformationLabel')
self.welcomeLayout.addWidget(self.informationLabel)
self.welcomeLayout.addStretch()
ThemeWizard.addPage(self.welcomePage)
add_welcome_page(themeWizard, u':/wizards/wizard_createtheme.bmp')
# Background Page
self.backgroundPage = QtGui.QWizardPage()
self.backgroundPage.setObjectName(u'BackgroundPage')
@ -67,10 +54,8 @@ class Ui_ThemeWizard(object):
self.backgroundComboBox.setObjectName(u'BackgroundComboBox')
self.backgroundTypeLayout.addRow(self.backgroundLabel,
self.backgroundComboBox)
self.backgroundTypeSpacer = QtGui.QSpacerItem(10, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum)
self.backgroundTypeLayout.setItem(1, QtGui.QFormLayout.LabelRole,
self.backgroundTypeSpacer)
self.spacer)
self.backgroundLayout.addLayout(self.backgroundTypeLayout)
self.backgroundStack = QtGui.QStackedLayout()
self.backgroundStack.setObjectName(u'BackgroundStack')
@ -84,10 +69,7 @@ class Ui_ThemeWizard(object):
self.colorButton = QtGui.QPushButton(self.colorWidget)
self.colorButton.setObjectName(u'ColorButton')
self.colorLayout.addRow(self.colorLabel, self.colorButton)
self.colorSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.colorLayout.setItem(1, QtGui.QFormLayout.LabelRole,
self.colorSpacer)
self.colorLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.colorWidget)
self.gradientWidget = QtGui.QWidget(self.backgroundPage)
self.gradientWidget.setObjectName(u'GradientWidget')
@ -113,10 +95,7 @@ class Ui_ThemeWizard(object):
self.gradientComboBox.addItems([u'', u'', u'', u'', u''])
self.gradientLayout.addRow(self.gradientTypeLabel,
self.gradientComboBox)
self.gradientSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.gradientLayout.setItem(3, QtGui.QFormLayout.LabelRole,
self.gradientSpacer)
self.gradientLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.gradientWidget)
self.imageWidget = QtGui.QWidget(self.backgroundPage)
self.imageWidget.setObjectName(u'ImageWidget')
@ -136,13 +115,10 @@ class Ui_ThemeWizard(object):
build_icon(u':/general/general_open.png'))
self.imageFileLayout.addWidget(self.imageBrowseButton)
self.imageLayout.addRow(self.imageLabel, self.imageFileLayout)
self.imageSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.imageLayout.setItem(1, QtGui.QFormLayout.LabelRole,
self.imageSpacer)
self.imageLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.backgroundStack.addWidget(self.imageWidget)
self.backgroundLayout.addLayout(self.backgroundStack)
ThemeWizard.addPage(self.backgroundPage)
themeWizard.addPage(self.backgroundPage)
# Main Area Page
self.mainAreaPage = QtGui.QWizardPage()
self.mainAreaPage.setObjectName(u'MainAreaPage')
@ -225,7 +201,7 @@ class Ui_ThemeWizard(object):
self.shadowSizeSpinBox.setObjectName(u'ShadowSizeSpinBox')
self.shadowLayout.addWidget(self.shadowSizeSpinBox)
self.mainAreaLayout.addRow(self.shadowCheckBox, self.shadowLayout)
ThemeWizard.addPage(self.mainAreaPage)
themeWizard.addPage(self.mainAreaPage)
# Footer Area Page
self.footerAreaPage = QtGui.QWizardPage()
self.footerAreaPage.setObjectName(u'FooterAreaPage')
@ -251,7 +227,9 @@ class Ui_ThemeWizard(object):
self.footerSizeSpinBox.setObjectName(u'FooterSizeSpinBox')
self.footerAreaLayout.addRow(self.footerSizeLabel,
self.footerSizeSpinBox)
ThemeWizard.addPage(self.footerAreaPage)
self.footerAreaLayout.setItem(3, QtGui.QFormLayout.LabelRole,
self.spacer)
themeWizard.addPage(self.footerAreaPage)
# Alignment Page
self.alignmentPage = QtGui.QWizardPage()
self.alignmentPage.setObjectName(u'AlignmentPage')
@ -264,19 +242,17 @@ 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)
self.transitionsCheckBox.setObjectName(u'TransitionsCheckBox')
self.alignmentLayout.addRow(self.transitionsLabel,
self.transitionsCheckBox)
ThemeWizard.addPage(self.alignmentPage)
self.alignmentLayout.setItem(3, QtGui.QFormLayout.LabelRole,
self.spacer)
themeWizard.addPage(self.alignmentPage)
# Area Position Page
self.areaPositionPage = QtGui.QWizardPage()
self.areaPositionPage.setObjectName(u'AreaPositionPage')
@ -352,7 +328,7 @@ class Ui_ThemeWizard(object):
self.footerPositionLayout.addRow(self.footerHeightLabel,
self.footerHeightSpinBox)
self.areaPositionLayout.addWidget(self.footerPositionGroupBox)
ThemeWizard.addPage(self.areaPositionPage)
themeWizard.addPage(self.areaPositionPage)
# Preview Page
self.previewPage = QtGui.QWizardPage()
self.previewPage.setObjectName(u'PreviewPage')
@ -381,9 +357,8 @@ class Ui_ThemeWizard(object):
self.previewBoxLabel.setObjectName(u'PreviewBoxLabel')
self.previewAreaLayout.addWidget(self.previewBoxLabel)
self.previewLayout.addWidget(self.previewArea)
ThemeWizard.addPage(self.previewPage)
self.retranslateUi(ThemeWizard)
themeWizard.addPage(self.previewPage)
self.retranslateUi(themeWizard)
QtCore.QObject.connect(self.backgroundComboBox,
QtCore.SIGNAL(u'currentIndexChanged(int)'), self.backgroundStack,
QtCore.SLOT(u'setCurrentIndex(int)'))
@ -423,10 +398,10 @@ class Ui_ThemeWizard(object):
QtCore.QObject.connect(self.footerPositionCheckBox,
QtCore.SIGNAL(u'toggled(bool)'), self.footerHeightSpinBox,
QtCore.SLOT(u'setDisabled(bool)'))
QtCore.QMetaObject.connectSlotsByName(ThemeWizard)
QtCore.QMetaObject.connectSlotsByName(themeWizard)
def retranslateUi(self, ThemeWizard):
ThemeWizard.setWindowTitle(
def retranslateUi(self, themeWizard):
themeWizard.setWindowTitle(
translate('OpenLP.ThemeWizard', 'Theme Wizard'))
self.titleLabel.setText(
u'<span style="font-size:14pt; font-weight:600;">%s</span>' % \
@ -471,8 +446,7 @@ class Ui_ThemeWizard(object):
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'))
@ -486,8 +460,7 @@ class Ui_ThemeWizard(object):
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.mainBoldCheckBox.setText(translate('OpenLP.ThemeWizard', 'Bold'))
self.mainItalicsCheckBox.setText(
translate('OpenLP.ThemeWizard', 'Italic'))
self.footerAreaPage.setTitle(
@ -512,14 +485,6 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'Right'))
self.horizontalComboBox.setItemText(2,
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(
@ -568,16 +533,6 @@ class Ui_ThemeWizard(object):
translate('OpenLP.ThemeWizard', 'Theme name:'))
# Align all QFormLayouts towards each other.
labelWidth = max(self.backgroundLabel.minimumSizeHint().width(),
self.colorLabel.minimumSizeHint().width(),
self.gradientStartLabel.minimumSizeHint().width(),
self.gradientEndLabel.minimumSizeHint().width(),
self.gradientTypeLabel.minimumSizeHint().width(),
self.imageLabel.minimumSizeHint().width())
self.backgroundTypeSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.colorSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.gradientSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.imageSpacer.changeSize(labelWidth, 0,
self.horizontalLabel.minimumSizeHint().width())
self.spacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)

View File

@ -27,10 +27,12 @@
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 import build_icon, Receiver, SettingsManager
from openlp.core.lib.ui import UiStrings, add_welcome_page
log = logging.getLogger(__name__)
@ -63,35 +65,17 @@ class OpenLPWizard(QtGui.QWizard):
self.setOptions(QtGui.QWizard.IndependentPages |
QtGui.QWizard.NoBackButtonOnStartPage |
QtGui.QWizard.NoBackButtonOnLastPage)
self.addWelcomePage(image)
add_welcome_page(self, image)
self.addCustomPages()
self.addProgressPage()
self.retranslateUi()
QtCore.QMetaObject.connectSlotsByName(self)
def addWelcomePage(self, image):
def registerFields(self):
"""
Add the opening welcome page to the wizard.
``image``
A splash image for the wizard
Hook method for wizards to register any fields they need.
"""
self.welcomePage = QtGui.QWizardPage()
self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap,
QtGui.QPixmap(image))
self.welcomePage.setObjectName(u'WelcomePage')
self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage)
self.welcomeLayout.setObjectName(u'WelcomeLayout')
self.titleLabel = QtGui.QLabel(self.welcomePage)
self.titleLabel.setObjectName(u'TitleLabel')
self.welcomeLayout.addWidget(self.titleLabel)
self.welcomeLayout.addSpacing(40)
self.informationLabel = QtGui.QLabel(self.welcomePage)
self.informationLabel.setWordWrap(True)
self.informationLabel.setObjectName(u'InformationLabel')
self.welcomeLayout.addWidget(self.informationLabel)
self.welcomeLayout.addStretch()
self.addPage(self.welcomePage)
pass
def addProgressPage(self):
"""
@ -169,3 +153,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)

View File

@ -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
@ -137,10 +137,7 @@ class AppLocation(object):
os.path.split(openlp.__file__)[0])
return os.path.join(app_path, u'i18n')
else:
return _get_os_dir_path(u'openlp',
os.path.join(os.getenv(u'HOME'), u'Library',
u'Application Support', u'openlp'),
None, os.path.join(os.getenv(u'HOME'), u'.openlp'), dir_type)
return _get_os_dir_path(dir_type)
@staticmethod
def get_data_path():
@ -163,27 +160,38 @@ class AppLocation(object):
os.makedirs(path)
return path
def _get_os_dir_path(win_option, darwin_option, base_dir_option,
non_base_dir_option, dir_type=1):
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'), win_option)
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(darwin_option, u'Data')
return darwin_option
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 non_base_dir_option
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):
"""
@ -191,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):
"""
@ -375,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):
"""

View File

@ -40,21 +40,13 @@ 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)
visible_name = self.getString(StringContent.VisibleName)
self.alertForm = AlertForm(self, visible_name[u'title'])
def getSettingsTab(self):
"""
Return the settings tab for the Alerts plugin
"""
visible_name = self.getString(StringContent.VisibleName)
self.alertsTab = AlertsTab(self, visible_name[u'title'])
return self.alertsTab
self.alertForm = AlertForm(self)
def addToolsMenuItem(self, tools_menu):
"""
@ -82,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):
"""

View File

@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
from openlp.core.lib.ui import create_delete_push_button
class Ui_AlertDialog(object):
def setupUi(self, alertDialog):
@ -65,9 +66,8 @@ class Ui_AlertDialog(object):
self.saveButton.setIcon(build_icon(u':/general/general_save.png'))
self.saveButton.setObjectName(u'saveButton')
self.manageButtonLayout.addWidget(self.saveButton)
self.deleteButton = QtGui.QPushButton(alertDialog)
self.deleteButton.setIcon(build_icon(u':/general/general_delete.png'))
self.deleteButton.setObjectName(u'deleteButton')
self.deleteButton = create_delete_push_button(alertDialog)
self.deleteButton.setEnabled(False)
self.manageButtonLayout.addWidget(self.deleteButton)
self.manageButtonLayout.addStretch()
self.alertDialogLayout.addLayout(self.manageButtonLayout, 1, 1)
@ -75,11 +75,13 @@ class Ui_AlertDialog(object):
self.buttonBox.addButton(QtGui.QDialogButtonBox.Close)
displayIcon = build_icon(u':/general/general_live.png')
self.displayButton = QtGui.QPushButton(alertDialog)
self.displayButton.setEnabled(False)
self.displayButton.setIcon(displayIcon)
self.displayButton.setObjectName(u'displayButton')
self.buttonBox.addButton(self.displayButton,
QtGui.QDialogButtonBox.ActionRole)
self.displayCloseButton = QtGui.QPushButton(alertDialog)
self.displayCloseButton.setEnabled(False)
self.displayCloseButton.setIcon(displayIcon)
self.displayCloseButton.setObjectName(u'displayCloseButton')
self.buttonBox.addButton(self.displayCloseButton,
@ -101,8 +103,6 @@ class Ui_AlertDialog(object):
translate('AlertsPlugin.AlertForm', '&New'))
self.saveButton.setText(
translate('AlertsPlugin.AlertForm', '&Save'))
self.deleteButton.setText(
translate('AlertsPlugin.AlertForm', '&Delete'))
self.displayButton.setText(
translate('AlertsPlugin.AlertForm', 'Displ&ay'))
self.displayCloseButton.setText(

View File

@ -35,7 +35,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
"""
Provide UI for the alert system
"""
def __init__(self, plugin, visible_title):
def __init__(self, plugin):
"""
Initialise the alert form
"""
@ -44,22 +44,22 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
self.item_id = None
QtGui.QDialog.__init__(self, plugin.formparent)
self.setupUi(self)
QtCore.QObject.connect(self.displayButton, QtCore.SIGNAL(u'clicked()'),
self.onDisplayClicked)
QtCore.QObject.connect(self.displayButton,
QtCore.SIGNAL(u'clicked()'), self.onDisplayClicked)
QtCore.QObject.connect(self.displayCloseButton,
QtCore.SIGNAL(u'clicked()'), self.onDisplayCloseClicked)
QtCore.QObject.connect(self.alertTextEdit,
QtCore.SIGNAL(u'textChanged(const QString&)'), self.onTextChanged)
QtCore.QObject.connect(self.newButton, QtCore.SIGNAL(u'clicked()'),
self.onNewClick)
QtCore.QObject.connect(self.deleteButton, QtCore.SIGNAL(u'clicked()'),
self.onDeleteClick)
QtCore.QObject.connect(self.saveButton, QtCore.SIGNAL(u'clicked()'),
self.onSaveClick)
QtCore.QObject.connect(self.newButton,
QtCore.SIGNAL(u'clicked()'), self.onNewClick)
QtCore.QObject.connect(self.saveButton,
QtCore.SIGNAL(u'clicked()'), self.onSaveClick)
QtCore.QObject.connect(self.alertListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onDoubleClick)
QtCore.QObject.connect(self.alertListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSingleClick)
QtCore.QObject.connect(self.alertListWidget,
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
def loadList(self):
"""
@ -72,18 +72,15 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
item_name = QtGui.QListWidgetItem(alert.text)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id))
self.alertListWidget.addItem(item_name)
self.saveButton.setEnabled(False)
self.deleteButton.setEnabled(False)
def onDisplayClicked(self):
if self.triggerAlert(unicode(self.alertTextEdit.text())):
self.loadList()
self.triggerAlert(unicode(self.alertTextEdit.text()))
def onDisplayCloseClicked(self):
if self.triggerAlert(unicode(self.alertTextEdit.text())):
self.close()
def onDeleteClick(self):
def onDeleteButtonClicked(self):
"""
Deletes the selected item.
"""
@ -95,8 +92,6 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
self.alertListWidget.takeItem(row)
self.item_id = None
self.alertTextEdit.setText(u'')
self.saveButton.setEnabled(False)
self.deleteButton.setEnabled(False)
def onNewClick(self):
if len(self.alertTextEdit.text()) == 0:
@ -135,30 +130,26 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
"""
List item has been double clicked to display it
"""
items = self.alertListWidget.selectedIndexes()
for item in items:
bitem = self.alertListWidget.item(item.row())
self.triggerAlert(unicode(bitem.text()))
self.alertTextEdit.setText(unicode(bitem.text()))
self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
item = self.alertListWidget.selectedIndexes()[0]
bitem = self.alertListWidget.item(item.row())
self.triggerAlert(unicode(bitem.text()))
self.alertTextEdit.setText(unicode(bitem.text()))
self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
self.saveButton.setEnabled(False)
self.deleteButton.setEnabled(True)
def onSingleClick(self):
"""
List item has been single clicked to add it to
the edit field so it can be changed.
"""
items = self.alertListWidget.selectedIndexes()
for item in items:
bitem = self.alertListWidget.item(item.row())
self.alertTextEdit.setText(unicode(bitem.text()))
self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
item = self.alertListWidget.selectedIndexes()[0]
bitem = self.alertListWidget.item(item.row())
self.alertTextEdit.setText(unicode(bitem.text()))
self.item_id = (bitem.data(QtCore.Qt.UserRole)).toInt()[0]
# If the alert does not contain '<>' we clear the ParameterEdit field.
if unicode(self.alertTextEdit.text()).find(u'<>') == -1:
self.parameterEdit.setText(u'')
self.saveButton.setEnabled(False)
self.deleteButton.setEnabled(True)
def triggerAlert(self, text):
"""
@ -167,30 +158,49 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
``text``
The alert text (unicode).
"""
if text:
# We found '<>' in the alert text, but the ParameterEdit field is
# empty.
if text.find(u'<>') != -1 and not self.parameterEdit.text() and \
QtGui.QMessageBox.question(self,
translate('AlertPlugin.AlertForm', 'No Parameter found'),
translate('AlertPlugin.AlertForm', 'You have not entered a '
'parameter to be replaced.\nDo you want to continue anyway?'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
self.parameterEdit.setFocus()
return False
# The ParameterEdit field is not empty, but we have not found '<>'
# in the alert text.
elif text.find(u'<>') == -1 and self.parameterEdit.text() and \
QtGui.QMessageBox.question(self,
translate('AlertPlugin.AlertForm', 'No Placeholder found'),
translate('AlertPlugin.AlertForm', 'The alert text does not'
' contain \'<>\'.\nDo want to continue anyway?'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
self.parameterEdit.setFocus()
return False
text = text.replace(u'<>', unicode(self.parameterEdit.text()))
self.parent.alertsmanager.displayAlert(text)
return True
return False
if not text:
return False
# We found '<>' in the alert text, but the ParameterEdit field is empty.
if text.find(u'<>') != -1 and not self.parameterEdit.text() and \
QtGui.QMessageBox.question(self,
translate('AlertPlugin.AlertForm', 'No Parameter found'),
translate('AlertPlugin.AlertForm', 'You have not entered a '
'parameter to be replaced.\nDo you want to continue anyway?'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
self.parameterEdit.setFocus()
return False
# The ParameterEdit field is not empty, but we have not found '<>'
# in the alert text.
elif text.find(u'<>') == -1 and self.parameterEdit.text() and \
QtGui.QMessageBox.question(self,
translate('AlertPlugin.AlertForm', 'No Placeholder found'),
translate('AlertPlugin.AlertForm', 'The alert text does not'
' contain \'<>\'.\nDo want to continue anyway?'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.No |
QtGui.QMessageBox.Yes)) == QtGui.QMessageBox.No:
self.parameterEdit.setFocus()
return False
text = text.replace(u'<>', unicode(self.parameterEdit.text()))
self.parent.alertsmanager.displayAlert(text)
return True
def onCurrentRowChanged(self, row):
"""
Called when the *alertListWidget*'s current row has been changed. This
enables or disables buttons which require an item to act on.
``row``
The row (int). If there is no current row, the value is -1.
"""
if row == -1:
self.displayButton.setEnabled(False)
self.displayCloseButton.setEnabled(False)
self.saveButton.setEnabled(False)
self.deleteButton.setEnabled(False)
else:
self.displayButton.setEnabled(True)
self.displayCloseButton.setEnabled(True)
self.deleteButton.setEnabled(True)
# We do not need to enable the save button, as it is only enabled
# when typing text in the "alertTextEdit".

View File

@ -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()
self.generateAlert()

View File

@ -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:'))
@ -123,18 +115,8 @@ class AlertsTab(SettingsTab):
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.PreviewGroupBox.setTitle(UiStrings.Preview)
self.FontPreview.setText(UiStrings.OLPV2)
def onBackgroundColorButtonClicked(self):
new_color = QtGui.QColorDialog.getColor(
@ -148,9 +130,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 +167,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 +176,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):

View File

@ -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')
@ -102,7 +95,7 @@ class BiblePlugin(Plugin):
Called to find out if the bible plugin is currently using a theme.
Returns True if the theme is being used, otherwise returns False.
"""
if self.settings_tab.bible_theme == theme:
if unicode(self.settings_tab.bible_theme) == theme:
return True
return False
@ -119,6 +112,7 @@ class BiblePlugin(Plugin):
The new name the plugin should now use.
"""
self.settings_tab.bible_theme = newTheme
self.settings_tab.save()
def setPluginTextStrings(self):
"""
@ -134,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)

View File

@ -33,9 +33,9 @@ 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.ui import criticalErrorMessageBox
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard
from openlp.core.utils import AppLocation, string_is_unicode
from openlp.plugins.bibles.lib.manager import BibleFormat
@ -124,9 +124,12 @@ class BibleImportForm(OpenLPWizard):
QtCore.QObject.connect(self.osisBrowseButton,
QtCore.SIGNAL(u'clicked()'),
self.onOsisBrowseButtonClicked)
QtCore.QObject.connect(self.csvTestamentsButton,
QtCore.SIGNAL(u'clicked()'),
self.onCsvTestamentsBrowseButtonClicked)
QtCore.QObject.connect(self.csvBooksButton,
QtCore.SIGNAL(u'clicked()'),
self.onBooksBrowseButtonClicked)
self.onCsvBooksBrowseButtonClicked)
QtCore.QObject.connect(self.csvVersesButton,
QtCore.SIGNAL(u'clicked()'),
self.onCsvVersesBrowseButtonClicked)
@ -154,10 +157,9 @@ class BibleImportForm(OpenLPWizard):
self.formatComboBox.addItems([u'', u'', u'', u'', u''])
self.formatComboBox.setObjectName(u'FormatComboBox')
self.formatLayout.addRow(self.formatLabel, self.formatComboBox)
self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole,
self.formatSpacer)
self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectPageLayout.addLayout(self.formatLayout)
self.selectStack = QtGui.QStackedLayout()
self.selectStack.setObjectName(u'SelectStack')
@ -178,15 +180,25 @@ class BibleImportForm(OpenLPWizard):
self.osisBrowseButton.setObjectName(u'OsisBrowseButton')
self.osisFileLayout.addWidget(self.osisBrowseButton)
self.osisLayout.addRow(self.osisFileLabel, self.osisFileLayout)
self.osisSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.osisLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.osisSpacer)
self.osisLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.osisWidget)
self.csvWidget = QtGui.QWidget(self.selectPage)
self.csvWidget.setObjectName(u'CsvWidget')
self.csvLayout = QtGui.QFormLayout(self.csvWidget)
self.csvLayout.setMargin(0)
self.csvLayout.setObjectName(u'CsvLayout')
self.csvTestamentsLabel = QtGui.QLabel(self.csvWidget)
self.csvTestamentsLabel.setObjectName(u'CsvTestamentsLabel')
self.csvTestamentsLayout = QtGui.QHBoxLayout()
self.csvTestamentsLayout.setObjectName(u'CsvTestamentsLayout')
self.csvTestamentsEdit = QtGui.QLineEdit(self.csvWidget)
self.csvTestamentsEdit.setObjectName(u'CsvTestamentsEdit')
self.csvTestamentsLayout.addWidget(self.csvTestamentsEdit)
self.csvTestamentsButton = QtGui.QToolButton(self.csvWidget)
self.csvTestamentsButton.setIcon(self.openIcon)
self.csvTestamentsButton.setObjectName(u'CsvTestamentsButton')
self.csvTestamentsLayout.addWidget(self.csvTestamentsButton)
self.csvLayout.addRow(self.csvTestamentsLabel, self.csvTestamentsLayout)
self.csvBooksLabel = QtGui.QLabel(self.csvWidget)
self.csvBooksLabel.setObjectName(u'CsvBooksLabel')
self.csvBooksLayout = QtGui.QHBoxLayout()
@ -211,9 +223,7 @@ class BibleImportForm(OpenLPWizard):
self.csvVersesButton.setObjectName(u'CsvVersesButton')
self.csvVersesLayout.addWidget(self.csvVersesButton)
self.csvLayout.addRow(self.csvVersesLabel, self.csvVersesLayout)
self.csvSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.csvLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.csvSpacer)
self.csvLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.csvWidget)
self.openSongWidget = QtGui.QWidget(self.selectPage)
self.openSongWidget.setObjectName(u'OpenSongWidget')
@ -233,10 +243,7 @@ class BibleImportForm(OpenLPWizard):
self.openSongFileLayout.addWidget(self.openSongBrowseButton)
self.openSongLayout.addRow(self.openSongFileLabel,
self.openSongFileLayout)
self.openSongSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.openSongLayout.setItem(1, QtGui.QFormLayout.LabelRole,
self.openSongSpacer)
self.openSongLayout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.openSongWidget)
self.webTabWidget = QtGui.QTabWidget(self.selectPage)
self.webTabWidget.setObjectName(u'WebTabWidget')
@ -315,10 +322,7 @@ class BibleImportForm(OpenLPWizard):
self.openlp1DisabledLabel.setWordWrap(True)
self.openlp1DisabledLabel.setObjectName(u'Openlp1DisabledLabel')
self.openlp1Layout.addRow(self.openlp1DisabledLabel)
self.openlp1Spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole,
self.openlp1Spacer)
self.openlp1Layout.setItem(1, QtGui.QFormLayout.LabelRole, self.spacer)
self.selectStack.addWidget(self.openlp1Widget)
self.selectPageLayout.addLayout(self.selectStack)
self.addPage(self.selectPage)
@ -386,15 +390,17 @@ class BibleImportForm(OpenLPWizard):
self.formatComboBox.setItemText(4,
translate('BiblesPlugin.ImportWizardForm', 'openlp.org 1.x'))
self.openlp1FileLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'File location:'))
translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.osisFileLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'File location:'))
translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.csvTestamentsLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Testaments file:'))
self.csvBooksLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Books location:'))
translate('BiblesPlugin.ImportWizardForm', 'Books file:'))
self.csvVersesLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Verse location:'))
translate('BiblesPlugin.ImportWizardForm', 'Verses file:'))
self.openSongFileLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Bible filename:'))
translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.webSourceLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Location:'))
self.webSourceComboBox.setItemText(0,
@ -445,19 +451,12 @@ class BibleImportForm(OpenLPWizard):
# Align all QFormLayouts towards each other.
labelWidth = max(self.formatLabel.minimumSizeHint().width(),
self.osisFileLabel.minimumSizeHint().width(),
self.csvTestamentsLabel.minimumSizeHint().width(),
self.csvBooksLabel.minimumSizeHint().width(),
self.csvVersesLabel.minimumSizeHint().width(),
self.openSongFileLabel.minimumSizeHint().width(),
self.openlp1FileLabel.minimumSizeHint().width())
self.formatSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.osisSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.csvSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.openSongSpacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
self.openlp1Spacer.changeSize(labelWidth, 0,
self.spacer.changeSize(labelWidth, 0,
QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
def validateCurrentPage(self):
@ -469,7 +468,7 @@ 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():
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm',
'Invalid Bible Location'),
translate('BiblesPlugin.ImportWizardForm',
@ -478,8 +477,17 @@ class BibleImportForm(OpenLPWizard):
self.osisFileEdit.setFocus()
return False
elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV:
if not self.field(u'csv_booksfile').toString():
criticalErrorMessageBox(
if not self.field(u'csv_testamentsfile').toString():
answer = critical_error_message_box(translate(
'BiblesPlugin.ImportWizardForm', 'No Testaments File'),
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'),
translate('BiblesPlugin.ImportWizardForm',
@ -488,7 +496,7 @@ class BibleImportForm(OpenLPWizard):
self.csvBooksEdit.setFocus()
return False
elif not self.field(u'csv_versefile').toString():
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm',
'Invalid Verse File'),
translate('BiblesPlugin.ImportWizardForm',
@ -499,7 +507,7 @@ class BibleImportForm(OpenLPWizard):
elif self.field(u'source_format').toInt()[0] == \
BibleFormat.OpenSong:
if not self.field(u'opensong_file').toString():
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm',
'Invalid OpenSong Bible'),
translate('BiblesPlugin.ImportWizardForm',
@ -509,7 +517,7 @@ class BibleImportForm(OpenLPWizard):
return False
elif self.field(u'source_format').toInt()[0] == BibleFormat.OpenLP1:
if not self.field(u'openlp1_location').toString():
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm',
'Invalid Bible Location'),
translate('BiblesPlugin.ImportWizardForm',
@ -523,7 +531,7 @@ class BibleImportForm(OpenLPWizard):
license_copyright = \
unicode(self.field(u'license_copyright').toString())
if not license_version:
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm',
'Empty Version Name'),
translate('BiblesPlugin.ImportWizardForm',
@ -531,7 +539,7 @@ class BibleImportForm(OpenLPWizard):
self.versionNameEdit.setFocus()
return False
elif not license_copyright:
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm',
'Empty Copyright'),
translate('BiblesPlugin.ImportWizardForm',
@ -540,7 +548,7 @@ class BibleImportForm(OpenLPWizard):
self.copyrightEdit.setFocus()
return False
elif self.manager.exists(license_version):
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm', 'Bible Exists'),
translate('BiblesPlugin.ImportWizardForm',
'This Bible already exists. Please import '
@ -572,7 +580,15 @@ class BibleImportForm(OpenLPWizard):
translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'),
self.osisFileEdit)
def onBooksBrowseButtonClicked(self):
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)'
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
def onCsvBooksBrowseButtonClicked(self):
"""
Show the file open dialog for the books CSV file.
"""
@ -613,12 +629,14 @@ class BibleImportForm(OpenLPWizard):
"""
self.selectPage.registerField(u'source_format', self.formatComboBox)
self.selectPage.registerField(u'osis_location', self.osisFileEdit)
self.selectPage.registerField(
u'csv_testamentsfile', self.csvTestamentsEdit)
self.selectPage.registerField(u'csv_booksfile', self.csvBooksEdit)
self.selectPage.registerField(u'csv_versefile', self.csvVersesEdit)
self.selectPage.registerField(u'opensong_file', self.openSongFileEdit)
self.selectPage.registerField(u'web_location', self.webSourceComboBox)
self.selectPage.registerField(u'web_biblename',
self.webTranslationComboBox)
self.selectPage.registerField(
u'web_biblename', self.webTranslationComboBox)
self.selectPage.registerField(u'proxy_server', self.webServerEdit)
self.selectPage.registerField(u'proxy_username', self.webUserEdit)
self.selectPage.registerField(u'proxy_password', self.webPasswordEdit)
@ -641,6 +659,7 @@ class BibleImportForm(OpenLPWizard):
self.cancelButton.setVisible(True)
self.setField(u'source_format', QtCore.QVariant(0))
self.setField(u'osis_location', QtCore.QVariant(''))
self.setField(u'csv_testamentsfile', QtCore.QVariant(''))
self.setField(u'csv_booksfile', QtCore.QVariant(''))
self.setField(u'csv_versefile', QtCore.QVariant(''))
self.setField(u'opensong_file', QtCore.QVariant(''))
@ -708,34 +727,6 @@ class BibleImportForm(OpenLPWizard):
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.
@ -770,7 +761,8 @@ class BibleImportForm(OpenLPWizard):
elif bible_type == BibleFormat.CSV:
# Import a CSV bible.
importer = self.manager.import_bible(BibleFormat.CSV,
name=license_version,
name=license_version, testamentsfile=unicode(
self.field(u'csv_testamentsfile').toString()),
booksfile=unicode(self.field(u'csv_booksfile').toString()),
versefile=unicode(self.field(u'csv_versefile').toString())
)
@ -795,8 +787,7 @@ class BibleImportForm(OpenLPWizard):
bible = \
self.web_bible_list[WebDownload.Bibleserver][bible_version]
importer = self.manager.import_bible(
BibleFormat.WebDownload,
name=license_version,
BibleFormat.WebDownload, name=license_version,
download_source=WebDownload.get_name(download_location),
download_name=bible,
proxy_server=unicode(self.field(u'proxy_server').toString()),

View File

@ -33,6 +33,13 @@ import re
log = logging.getLogger(__name__)
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 +69,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<from_chapter>[0-9]+)%(sep_v)s)?'
It starts with a optional chapter reference ``from_chapter`` followed by
a verse separator.
2. ``(?P<from_verse>[0-9]+)``
The verse reference ``from_verse`` is manditory
3. ``(?P<range_to>%(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<to_chapter>[0-9]+)%(sep_v)s)?``
The ``to_chapter`` reference with separator is equivalent to group 1.
5. ``(?P<to_verse>[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<book>[\d]*[^\d]+)(?<!\s)\s*``
The ``book`` group starts with the first non-whitespace character. There
are optional leading digits followed by non-digits. The group ends
before the whitspace in front of the next digit.
2. ``(?P<ranges>(?:`` + 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)
For example::
[(u'John', 3, 16, 18), (u'John', 4, 1, 1)]
``reference``
The bible reference to parse.
**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<from_chapter>[0-9]+)%(sep_v)s)?``
It starts with a optional chapter reference ``from_chapter`` followed by
a verse separator.
``(?P<from_verse>[0-9]+)``
The verse reference ``from_verse`` is manditory
``(?P<range_to>%(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<to_chapter>[0-9]+)%(sep_v)s)?``
The ``to_chapter`` reference with separator is equivalent to group 1.
``(?P<to_verse>[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<book>[\d]*[^\d]+)(?<!\s)\s*``
The ``book`` group starts with the first non-whitespace character. There
are optional leading digits followed by non-digits. The group ends
before the whitspace in front of the next digit.
``(?P<ranges>(?:`` + 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 +222,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 +235,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

View File

@ -23,7 +23,48 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`cvsbible` modules provides a facility to import bibles from a set of
CSV files.
The module expects two mandatory files containing the books and the verses and
will accept an optional third file containing the testaments.
The format of the testament file is:
<testament_id>,<testament_name>
For example:
1,Old Testament
2,New Testament
The format of the books file is:
<book_id>,<testament_id>,<book_name>,<book_abbreviation>
For example
1,1,Genesis,Gen
2,1,Exodus,Exod
...
40,2,Matthew,Matt
There are two acceptable formats of the verses file. They are:
<book_id>,<chapter_number>,<verse_number>,<verse_text>
or
<book_name>,<chapter_number>,<verse_number>,<verse_text>
For example:
1,1,1,"In the beginning God created the heaven and the earth."
or
"Genesis",1,2,"And the earth was without form, and void; and...."
All CSV files are expected to use a comma (',') as the delimeter and double
quotes ('"') as the quote symbol.
"""
import logging
import chardet
import csv
@ -31,7 +72,7 @@ import csv
from PyQt4 import QtCore
from openlp.core.lib import Receiver, translate
from openlp.plugins.bibles.lib.db import BibleDB
from openlp.plugins.bibles.lib.db import BibleDB, Testament
log = logging.getLogger(__name__)
@ -39,68 +80,120 @@ class CSVBible(BibleDB):
"""
This class provides a specialisation for importing of CSV Bibles.
"""
def __init__(self, parent, **kwargs):
"""
Loads a Bible from a pair of CVS files passed in
Loads a Bible from a set of CVS files.
This class assumes the files contain all the information and
a clean bible is being loaded.
"""
log.info(self.__class__.__name__)
BibleDB.__init__(self, parent, **kwargs)
try:
self.testamentsfile = kwargs[u'testamentsfile']
except KeyError:
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):
"""
Overrides parent method so we can handle importing a testament file.
"""
if self.testamentsfile:
self.wizard.progressBar.setMinimum(0)
self.wizard.progressBar.setMaximum(2)
self.wizard.progressBar.setValue(0)
testaments_file = None
try:
details = get_file_encoding(self.testamentsfile)
testaments_file = open(self.testamentsfile, 'rb')
testaments_reader = csv.reader(testaments_file, delimiter=',',
quotechar='"')
for line in testaments_reader:
if self.stop_import_flag:
break
self.wizard.incrementProgressBar(unicode(
translate('BibleDB.Wizard',
'Importing testaments... %s')) %
unicode(line[1], details['encoding']), 0)
self.save_object(Testament.populate(
name=unicode(line[1], details['encoding'])))
Receiver.send_message(u'openlp_process_events')
except (IOError, IndexError):
log.exception(u'Loading testaments from file failed')
finally:
if testaments_file:
testaments_file.close()
self.wizard.incrementProgressBar(unicode(translate(
'BibleDB.Wizard', 'Importing testaments... done.')), 2)
else:
BibleDB.setup_testaments(self)
def do_import(self):
"""
Import the bible books and verses.
"""
self.wizard.progressBar.setValue(0)
self.wizard.progressBar.setMinimum(0)
self.wizard.progressBar.setMaximum(66)
success = True
books_file = None
book_ptr = None
verse_file = None
book_list = {}
# Populate the Tables
try:
details = get_file_encoding(self.booksfile)
books_file = open(self.booksfile, 'r')
dialect = csv.Sniffer().sniff(books_file.read(1024))
books_file.seek(0)
books_reader = csv.reader(books_file, dialect)
books_reader = csv.reader(books_file, delimiter=',', quotechar='"')
for line in books_reader:
# cancel pressed
if self.stop_import_flag:
break
details = chardet.detect(line[1])
self.create_book(unicode(line[1], details['encoding']),
line[2], int(line[0]))
Receiver.send_message(u'openlp_process_events')
self.wizard.incrementProgressBar(unicode(
translate('BibleDB.Wizard', 'Importing books... %s')) %
unicode(line[2], details['encoding']))
self.create_book(unicode(line[2], details['encoding']),
unicode(line[3], details['encoding']), int(line[1]))
book_list[int(line[0])] = unicode(line[2], details['encoding'])
Receiver.send_message(u'openlp_process_events')
except (IOError, IndexError):
log.exception(u'Loading books from file failed')
success = False
finally:
if books_file:
books_file.close()
if not success:
if self.stop_import_flag or not success:
return False
self.wizard.progressBar.setValue(0)
self.wizard.progressBar.setMaximum(67)
verse_file = None
try:
verse_file = open(self.versesfile, 'r')
dialect = csv.Sniffer().sniff(verse_file.read(1024))
verse_file.seek(0)
verse_reader = csv.reader(verse_file, dialect)
book_ptr = None
details = get_file_encoding(self.versesfile)
verse_file = open(self.versesfile, 'rb')
verse_reader = csv.reader(verse_file, delimiter=',', quotechar='"')
for line in verse_reader:
if self.stop_import_flag:
# cancel pressed
break
details = chardet.detect(line[3])
if book_ptr != line[0]:
book = self.get_book(line[0])
try:
line_book = book_list[int(line[0])]
except ValueError:
line_book = unicode(line[0], details['encoding'])
if book_ptr != line_book:
book = self.get_book(line_book)
book_ptr = book.name
self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.CSVImport', 'Importing %s %s...',
'Importing <book name> <chapter>...')) %
(book.name, int(line[1])))
'BibleDB.Wizard', 'Importing verses from %s...',
'Importing verses from <book name>...')) % book.name)
self.session.commit()
self.create_verse(book.id, line[1], line[2],
unicode(line[3], details['encoding']))
Receiver.send_message(u'openlp_process_events')
try:
verse_text = unicode(line[3], details['encoding'])
except UnicodeError:
verse_text = unicode(line[3], u'cp1252')
self.create_verse(book.id, line[1], line[2], verse_text)
self.wizard.incrementProgressBar(translate('BibleDB.Wizard',
'Importing verses... done.'))
Receiver.send_message(u'openlp_process_events')
self.session.commit()
except IOError:
log.exception(u'Loading verses from file failed')
@ -112,3 +205,18 @@ class CSVBible(BibleDB):
return False
else:
return success
def get_file_encoding(filename):
"""
Utility function to get the file encoding.
"""
detect_file = None
try:
detect_file = open(filename, 'r')
details = chardet.detect(detect_file.read(1024))
except IOError:
log.exception(u'Error detecting file encoding')
finally:
if detect_file:
detect_file.close()
return details

View File

@ -35,7 +35,7 @@ from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import translate
from openlp.core.lib.db import BaseModel, init_db, Manager
from openlp.core.ui import criticalErrorMessageBox
from openlp.core.lib.ui import critical_error_message_box
log = logging.getLogger(__name__)
@ -206,10 +206,16 @@ class BibleDB(QtCore.QObject, Manager):
"""
self.wizard = wizard
self.create_meta(u'dbversion', u'2')
self.setup_testaments()
return self.name
def setup_testaments(self):
"""
Initialise the testaments section of a bible with suitable defaults.
"""
self.save_object(Testament.populate(name=u'Old Testament'))
self.save_object(Testament.populate(name=u'New Testament'))
self.save_object(Testament.populate(name=u'Apocrypha'))
return self.name
def create_book(self, name, abbrev, testament=1):
"""
@ -355,7 +361,7 @@ class BibleDB(QtCore.QObject, Manager):
verse_list.extend(verses)
else:
log.debug(u'OpenLP failed to find book %s', book)
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'),
translate('BiblesPlugin', 'No matching book '
'could be found in this Bible. Check that you have '

View File

@ -38,7 +38,7 @@ from HTMLParser import HTMLParseError
from BeautifulSoup import BeautifulSoup, NavigableString
from openlp.core.lib import Receiver, translate
from openlp.core.ui import criticalErrorMessageBox
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, get_web_page
from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.db import BibleDB, Book
@ -210,7 +210,8 @@ class BGExtract(object):
cleaner = [(re.compile('&nbsp;|<br />|\'\+\''), lambda match: '')]
soup = get_soup_for_bible_ref(
u'http://www.biblegateway.com/passage/?%s' % url_params,
cleaner=cleaner)
pre_parse_regex=r'<meta name.*?/>', pre_parse_substitute='',
cleaner=cleaner)
if not soup:
return None
Receiver.send_message(u'openlp_process_events')
@ -430,7 +431,7 @@ class HTTPBible(BibleDB):
if not db_book:
book_details = HTTPBooks.get_book(book)
if not book_details:
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'),
translate('BiblesPlugin', 'No matching '
'book could be found in this Bible. Check that you '
@ -442,7 +443,6 @@ class HTTPBible(BibleDB):
book = db_book.name
if BibleDB.get_verse_count(self, book, reference[1]) == 0:
Receiver.send_message(u'cursor_busy')
Receiver.send_message(u'openlp_process_events')
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
@ -499,7 +499,8 @@ class HTTPBible(BibleDB):
"""
return HTTPBooks.get_verse_count(book, chapter)
def get_soup_for_bible_ref(reference_url, header=None, cleaner=None):
def get_soup_for_bible_ref(reference_url, header=None, pre_parse_regex=None,
pre_parse_substitute=None, cleaner=None):
"""
Gets a webpage and returns a parsed and optionally cleaned soup or None.
@ -509,6 +510,13 @@ def get_soup_for_bible_ref(reference_url, header=None, cleaner=None):
``header``
An optional HTTP header to pass to the bible web server.
``pre_parse_regex``
A regular expression to run on the webpage. Allows manipulation of the
webpage before passing to BeautifulSoup for parsing.
``pre_parse_substitute``
The text to replace any matches to the regular expression with.
``cleaner``
An optional regex to use during webpage parsing.
"""
@ -518,12 +526,15 @@ def get_soup_for_bible_ref(reference_url, header=None, cleaner=None):
if not page:
send_error_message(u'download')
return None
page_source = page.read()
if pre_parse_regex and pre_parse_substitute is not None:
page_source = re.sub(pre_parse_regex, pre_parse_substitute, page_source)
soup = None
try:
if cleaner:
soup = BeautifulSoup(page, markupMassage=cleaner)
soup = BeautifulSoup(page_source, markupMassage=cleaner)
else:
soup = BeautifulSoup(page)
soup = BeautifulSoup(page_source)
except HTMLParseError:
log.exception(u'BeautifulSoup could not parse the bible page.')
if not soup:
@ -540,14 +551,14 @@ def send_error_message(error_type):
The type of error that occured for the issue.
"""
if error_type == u'download':
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblePlugin.HTTPBible', 'Download Error'),
translate('BiblePlugin.HTTPBible', 'There was a '
'problem downloading your verse selection. Please check your '
'Internet connection, and if this error continues to occur '
'please consider reporting a bug.'))
elif error_type == u'parse':
criticalErrorMessageBox(
critical_error_message_box(
translate('BiblePlugin.HTTPBible', 'Parse Error'),
translate('BiblePlugin.HTTPBible', 'There was a '
'problem extracting your verse selection. If this error continues '

View File

@ -92,7 +92,7 @@ class BibleFormat(object):
return None
@staticmethod
def list():
def get_formats_list():
"""
Return a list of the supported Bible formats.
"""

View File

@ -28,21 +28,22 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
ItemCapabilities, translate
from openlp.core.ui import criticalErrorMessageBox
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
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):
@ -53,7 +54,6 @@ 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.search_results = {}
@ -81,50 +81,33 @@ class BibleMediaItem(MediaManagerItem):
self.quickLayout.setObjectName(u'quickLayout')
self.quickVersionLabel = QtGui.QLabel(self.quickTab)
self.quickVersionLabel.setObjectName(u'quickVersionLabel')
self.quickVersionComboBox = QtGui.QComboBox(self.quickTab)
self.quickVersionComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.quickVersionComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.quickVersionComboBox.setObjectName(u'quickVersionComboBox')
self.quickVersionComboBox = media_item_combo_box(self.quickTab,
u'quickVersionComboBox')
self.quickVersionLabel.setBuddy(self.quickVersionComboBox)
self.quickLayout.addRow(self.quickVersionLabel,
self.quickVersionComboBox)
self.quickSecondLabel = QtGui.QLabel(self.quickTab)
self.quickSecondLabel.setObjectName(u'quickSecondLabel')
self.quickSecondComboBox = QtGui.QComboBox(self.quickTab)
self.quickSecondComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.quickSecondComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.quickSecondComboBox.setObjectName(u'quickSecondComboBox')
self.quickSecondComboBox = media_item_combo_box(self.quickTab,
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 = QtGui.QComboBox(self.quickTab)
self.quickSearchComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.quickSearchComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.quickSearchComboBox.setObjectName(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')
self.quickClearComboBox = QtGui.QComboBox(self.quickTab)
self.quickClearComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.quickClearComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.quickClearComboBox.setObjectName(u'quickClearComboBox')
self.quickClearComboBox = media_item_combo_box(self.quickTab,
u'quickClearComboBox')
self.quickLayout.addRow(self.quickClearLabel, self.quickClearComboBox)
self.quickSearchButtonLayout = QtGui.QHBoxLayout()
self.quickSearchButtonLayout.setObjectName(u'quickSearchButtonLayout')
@ -144,36 +127,24 @@ class BibleMediaItem(MediaManagerItem):
self.advancedVersionLabel.setObjectName(u'advancedVersionLabel')
self.advancedLayout.addWidget(self.advancedVersionLabel, 0, 0,
QtCore.Qt.AlignRight)
self.advancedVersionComboBox = QtGui.QComboBox(self.advancedTab)
self.advancedVersionComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.advancedVersionComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.advancedVersionComboBox.setObjectName(u'advancedVersionComboBox')
self.advancedVersionComboBox = media_item_combo_box(self.advancedTab,
u'advancedVersionComboBox')
self.advancedVersionLabel.setBuddy(self.advancedVersionComboBox)
self.advancedLayout.addWidget(self.advancedVersionComboBox, 0, 1, 1, 2)
self.advancedSecondLabel = QtGui.QLabel(self.advancedTab)
self.advancedSecondLabel.setObjectName(u'advancedSecondLabel')
self.advancedLayout.addWidget(self.advancedSecondLabel, 1, 0,
QtCore.Qt.AlignRight)
self.advancedSecondComboBox = QtGui.QComboBox(self.advancedTab)
self.advancedSecondComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.advancedSecondComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.advancedSecondComboBox.setObjectName(u'advancedSecondComboBox')
self.advancedSecondComboBox = media_item_combo_box(self.advancedTab,
u'advancedSecondComboBox')
self.advancedSecondLabel.setBuddy(self.advancedSecondComboBox)
self.advancedLayout.addWidget(self.advancedSecondComboBox, 1, 1, 1, 2)
self.advancedBookLabel = QtGui.QLabel(self.advancedTab)
self.advancedBookLabel.setObjectName(u'advancedBookLabel')
self.advancedLayout.addWidget(self.advancedBookLabel, 2, 0,
QtCore.Qt.AlignRight)
self.advancedBookComboBox = QtGui.QComboBox(self.advancedTab)
self.advancedBookComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.advancedBookComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.advancedBookComboBox.setObjectName(u'advancedBookComboBox')
self.advancedBookComboBox = media_item_combo_box(self.advancedTab,
u'advancedBookComboBox')
self.advancedBookLabel.setBuddy(self.advancedBookComboBox)
self.advancedLayout.addWidget(self.advancedBookComboBox, 2, 1, 1, 2)
self.advancedChapterLabel = QtGui.QLabel(self.advancedTab)
@ -202,17 +173,12 @@ class BibleMediaItem(MediaManagerItem):
self.advancedToVerse = QtGui.QComboBox(self.advancedTab)
self.advancedToVerse.setObjectName(u'advancedToVerse')
self.advancedLayout.addWidget(self.advancedToVerse, 5, 2)
self.advancedClearLabel = QtGui.QLabel(self.quickTab)
self.advancedClearLabel.setObjectName(u'advancedClearLabel')
self.advancedLayout.addWidget(self.advancedClearLabel, 6, 0,
QtCore.Qt.AlignRight)
self.advancedClearComboBox = QtGui.QComboBox(self.quickTab)
self.advancedClearComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.advancedClearComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.advancedClearComboBox.setObjectName(u'advancedClearComboBox')
self.advancedClearComboBox = media_item_combo_box(self.quickTab,
u'advancedClearComboBox')
self.advancedClearLabel.setBuddy(self.advancedClearComboBox)
self.advancedLayout.addWidget(self.advancedClearComboBox, 6, 1, 1, 2)
self.advancedSearchButtonLayout = QtGui.QHBoxLayout()
@ -224,8 +190,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
@ -239,8 +204,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
@ -254,9 +219,6 @@ class BibleMediaItem(MediaManagerItem):
QtCore.QObject.connect(self.quickSearchEdit,
QtCore.SIGNAL(u'returnPressed()'), self.onQuickSearchButton)
def addListViewToToolBar(self):
MediaManagerItem.addListViewToToolBar(self)
def configUpdated(self):
log.debug(u'configUpdated')
if QtCore.QSettings().value(self.settingsSection + u'/second bibles',
@ -277,8 +239,6 @@ class BibleMediaItem(MediaManagerItem):
translate('BiblesPlugin.MediaItem', '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(
@ -303,10 +263,6 @@ class BibleMediaItem(MediaManagerItem):
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.quickClearComboBox.addItem(
translate('BiblesPlugin.MediaItem', 'Clear'))
self.quickClearComboBox.addItem(
@ -390,7 +346,8 @@ class BibleMediaItem(MediaManagerItem):
verse_count = self.parent.manager.get_verse_count(bible, book, 1)
if verse_count == 0:
self.advancedSearchButton.setEnabled(False)
criticalErrorMessageBox(message=translate('BiblePlugin.MediaItem',
critical_error_message_box(
message=translate('BiblePlugin.MediaItem',
'Bible not fully loaded'))
else:
self.advancedSearchButton.setEnabled(True)
@ -403,20 +360,18 @@ 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:
book_data = bibles[bible].get_books()
books = [book.name for book in book_data]
books.sort()
completer = QtGui.QCompleter(books)
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.quickSearchEdit.setCompleter(completer)
add_widget_completer(books, self.quickSearchEdit)
def onAdvancedVersionComboBox(self):
self.initialiseBible(
@ -528,19 +483,7 @@ class BibleMediaItem(MediaManagerItem):
if self.advancedClearComboBox.currentIndex() == 0:
self.listView.clear()
if self.listView.count() != 0:
# Check if the first item is a second bible item or not.
bitem = self.listView.item(0)
item_second_bible = self._decodeQtObject(bitem, 'second_bible')
if item_second_bible and second_bible or not item_second_bible and \
not second_bible:
self.displayResults(bible, second_bible)
elif criticalErrorMessageBox(
message=translate('BiblePlugin.MediaItem',
'You cannot combine single and second bible verses. Do you '
'want to delete your search results and start a new search?'),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self.listView.clear()
self.displayResults(bible, second_bible)
self.__checkSecondBible(bible, second_bible)
else:
self.displayResults(bible, second_bible)
Receiver.send_message(u'cursor_normal')
@ -550,7 +493,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)
@ -558,8 +501,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(
@ -580,24 +523,30 @@ class BibleMediaItem(MediaManagerItem):
if self.quickClearComboBox.currentIndex() == 0:
self.listView.clear()
if self.listView.count() != 0 and self.search_results:
bitem = self.listView.item(0)
item_second_bible = self._decodeQtObject(bitem, 'second_bible')
if item_second_bible and second_bible or not item_second_bible and \
not second_bible:
self.displayResults(bible, second_bible)
elif criticalErrorMessageBox(
message=translate('BiblePlugin.MediaItem',
'You cannot combine single and second bible verses. Do you '
'want to delete your search results and start a new search?'),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self.listView.clear()
self.displayResults(bible, second_bible)
self.__checkSecondBible(bible, second_bible)
elif self.search_results:
self.displayResults(bible, second_bible)
self.quickSearchButton.setEnabled(True)
Receiver.send_message(u'cursor_normal')
Receiver.send_message(u'openlp_process_events')
def __checkSecondBible(self, bible, second_bible):
"""
Check if the first item is a second bible item or not.
"""
bitem = self.listView.item(0)
item_second_bible = self._decodeQtObject(bitem, 'second_bible')
if item_second_bible and second_bible or not item_second_bible and \
not second_bible:
self.displayResults(bible, second_bible)
elif critical_error_message_box(
message=translate('BiblePlugin.MediaItem',
'You cannot combine single and second bible verses. Do you '
'want to delete your search results and start a new search?'),
parent=self, question=True) == QtGui.QMessageBox.Yes:
self.listView.clear()
self.displayResults(bible, second_bible)
def displayResults(self, bible, second_bible=u''):
"""
Displays the search results in the media manager. All data needed for

View File

@ -38,7 +38,6 @@ class OpenSongBible(BibleDB):
"""
OpenSong Bible format importer class.
"""
def __init__(self, parent, **kwargs):
"""
Constructor to create and set up an instance of the OpenSongBible
@ -81,14 +80,13 @@ class OpenSongBible(BibleDB):
db_book.id,
int(chapter.attrib[u'n'].split()[-1]),
int(verse.attrib[u'n']),
unicode(verse.text)
)
Receiver.send_message(u'openlp_process_events')
unicode(verse.text))
self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.Opensong', 'Importing %s %s...',
'Importing <book name> <chapter>...')) %
(db_book.name, int(chapter.attrib[u'n'].split()[-1])))
self.session.commit()
self.session.commit()
Receiver.send_message(u'openlp_process_events')
except (IOError, AttributeError):
log.exception(u'Loading bible from OpenSong file failed')
success = False

View File

@ -19,7 +19,7 @@ IBS-fordítás (Új Károli), KAR
King James Version, KJV
Luther 1984, LUT
Septuaginta, LXX
Neue Genfer Übersetzung, NGÜ
Neue Genfer Übersetzung, NGU
New International Readers Version, NIRV
New International Version, NIV
Neues Leben, NL

1 عربي ARA
19 King James Version KJV
20 Luther 1984 LUT
21 Septuaginta LXX
22 Neue Genfer Übersetzung NGÜ NGU
23 New International Readers Version NIRV
24 New International Version NIV
25 Neues Leben NL

View File

@ -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.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', '<strong>Custom Plugin</strong>'
'<br />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):
"""

View File

@ -27,6 +27,8 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
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):
def setupUi(self, customEditDialog):
@ -58,22 +60,21 @@ class Ui_CustomEditDialog(object):
self.addButton.setObjectName(u'addButton')
self.buttonLayout.addWidget(self.addButton)
self.editButton = QtGui.QPushButton(customEditDialog)
self.editButton.setEnabled(False)
self.editButton.setObjectName(u'editButton')
self.buttonLayout.addWidget(self.editButton)
self.editAllButton = QtGui.QPushButton(customEditDialog)
self.editAllButton.setObjectName(u'editAllButton')
self.buttonLayout.addWidget(self.editAllButton)
self.deleteButton = QtGui.QPushButton(customEditDialog)
self.deleteButton.setObjectName(u'deleteButton')
self.deleteButton = create_delete_push_button(customEditDialog)
self.deleteButton.setEnabled(False)
self.buttonLayout.addWidget(self.deleteButton)
self.buttonLayout.addStretch()
self.upButton = QtGui.QPushButton(customEditDialog)
self.upButton.setIcon(build_icon(u':/services/service_up.png'))
self.upButton.setObjectName(u'upButton')
self.upButton, self.downButton = create_up_down_push_button_set(
customEditDialog)
self.upButton.setEnabled(False)
self.downButton.setEnabled(False)
self.buttonLayout.addWidget(self.upButton)
self.downButton = QtGui.QPushButton(customEditDialog)
self.downButton.setIcon(build_icon(u':/services/service_down.png'))
self.downButton.setObjectName(u'downButton')
self.buttonLayout.addWidget(self.downButton)
self.centralLayout.addLayout(self.buttonLayout)
self.dialogLayout.addLayout(self.centralLayout)
@ -93,36 +94,24 @@ class Ui_CustomEditDialog(object):
self.creditLabel.setBuddy(self.creditEdit)
self.bottomFormLayout.addRow(self.creditLabel, self.creditEdit)
self.dialogLayout.addLayout(self.bottomFormLayout)
self.buttonBox = QtGui.QDialogButtonBox(customEditDialog)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
QtGui.QDialogButtonBox.Save)
self.buttonBox.setObjectName(u'buttonBox')
self.buttonBox = create_accept_reject_button_box(customEditDialog)
self.previewButton = QtGui.QPushButton()
self.buttonBox.addButton(
self.previewButton, QtGui.QDialogButtonBox.ActionRole)
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(customEditDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
customEditDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
customEditDialog.closePressed)
QtCore.QMetaObject.connectSlotsByName(customEditDialog)
def retranslateUi(self, customEditDialog):
customEditDialog.setWindowTitle(
translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides'))
self.upButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Move slide up one '
'position.'))
self.downButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Move slide down one '
'position.'))
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.'))
@ -131,12 +120,9 @@ class Ui_CustomEditDialog(object):
self.editAllButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Edit all the slides at '
'once.'))
self.deleteButton.setText(
translate('CustomPlugin.EditCustomForm', '&Delete'))
self.deleteButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Delete the selected '
'slide.'))
self.themeLabel.setText(
translate('CustomPlugin.EditCustomForm', 'The&me:'))
self.creditLabel.setText(
translate('CustomPlugin.EditCustomForm', '&Credits:'))
self.previewButton.setText(
translate('CustomPlugin.EditCustomForm', 'Save && Preview'))

View File

@ -29,7 +29,7 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate
from openlp.core.ui import criticalErrorMessageBox
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser
from openlp.plugins.custom.lib.db import CustomSlide
from editcustomdialog import Ui_CustomEditDialog
@ -48,52 +48,22 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
"""
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
# Create other objects and forms.
self.manager = manager
self.editSlideForm = EditCustomSlideForm(self)
# Connecting signals and slots
self.previewButton = QtGui.QPushButton()
self.previewButton.setText(
translate('CustomPlugin.EditCustomForm', 'Save && Preview'))
self.buttonBox.addButton(
self.previewButton, QtGui.QDialogButtonBox.ActionRole)
QtCore.QObject.connect(self.buttonBox,
QtCore.SIGNAL(u'clicked(QAbstractButton*)'), self.onPreview)
QtCore.QObject.connect(self.previewButton,
QtCore.SIGNAL(u'pressed()'), self.onPreviewButtonPressed)
QtCore.QObject.connect(self.addButton,
QtCore.SIGNAL(u'pressed()'), self.onAddButtonPressed)
QtCore.QObject.connect(self.editButton,
QtCore.SIGNAL(u'pressed()'), self.onEditButtonPressed)
QtCore.QObject.connect(self.editAllButton,
QtCore.SIGNAL(u'pressed()'), self.onEditAllButtonPressed)
QtCore.QObject.connect(self.deleteButton,
QtCore.SIGNAL(u'pressed()'), self.onDeleteButtonPressed)
QtCore.QObject.connect(self.upButton,
QtCore.SIGNAL(u'pressed()'), self.onUpButtonPressed)
QtCore.QObject.connect(self.downButton,
QtCore.SIGNAL(u'pressed()'), self.onDownButtonPressed)
QtCore.QObject.connect(self.slideListView,
QtCore.SIGNAL(u'itemClicked(QListWidgetItem*)'),
self.onSlideListViewPressed)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
# Create other objects and forms.
self.manager = manager
self.editSlideForm = EditCustomSlideForm(self)
self.initialise()
def onPreview(self, button):
log.debug(u'onPreview')
if button.text() == unicode(translate('CustomPlugin.EditCustomForm',
'Save && Preview')) and self.saveCustom():
Receiver.send_message(u'custom_preview')
def initialise(self):
self.addButton.setEnabled(True)
self.deleteButton.setEnabled(False)
self.editButton.setEnabled(False)
self.editAllButton.setEnabled(True)
self.titleEdit.setText(u'')
self.creditEdit.setText(u'')
self.slideListView.clear()
# Make sure we have a new item.
self.customSlide = CustomSlide()
QtCore.QObject.connect(self.slideListView,
QtCore.SIGNAL(u'currentRowChanged(int)'), self.onCurrentRowChanged)
def loadThemes(self, themelist):
self.themeComboBox.clear()
@ -112,9 +82,13 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
States whether the custom is edited while being previewed in the
preview panel.
"""
self.customSlide = CustomSlide()
self.initialise()
if id != 0:
self.slideListView.clear()
if id == 0:
self.customSlide = CustomSlide()
self.titleEdit.setText(u'')
self.creditEdit.setText(u'')
self.themeComboBox.setCurrentIndex(0)
else:
self.customSlide = self.manager.get_object(CustomSlide, id)
self.titleEdit.setText(self.customSlide.title)
self.creditEdit.setText(self.customSlide.credits)
@ -128,31 +102,26 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
if id == -1:
id = 0
self.themeComboBox.setCurrentIndex(id)
else:
self.themeComboBox.setCurrentIndex(0)
self.editAllButton.setEnabled(False)
# If not preview hide the preview button.
self.previewButton.setVisible(False)
if preview:
self.previewButton.setVisible(True)
def closePressed(self):
def reject(self):
Receiver.send_message(u'custom_edit_clear')
self.close()
QtGui.QDialog.reject(self)
def accept(self):
log.debug(u'accept')
if self.saveCustom():
Receiver.send_message(u'custom_load_list')
self.close()
QtGui.QDialog.accept(self)
def saveCustom(self):
"""
Saves the custom.
"""
valid, message = self._validate()
if not valid:
criticalErrorMessageBox(message=message)
if not self._validate():
return False
sxml = CustomXMLBuilder()
sxml.new_document()
@ -168,14 +137,14 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.customSlide.theme_name = unicode(self.themeComboBox.currentText())
return self.manager.save_object(self.customSlide)
def onUpButtonPressed(self):
def onUpButtonClicked(self):
selectedRow = self.slideListView.currentRow()
if selectedRow != 0:
qw = self.slideListView.takeItem(selectedRow)
self.slideListView.insertItem(selectedRow - 1, qw)
self.slideListView.setCurrentRow(selectedRow - 1)
def onDownButtonPressed(self):
def onDownButtonClicked(self):
selectedRow = self.slideListView.currentRow()
# zero base arrays
if selectedRow != self.slideListView.count() - 1:
@ -183,16 +152,11 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.slideListView.insertItem(selectedRow + 1, qw)
self.slideListView.setCurrentRow(selectedRow + 1)
def onSlideListViewPressed(self, item):
self.deleteButton.setEnabled(True)
self.editButton.setEnabled(True)
def onAddButtonPressed(self):
self.editSlideForm.setText(u'')
if self.editSlideForm.exec_():
for slide in self.editSlideForm.getText():
self.slideListView.addItem(slide)
self.editAllButton.setEnabled(True)
def onEditButtonPressed(self):
self.editSlideForm.setText(self.slideListView.currentItem().text())
@ -203,16 +167,23 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
"""
Edits all slides.
"""
if self.slideListView.count() > 0:
slide_list = u''
for row in range(0, self.slideListView.count()):
item = self.slideListView.item(row)
slide_list += item.text()
if row != self.slideListView.count() - 1:
slide_list += u'\n[---]\n'
self.editSlideForm.setText(slide_list)
if self.editSlideForm.exec_():
self.updateSlideList(self.editSlideForm.getText(), True)
slide_list = u''
for row in range(0, self.slideListView.count()):
item = self.slideListView.item(row)
slide_list += item.text()
if row != self.slideListView.count() - 1:
slide_list += u'\n[---]\n'
self.editSlideForm.setText(slide_list)
if self.editSlideForm.exec_():
self.updateSlideList(self.editSlideForm.getText(), True)
def onPreviewButtonPressed(self):
"""
Save the custom item and preview it.
"""
log.debug(u'onPreview')
if self.saveCustom():
Receiver.send_message(u'custom_preview')
def updateSlideList(self, slides, edit_all=False):
"""
@ -243,14 +214,41 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.slideListView.addItem(slide)
self.slideListView.repaint()
def onDeleteButtonPressed(self):
def onDeleteButtonClicked(self):
"""
Removes the current row from the list.
"""
self.slideListView.takeItem(self.slideListView.currentRow())
self.editButton.setEnabled(True)
self.editAllButton.setEnabled(True)
if self.slideListView.count() == 0:
if self.slideListView.currentRow() == 0:
self.upButton.setEnabled(False)
if self.slideListView.currentRow() == self.slideListView.count():
self.downButton.setEnabled(False)
def onCurrentRowChanged(self, row):
"""
Called when the *slideListView*'s current row has been changed. This
enables or disables buttons which require an slide to act on.
``row``
The row (int). If there is no current row, the value is -1.
"""
if row == -1:
self.deleteButton.setEnabled(False)
self.editButton.setEnabled(False)
self.editAllButton.setEnabled(False)
self.upButton.setEnabled(False)
self.downButton.setEnabled(False)
else:
self.deleteButton.setEnabled(True)
self.editButton.setEnabled(True)
# Decide if the up/down buttons should be enabled or not.
if self.slideListView.count() - 1 == row:
self.downButton.setEnabled(False)
else:
self.downButton.setEnabled(True)
if row == 0:
self.upButton.setEnabled(False)
else:
self.upButton.setEnabled(True)
def _validate(self):
"""
@ -259,10 +257,14 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
# We must have a title.
if len(self.titleEdit.displayText()) == 0:
self.titleEdit.setFocus()
return False, translate('CustomPlugin.EditCustomForm',
'You need to type in a title.')
critical_error_message_box(
message=translate('CustomPlugin.EditCustomForm',
'You need to type in a title.'))
return False
# We must have at least one slide.
if self.slideListView.count() == 0:
return False, translate('CustomPlugin.EditCustomForm',
'You need to add at least one slide')
return True, u''
critical_error_message_box(
message=translate('CustomPlugin.EditCustomForm',
'You need to add at least one slide'))
return False
return True

View File

@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, SpellTextEdit
from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_CustomSlideEditDialog(object):
def setupUi(self, customSlideEditDialog):
@ -36,20 +37,13 @@ class Ui_CustomSlideEditDialog(object):
self.slideTextEdit = SpellTextEdit(self)
self.slideTextEdit.setObjectName(u'slideTextEdit')
self.dialogLayout.addWidget(self.slideTextEdit)
self.buttonBox = QtGui.QDialogButtonBox(customSlideEditDialog)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
QtGui.QDialogButtonBox.Save)
self.buttonBox.setObjectName(u'buttonBox')
self.buttonBox = create_accept_reject_button_box(customSlideEditDialog)
self.splitButton = QtGui.QPushButton(customSlideEditDialog)
self.splitButton.setObjectName(u'splitButton')
self.buttonBox.addButton(self.splitButton,
QtGui.QDialogButtonBox.ActionRole)
self.dialogLayout.addWidget(self.buttonBox)
self.retranslateUi(customSlideEditDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
customSlideEditDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
customSlideEditDialog.reject)
QtCore.QMetaObject.connectSlotsByName(customSlideEditDialog)
def retranslateUi(self, customSlideEditDialog):

View File

@ -28,18 +28,13 @@ 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, \
translate, check_item_selected
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 +43,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
@ -68,11 +60,8 @@ class CustomMediaItem(MediaManagerItem):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
def requiredIcons(self):
MediaManagerItem.requiredIcons(self)
def initialise(self):
self.loadCustomListView(self.manager.get_all_objects(
self.loadList(self.manager.get_all_objects(
CustomSlide, order_by_ref=CustomSlide.title))
# Called to redisplay the custom list screen edith from a search
# or from the exit of the Custom edit dialog. If remote editing is
@ -83,7 +72,7 @@ class CustomMediaItem(MediaManagerItem):
self.onPreviewClick()
self.onRemoteEditClear()
def loadCustomListView(self, list):
def loadList(self, list):
self.listView.clear()
for customSlide in list:
custom_name = QtGui.QListWidgetItem(customSlide.title)
@ -149,16 +138,7 @@ class CustomMediaItem(MediaManagerItem):
raw_footer = []
slide = None
theme = None
if item is None:
if self.remoteTriggered is None:
item = self.listView.currentItem()
if item is None:
return False
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
else:
item_id = self.remoteCustom
else:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
item_id = self._getIdOfItemToGenerate(item, self.remoteCustom)
service_item.add_capability(ItemCapabilities.AllowsEdit)
service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop)
@ -182,4 +162,4 @@ class CustomMediaItem(MediaManagerItem):
else:
raw_footer.append(u'')
service_item.raw_footer = raw_footer
return True
return True

View File

@ -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', '<strong>Image Plugin</strong>'
'<br />The image plugin provides displaying of images.<br />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)

View File

@ -29,22 +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
from openlp.core.ui import criticalErrorMessageBox
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.
@ -53,25 +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',
'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'))
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)
@ -83,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),
@ -95,7 +80,6 @@ class ImageMediaItem(MediaManagerItem):
def addListViewToToolBar(self):
MediaManagerItem.addListViewToToolBar(self)
self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.listView.addAction(self.replaceAction)
def addEndHeaderBar(self):
@ -123,26 +107,26 @@ class ImageMediaItem(MediaManagerItem):
self.settingsSection, self.getFileList())
def loadList(self, list):
for file in list:
filename = os.path.split(unicode(file))[1]
for imageFile in list:
filename = os.path.split(unicode(imageFile))[1]
thumb = os.path.join(self.servicePath, filename)
if os.path.exists(thumb):
if self.validate(file, thumb):
if self.validate(imageFile, thumb):
icon = build_icon(thumb)
else:
icon = build_icon(u':/general/general_delete.png')
else:
icon = self.iconFromFile(file, thumb)
icon = self.iconFromFile(imageFile, thumb)
item_name = QtGui.QListWidgetItem(filename)
item_name.setIcon(icon)
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(file))
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
self.listView.addItem(item_name)
def generateSlideData(self, service_item, item=None, xmlVersion=False):
items = self.listView.selectedIndexes()
if items:
service_item.title = unicode(
translate('ImagePlugin.MediaItem', 'Image(s)'))
translate('ImagePlugin.MediaItem', 'Images'))
service_item.add_capability(ItemCapabilities.AllowsMaintain)
service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop)
@ -161,7 +145,7 @@ class ImageMediaItem(MediaManagerItem):
items.remove(item)
# We cannot continue, as all images do not exist.
if not items:
criticalErrorMessageBox(
critical_error_message_box(
translate('ImagePlugin.MediaItem', 'Missing Image(s)'),
unicode(translate('ImagePlugin.MediaItem',
'The following image(s) no longer exist: %s')) %
@ -193,6 +177,12 @@ class ImageMediaItem(MediaManagerItem):
self.resetAction.setVisible(False)
self.parent.liveController.display.resetImage()
def liveThemeChanged(self):
"""
Triggered by the change of theme in the slide controller
"""
self.resetAction.setVisible(False)
def onReplaceClick(self):
"""
Called to replace Live backgound with the image selected.
@ -208,11 +198,8 @@ class ImageMediaItem(MediaManagerItem):
self.parent.liveController.display.directImage(name, filename)
self.resetAction.setVisible(True)
else:
criticalErrorMessageBox(
critical_error_message_box(
translate('ImagePlugin.MediaItem', 'Live Background Error'),
unicode(translate('ImagePlugin.MediaItem',
'There was a problem replacing your background, '
'the image file "%s" no longer exists.')) % filename)
def onPreviewClick(self):
MediaManagerItem.onPreviewClick(self)

View File

@ -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
from openlp.core.ui import criticalErrorMessageBox
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,28 +45,27 @@ 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.serviceItemIconName = u':/media/image_clapperboard.png'
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'))
'Videos (%s);;Audio (%s);;%s (*)')) % (self.parent.video_list,
self.parent.audio_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)
@ -81,7 +75,6 @@ class MediaMediaItem(MediaManagerItem):
def addListViewToToolBar(self):
MediaManagerItem.addListViewToToolBar(self)
self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
self.listView.addAction(self.replaceAction)
def addEndHeaderBar(self):
@ -99,6 +92,12 @@ class MediaMediaItem(MediaManagerItem):
self.resetAction.setVisible(False)
self.parent.liveController.display.resetVideo()
def videobackgroundReplaced(self):
"""
Triggered by main display on change of serviceitem
"""
self.resetAction.setVisible(False)
def onReplaceClick(self):
"""
Called to replace Live backgound with the media selected.
@ -113,7 +112,7 @@ class MediaMediaItem(MediaManagerItem):
self.parent.liveController.display.video(filename, 0, True)
self.resetAction.setVisible(True)
else:
criticalErrorMessageBox(translate('MediaPlugin.MediaItem',
critical_error_message_box(translate('MediaPlugin.MediaItem',
'Live Background Error'),
unicode(translate('MediaPlugin.MediaItem',
'There was a problem replacing your background, '
@ -126,26 +125,34 @@ class MediaMediaItem(MediaManagerItem):
return False
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
self.MediaState = None
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.mediaObject.setCurrentSource(Phonon.MediaSource(filename))
self.mediaObject.play()
service_item.title = unicode(
translate('MediaPlugin.MediaItem', 'Media'))
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:
# File is no longer present
criticalErrorMessageBox(
critical_error_message_box(
translate('MediaPlugin.MediaItem', 'Missing Media File'),
unicode(translate('MediaPlugin.MediaItem',
'The file %s no longer exists.')) % filename)
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))
@ -171,3 +178,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()

View File

@ -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'))

View File

@ -38,7 +38,8 @@ 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)
@ -75,13 +76,6 @@ class MediaPlugin(Plugin):
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 about(self):
about_text = translate('MediaPlugin', '<strong>Media Plugin</strong>'
'<br />The media plugin provides playback of audio and video.')
@ -101,45 +95,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)

View File

@ -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,17 +171,19 @@ 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
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:
log.exception(u'Failed to terminate OpenOffice')
return
docs = desktop.getComponents()
if docs.hasElements():
log.debug(u'OpenOffice not terminated')
log.debug(u'OpenOffice not terminated as docs are still open')
else:
try:
desktop.terminate()
@ -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):
"""
@ -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

View File

@ -29,24 +29,13 @@ 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.ui import criticalErrorMessageBox
from openlp.core.lib import MediaManagerItem, 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.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 +50,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(),
@ -116,12 +102,8 @@ class PresentationMediaItem(MediaManagerItem):
self.displayLayout.setObjectName(u'displayLayout')
self.displayTypeLabel = QtGui.QLabel(self.presentationWidget)
self.displayTypeLabel.setObjectName(u'displayTypeLabel')
self.displayTypeComboBox = QtGui.QComboBox(self.presentationWidget)
self.displayTypeComboBox.setSizeAdjustPolicy(
QtGui.QComboBox.AdjustToMinimumContentsLength)
self.displayTypeComboBox.setSizePolicy(
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Fixed)
self.displayTypeComboBox.setObjectName(u'displayTypeComboBox')
self.displayTypeComboBox = media_item_combo_box(
self.presentationWidget, u'displayTypeComboBox')
self.displayTypeLabel.setBuddy(self.displayTypeComboBox)
self.displayLayout.addRow(self.displayTypeLabel,
self.displayTypeComboBox)
@ -181,7 +163,7 @@ class PresentationMediaItem(MediaManagerItem):
filename = os.path.split(unicode(file))[1]
if titles.count(filename) > 0:
if not initialLoad:
criticalErrorMessageBox(
critical_error_message_box(
translate('PresentationPlugin.MediaItem',
'File Exists'),
translate('PresentationPlugin.MediaItem',
@ -190,7 +172,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:
@ -205,7 +187,7 @@ class PresentationMediaItem(MediaManagerItem):
if initialLoad:
icon = build_icon(u':/general/general_delete.png')
else:
criticalErrorMessageBox(
critical_error_message_box(
self, translate('PresentationPlugin.MediaItem',
'Unsupported File'),
translate('PresentationPlugin.MediaItem',
@ -230,7 +212,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:
@ -250,6 +232,7 @@ class PresentationMediaItem(MediaManagerItem):
service_item.title = unicode(self.displayTypeComboBox.currentText())
service_item.shortname = unicode(self.displayTypeComboBox.currentText())
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
service_item.add_capability(ItemCapabilities.AllowsDetailedTitleDisplay)
shortname = service_item.shortname
if shortname:
for item in items:
@ -263,7 +246,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
@ -277,7 +260,7 @@ class PresentationMediaItem(MediaManagerItem):
return True
else:
# File is no longer present
criticalErrorMessageBox(
critical_error_message_box(
translate('PresentationPlugin.MediaItem',
'Missing Presentation'),
unicode(translate('PresentationPlugin.MediaItem',
@ -286,7 +269,7 @@ class PresentationMediaItem(MediaManagerItem):
return False
else:
# File is no longer present
criticalErrorMessageBox(
critical_error_message_box(
translate('PresentationPlugin.MediaItem',
'Missing Presentation'),
unicode(translate('PresentationPlugin.MediaItem',

View File

@ -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?
@ -116,7 +116,7 @@ class Controller(object):
def last(self):
"""
Based on the handler passed at startup triggers the first slide
Based on the handler passed at startup triggers the last slide
"""
log.debug(u'Live = %s, last' % self.is_live)
if not self.is_live:

View File

@ -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
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

View File

@ -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)
self.controller.process.PrevStep(self.pptid)

View File

@ -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 ''
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

View File

@ -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):
"""
@ -85,9 +86,7 @@ class PresentationTab(SettingsTab):
checkbox.setText(
unicode(translate('PresentationPlugin.PresentationTab',
'%s (unvailable)')) % controller.name)
self.AdvancedGroupBox.setTitle(
translate('PresentationPlugin.PresentationTab',
'Advanced'))
self.AdvancedGroupBox.setTitle(UiStrings.Advanced)
self.OverrideAppCheckBox.setText(
translate('PresentationPlugin.PresentationTab',
'Allow presentation application to be overriden'))

View File

@ -74,7 +74,11 @@ class PresentationPlugin(Plugin):
self.insertToolboxItem()
for controller in self.controllers:
if self.controllers[controller].enabled():
self.controllers[controller].start_process()
try:
self.controllers[controller].start_process()
except:
log.exception(u'Failed to start controller process')
self.controllers[controller].available = False
self.mediaItem.buildFileMaskString()
def finalise(self):
@ -163,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)

View File

@ -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

View File

@ -57,4 +57,6 @@ from songbookform import SongBookForm
from editverseform import EditVerseForm
from editsongform import EditSongForm
from songmaintenanceform import SongMaintenanceForm
from songimportform import SongImportForm
from songimportform import SongImportForm
from songexportform import SongExportForm

View File

@ -27,6 +27,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
from openlp.core.lib.ui import create_accept_reject_button_box
class Ui_AuthorsDialog(object):
def setupUi(self, authorsDialog):
@ -55,17 +56,10 @@ class Ui_AuthorsDialog(object):
self.displayLabel.setBuddy(self.displayEdit)
self.authorLayout.addRow(self.displayLabel, self.displayEdit)
self.dialogLayout.addLayout(self.authorLayout)
self.buttonBox = QtGui.QDialogButtonBox(authorsDialog)
self.buttonBox.setStandardButtons(
QtGui.QDialogButtonBox.Save | QtGui.QDialogButtonBox.Cancel)
self.buttonBox.setObjectName(u'buttonBox')
self.dialogLayout.addWidget(self.buttonBox)
self.dialogLayout.addWidget(
create_accept_reject_button_box(authorsDialog))
self.retranslateUi(authorsDialog)
authorsDialog.setMaximumHeight(authorsDialog.sizeHint().height())
QtCore.QObject.connect(self.buttonBox,
QtCore.SIGNAL(u'accepted()'), authorsDialog.accept)
QtCore.QObject.connect(self.buttonBox,
QtCore.SIGNAL(u'rejected()'), authorsDialog.reject)
QtCore.QMetaObject.connectSlotsByName(authorsDialog)
def retranslateUi(self, authorsDialog):

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