forked from openlp/openlp
Head
This commit is contained in:
commit
3c464a4a0f
19
OpenLP.spec
19
OpenLP.spec
@ -1,19 +0,0 @@
|
||||
# -*- mode: python -*-
|
||||
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'openlp.pyw'],
|
||||
pathex=[os.path.abspath('.')])
|
||||
pyz = PYZ(a.pure)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
exclude_binaries=1,
|
||||
name=os.path.join('build\\pyi.win32\\OpenLP', 'OpenLP.exe'),
|
||||
debug=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False , icon='resources\\images\\OpenLP.ico')
|
||||
coll = COLLECT( exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name=os.path.join('dist', 'OpenLP'))
|
@ -17,7 +17,7 @@ import sys
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.append(os.path.abspath(os.path.join('..', '..')))
|
||||
sys.path.insert(0, os.path.abspath(os.path.join('..', '..')))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
|
@ -60,12 +60,6 @@
|
||||
.. autoclass:: openlp.core.lib.settingstab.SettingsTab
|
||||
:members:
|
||||
|
||||
:mod:`ThemeXML`
|
||||
---------------
|
||||
|
||||
.. autoclass:: openlp.core.lib.themexmlhandler.ThemeXML
|
||||
:members:
|
||||
|
||||
:mod:`OpenLPToolbar`
|
||||
--------------------
|
||||
|
||||
|
22
documentation/source/manual/index.rst
Normal file
22
documentation/source/manual/index.rst
Normal file
@ -0,0 +1,22 @@
|
||||
.. OpenLP documentation master file, created by
|
||||
sphinx-quickstart on Thu Sep 30 21:24:54 2010.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to OpenLP's documentation
|
||||
==================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
introduction
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
46
documentation/source/manual/introduction.rst
Normal file
46
documentation/source/manual/introduction.rst
Normal file
@ -0,0 +1,46 @@
|
||||
=============
|
||||
Introduction
|
||||
=============
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
OpenLP is an open source lyrics projection application developed specifically
|
||||
for churches. It is licensed under the GNU Generic Public License, which means
|
||||
that it is free to use and distribute, and it stays free.
|
||||
|
||||
Lyrics Projection
|
||||
-----------------
|
||||
|
||||
OpenLP's purpose is to project the lyrics of songs and Bible verses using a
|
||||
computer and a data projector. OpenLP also has the ability to project videos,
|
||||
images, and also play audio. OpenLP also is highly customizable providing users
|
||||
with the ability to set up a wide variety of themes, including themes with
|
||||
video backgrounds.
|
||||
|
||||
Open Source
|
||||
-----------
|
||||
|
||||
OpenLP is open source software. This means that the source code (the
|
||||
programming instructions the developers write) is open to anyone who wants to
|
||||
look at it. This gives you, the end user, a few freedoms.
|
||||
|
||||
From a developer's perspective, it gives you the freedom to inspect the code
|
||||
and make sure that it is not malicious. Also, it gives you the freedom to
|
||||
change the code and the freedom to "fork" the project and make it your own.
|
||||
|
||||
For end users open source software gives you the freedom to use software as
|
||||
you wish. You are not required to pay for the software and you are free to
|
||||
make copies and distribute it to anyone you want.
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
The GNU General Public License was specifically chosen because it ensures the
|
||||
above mentioned freedoms. It specifically states that you are not allowed
|
||||
to charge for the software, and that you have to distribute the source code as
|
||||
well.
|
||||
|
||||
You can find a copy of the GNU General Public License from the Help menu
|
||||
selecting about OpenLP or on-line
|
||||
at: http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
@ -1,7 +1,7 @@
|
||||
.. _plugins-bibles:
|
||||
|
||||
:mod:`bibles` Plugin
|
||||
====================
|
||||
Bibles Plugin
|
||||
=============
|
||||
|
||||
.. automodule:: openlp.plugins.bibles
|
||||
:members:
|
||||
@ -60,8 +60,8 @@
|
||||
.. autoclass:: openlp.plugins.bibles.lib.http.HTTPBible
|
||||
:members:
|
||||
|
||||
:mod:`bibleOSISimpl`
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
:mod:`osis`
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.bibles.lib.osis
|
||||
:members:
|
||||
@ -69,18 +69,21 @@
|
||||
.. autoclass:: openlp.plugins.bibles.lib.osis.OSISBible
|
||||
:members:
|
||||
|
||||
:mod:`opensong`
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.bibles.lib.opensong
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.bibles.lib.opensong.OpenSongBible
|
||||
:members:
|
||||
|
||||
:mod:`biblestab`
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.bibles.lib.biblestab
|
||||
:members:
|
||||
|
||||
:mod:`common`
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.bibles.lib.common
|
||||
:members:
|
||||
|
||||
:mod:`manager`
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
|
8
documentation/source/plugins/images.rst
Normal file
8
documentation/source/plugins/images.rst
Normal file
@ -0,0 +1,8 @@
|
||||
.. _plugins-images:
|
||||
|
||||
Images Plugin
|
||||
=============
|
||||
|
||||
.. automodule:: openlp.plugins.images
|
||||
:members:
|
||||
|
@ -11,24 +11,9 @@
|
||||
|
||||
songs
|
||||
bibles
|
||||
|
||||
:mod:`presentations` Plugin
|
||||
---------------------------
|
||||
|
||||
.. automodule:: openlp.plugins.presentations
|
||||
:members:
|
||||
|
||||
:mod:`media` Plugin
|
||||
-------------------
|
||||
|
||||
.. automodule:: openlp.plugins.media
|
||||
:members:
|
||||
|
||||
:mod:`images` Plugin
|
||||
--------------------
|
||||
|
||||
.. automodule:: openlp.plugins.images
|
||||
:members:
|
||||
presentations
|
||||
media
|
||||
images
|
||||
|
||||
:mod:`custom` Plugin
|
||||
--------------------
|
||||
|
8
documentation/source/plugins/media.rst
Normal file
8
documentation/source/plugins/media.rst
Normal file
@ -0,0 +1,8 @@
|
||||
.. _plugins-media:
|
||||
|
||||
Media Plugin
|
||||
============
|
||||
|
||||
.. automodule:: openlp.plugins.media
|
||||
:members:
|
||||
|
40
documentation/source/plugins/presentations.rst
Normal file
40
documentation/source/plugins/presentations.rst
Normal file
@ -0,0 +1,40 @@
|
||||
.. _plugins-presentations:
|
||||
|
||||
Presentations Plugin
|
||||
====================
|
||||
|
||||
Plugin Class
|
||||
------------
|
||||
|
||||
.. autoclass:: openlp.plugins.presentations.presentationplugin.PresentationPlugin
|
||||
:members:
|
||||
|
||||
Helper Classes & Functions
|
||||
--------------------------
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.mediaitem
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.presentationtab
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.messagelistener
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.presentationcontroller
|
||||
:members:
|
||||
|
||||
Presentation Application Controllers
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.impresscontroller
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.pptviewcontroller
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.powerpointcontroller
|
||||
:members:
|
@ -1,13 +1,13 @@
|
||||
.. _plugins-songs:
|
||||
|
||||
:mod:`songs` Plugin
|
||||
===================
|
||||
Songs Plugin
|
||||
============
|
||||
|
||||
.. automodule:: openlp.plugins.songs
|
||||
:members:
|
||||
|
||||
:mod:`SongsPlugin` Class
|
||||
------------------------
|
||||
:class:`SongsPlugin` Class
|
||||
--------------------------
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.songsplugin.SongsPlugin
|
||||
:members:
|
||||
@ -18,8 +18,8 @@
|
||||
.. automodule:: openlp.plugins.songs.forms
|
||||
:members:
|
||||
|
||||
:mod:`AuthorsForm`
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
:class:`AuthorsForm`
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.authorsdialog.Ui_AuthorsDialog
|
||||
:members:
|
||||
@ -27,8 +27,8 @@
|
||||
.. autoclass:: openlp.plugins.songs.forms.authorsform.AuthorsForm
|
||||
:members:
|
||||
|
||||
:mod:`EditSongForm`
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
:class:`EditSongForm`
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.editsongdialog.Ui_EditSongDialog
|
||||
:members:
|
||||
@ -36,11 +36,158 @@
|
||||
.. autoclass:: openlp.plugins.songs.forms.editsongform.EditSongForm
|
||||
:members:
|
||||
|
||||
:mod:`EditVerseForm`
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
:class:`EditVerseForm`
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.editversedialog.Ui_EditVerseDialog
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.editverseform.EditVerseForm
|
||||
:members:
|
||||
|
||||
:class:`SongBookForm`
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.songbookdialog.Ui_SongBookDialog
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.songbookform.SongBookForm
|
||||
:members:
|
||||
|
||||
:class:`SongImportForm`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.songimportwizard.Ui_SongImportWizard
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.songimportform.ImportWizardForm
|
||||
:members:
|
||||
|
||||
:class:`SongMaintenanceForm`
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.songmaintenancedialog.Ui_SongMaintenanceDialog
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.songmaintenanceform.SongMaintenanceForm
|
||||
:members:
|
||||
|
||||
:class:`TopicsForm`
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.topicsdialog.Ui_TopicsDialog
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.forms.topicsform.TopicsForm
|
||||
:members:
|
||||
|
||||
:mod:`lib` Submodule
|
||||
--------------------
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib
|
||||
:members:
|
||||
|
||||
:mod:`cclifileimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.cclifileimport
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.lib.cclifileimport.CCLIFileImportError
|
||||
:members:
|
||||
|
||||
:mod:`db` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.db
|
||||
:members:
|
||||
|
||||
:mod:`ewimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.ewimport
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.lib.ewimport.FieldDescEntry
|
||||
:members:
|
||||
|
||||
:mod:`importer` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.importer
|
||||
:members:
|
||||
|
||||
:mod:`mediaitem` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.mediaitem
|
||||
:members:
|
||||
|
||||
.. autoclass:: openlp.plugins.songs.lib.mediaitem.SongListView
|
||||
:members:
|
||||
|
||||
:mod:`olp1import` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.olp1import
|
||||
:members:
|
||||
|
||||
:mod:`olpimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.olpimport
|
||||
:members:
|
||||
|
||||
:mod:`oooimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.oooimport
|
||||
:members:
|
||||
|
||||
:mod:`opensongimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.opensongimport
|
||||
:members:
|
||||
|
||||
:mod:`sofimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.sofimport
|
||||
:members:
|
||||
|
||||
:mod:`songbeamerimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.songbeamerimport
|
||||
:members:
|
||||
|
||||
:mod:`songimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.songimport
|
||||
:members:
|
||||
|
||||
:mod:`songstab` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.songstab
|
||||
:members:
|
||||
|
||||
:mod:`wowimport` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.wowimport
|
||||
:members:
|
||||
|
||||
:mod:`songxml` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.songxml
|
||||
:members:
|
||||
|
||||
:mod:`xml` Submodule
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. automodule:: openlp.plugins.songs.lib.xml
|
||||
:members:
|
||||
|
116
openlp.pyw
116
openlp.pyw
@ -30,6 +30,7 @@ import sys
|
||||
import logging
|
||||
from optparse import OptionParser
|
||||
from traceback import format_exception
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -71,6 +72,84 @@ class OpenLP(QtGui.QApplication):
|
||||
"""
|
||||
log.info(u'OpenLP Application Loaded')
|
||||
|
||||
def _get_version(self):
|
||||
"""
|
||||
Load and store current Application Version
|
||||
"""
|
||||
if u'--dev-version' 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
|
||||
from bzrlib.branch import Branch
|
||||
b = Branch.open_containing('.')[0]
|
||||
b.lock_read()
|
||||
try:
|
||||
# Get the branch's latest revision number.
|
||||
revno = b.revno()
|
||||
# Convert said revision number into a bzr revision id.
|
||||
revision_id = b.dotted_revno_to_revision_id((revno,))
|
||||
# Get a dict of tags, with the revision id as the key.
|
||||
tags = b.tags.get_reverse_tag_dict()
|
||||
# Check if the latest
|
||||
if revision_id in tags:
|
||||
full_version = u'%s' % tags[revision_id][0]
|
||||
else:
|
||||
full_version = '%s-bzr%s' % \
|
||||
(sorted(b.tags.get_tag_dict().keys())[-1], revno)
|
||||
finally:
|
||||
b.unlock()
|
||||
except:
|
||||
# Otherwise run the command line bzr client
|
||||
bzr = Popen((u'bzr', u'tags', u'--sort', u'time'), stdout=PIPE)
|
||||
output, error = bzr.communicate()
|
||||
code = bzr.wait()
|
||||
if code != 0:
|
||||
raise Exception(u'Error running bzr tags')
|
||||
lines = output.splitlines()
|
||||
if len(lines) == 0:
|
||||
tag = u'0.0.0'
|
||||
revision = u'0'
|
||||
else:
|
||||
tag, revision = lines[-1].split()
|
||||
bzr = Popen((u'bzr', u'log', u'--line', u'-r', u'-1'),
|
||||
stdout=PIPE)
|
||||
output, error = bzr.communicate()
|
||||
code = bzr.wait()
|
||||
if code != 0:
|
||||
raise Exception(u'Error running bzr log')
|
||||
latest = output.split(u':')[0]
|
||||
full_version = latest == revision and tag or \
|
||||
u'%s-bzr%s' % (tag, latest)
|
||||
else:
|
||||
# We're not running the development version, let's use the file
|
||||
filepath = AppLocation.get_directory(AppLocation.VersionDir)
|
||||
filepath = os.path.join(filepath, u'.version')
|
||||
fversion = None
|
||||
try:
|
||||
fversion = open(filepath, u'r')
|
||||
full_version = unicode(fversion.read()).rstrip()
|
||||
except IOError:
|
||||
log.exception('Error in version file.')
|
||||
full_version = u'0.0.0-bzr000'
|
||||
finally:
|
||||
if fversion:
|
||||
fversion.close()
|
||||
bits = full_version.split(u'-')
|
||||
app_version = {
|
||||
u'full': full_version,
|
||||
u'version': bits[0],
|
||||
u'build': bits[1] if len(bits) > 1 else None
|
||||
}
|
||||
if app_version[u'build']:
|
||||
log.info(
|
||||
u'Openlp version %s build %s',
|
||||
app_version[u'version'],
|
||||
app_version[u'build']
|
||||
)
|
||||
else:
|
||||
log.info(u'Openlp version %s' % app_version[u'version'])
|
||||
return app_version
|
||||
|
||||
def notify(self, obj, evt):
|
||||
#TODO needed for presentation exceptions
|
||||
return QtGui.QApplication.notify(self, obj, evt)
|
||||
@ -79,39 +158,7 @@ class OpenLP(QtGui.QApplication):
|
||||
"""
|
||||
Run the OpenLP application.
|
||||
"""
|
||||
#Load and store current Application Version
|
||||
filepath = AppLocation.get_directory(AppLocation.VersionDir)
|
||||
filepath = os.path.join(filepath, u'.version')
|
||||
fversion = None
|
||||
try:
|
||||
fversion = open(filepath, u'r')
|
||||
for line in fversion:
|
||||
full_version = unicode(line).rstrip() #\
|
||||
#.replace(u'\r', u'').replace(u'\n', u'')
|
||||
bits = full_version.split(u'-')
|
||||
app_version = {
|
||||
u'full': full_version,
|
||||
u'version': bits[0],
|
||||
u'build': bits[1] if len(bits) > 1 else None
|
||||
}
|
||||
if app_version[u'build']:
|
||||
log.info(
|
||||
u'Openlp version %s build %s',
|
||||
app_version[u'version'],
|
||||
app_version[u'build']
|
||||
)
|
||||
else:
|
||||
log.info(u'Openlp version %s' % app_version[u'version'])
|
||||
except IOError:
|
||||
log.exception('Error in version file.')
|
||||
app_version = {
|
||||
u'full': u'1.9.0-bzr000',
|
||||
u'version': u'1.9.0',
|
||||
u'build': u'bzr000'
|
||||
}
|
||||
finally:
|
||||
if fversion:
|
||||
fversion.close()
|
||||
app_version = self._get_version()
|
||||
#provide a listener for widgets to reqest a screen update.
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
||||
@ -172,6 +219,9 @@ def main():
|
||||
parser.add_option('-p', '--portable', dest='portable',
|
||||
action='store_true', help='Specify if this should be run as a '
|
||||
'portable app, off a USB flash drive (not implemented).')
|
||||
parser.add_option('-d', '--dev-version', dest='dev_version',
|
||||
action='store_true', help='Ignore the version file and pull the '
|
||||
'version directly from Bazaar')
|
||||
parser.add_option('-s', '--style', dest='style',
|
||||
help='Set the Qt4 style (passed directly to Qt4).')
|
||||
# Set up logging
|
||||
|
@ -313,7 +313,7 @@ def expand_tags(text):
|
||||
from spelltextedit import SpellTextEdit
|
||||
from eventreceiver import Receiver
|
||||
from settingsmanager import SettingsManager
|
||||
from plugin import PluginStatus, Plugin
|
||||
from plugin import PluginStatus, StringContent, Plugin
|
||||
from pluginmanager import PluginManager
|
||||
from settingstab import SettingsTab
|
||||
from serviceitem import ServiceItem
|
||||
|
@ -193,6 +193,14 @@ class EventReceiver(QtCore.QObject):
|
||||
``{plugin}_add_service_item``
|
||||
Ask the plugin to push the selected items to the service item
|
||||
|
||||
``{plugin}_service_load``
|
||||
Ask the plugin to process an individual service item after it has been
|
||||
loaded
|
||||
|
||||
``service_item_update``
|
||||
Passes back to the service manager the service item after it has been
|
||||
processed by the plugin
|
||||
|
||||
``alerts_text``
|
||||
Displays an alert message
|
||||
|
||||
|
@ -55,14 +55,17 @@ body {
|
||||
background-color: black;
|
||||
display: none;
|
||||
}
|
||||
#image {
|
||||
#bgimage {
|
||||
z-index:1;
|
||||
}
|
||||
#video1 {
|
||||
#image {
|
||||
z-index:2;
|
||||
}
|
||||
#video1 {
|
||||
z-index:3;
|
||||
}
|
||||
#video2 {
|
||||
z-index:2;
|
||||
z-index:3;
|
||||
}
|
||||
#alert {
|
||||
position: absolute;
|
||||
@ -73,7 +76,7 @@ body {
|
||||
}
|
||||
#footer {
|
||||
position: absolute;
|
||||
z-index:5;
|
||||
z-index:6;
|
||||
%s
|
||||
}
|
||||
/* lyric css */
|
||||
@ -294,7 +297,8 @@ body {
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<img id="image" class="size" %s />
|
||||
<img id="bgimage" class="size" %s />
|
||||
<img id="image" class="size" style="display:none" />
|
||||
<video id="video1" class="size" style="visibility:hidden" autobuffer preload>
|
||||
</video>
|
||||
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
|
||||
@ -397,7 +401,7 @@ def build_lyrics_css(item, webkitvers):
|
||||
"""
|
||||
style = """
|
||||
.lyricstable {
|
||||
z-index:4;
|
||||
z-index:5;
|
||||
position: absolute;
|
||||
display: table;
|
||||
%s
|
||||
|
@ -32,7 +32,8 @@ import os
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import context_menu_action, context_menu_separator, \
|
||||
SettingsManager, OpenLPToolbar, ServiceItem, build_icon, translate
|
||||
SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, \
|
||||
translate, Receiver
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -51,26 +52,19 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
The parent widget. Usually this will be the *Media Manager*
|
||||
itself. This needs to be a class descended from ``QWidget``.
|
||||
|
||||
``plugin``
|
||||
The plugin widget. Usually this will be the *Plugin*
|
||||
itself. This needs to be a class descended from ``Plugin``.
|
||||
|
||||
``icon``
|
||||
Either a ``QIcon``, a resource path, or a file name. This is
|
||||
the icon which is displayed in the *Media Manager*.
|
||||
|
||||
``title``
|
||||
The title visible on the item in the *Media Manager*.
|
||||
|
||||
**Member Variables**
|
||||
|
||||
When creating a descendant class from this class for your plugin,
|
||||
the following member variables should be set.
|
||||
|
||||
``self.PluginNameShort``
|
||||
The shortened (usually singular) name for the plugin e.g. *'Song'*
|
||||
for the Songs plugin.
|
||||
|
||||
``self.pluginNameVisible``
|
||||
The user visible name for a plugin which should use a suitable
|
||||
translation function.
|
||||
|
||||
``self.OnNewPrompt``
|
||||
Defaults to *'Select Image(s)'*.
|
||||
|
||||
@ -93,13 +87,17 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
log.info(u'Media Item loaded')
|
||||
|
||||
def __init__(self, parent=None, icon=None, title=None):
|
||||
def __init__(self, parent=None, plugin=None, icon=None):
|
||||
"""
|
||||
Constructor to create the media manager item.
|
||||
"""
|
||||
QtGui.QWidget.__init__(self)
|
||||
self.parent = parent
|
||||
self.settingsSection = title.lower()
|
||||
#TODO: plugin should not be the parent in future
|
||||
self.plugin = parent # plugin
|
||||
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):
|
||||
@ -107,8 +105,6 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
else:
|
||||
self.icon = None
|
||||
if title:
|
||||
self.title = title
|
||||
self.toolbar = None
|
||||
self.remoteTriggered = None
|
||||
self.serviceItemIconName = None
|
||||
@ -119,6 +115,9 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.requiredIcons()
|
||||
self.setupUi()
|
||||
self.retranslateUi()
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
|
||||
self.serviceLoad)
|
||||
|
||||
def requiredIcons(self):
|
||||
"""
|
||||
@ -208,64 +207,58 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
"""
|
||||
## Import Button ##
|
||||
if self.hasImportIcon:
|
||||
import_string = self.plugin.getString(StringContent.Import)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Import %s')) %
|
||||
self.PluginNameShort,
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Import a %s')) %
|
||||
self.pluginNameVisible,
|
||||
import_string[u'title'],
|
||||
import_string[u'tooltip'],
|
||||
u':/general/general_import.png', self.onImportClick)
|
||||
## File Button ##
|
||||
## Load Button ##
|
||||
if self.hasFileIcon:
|
||||
load_string = self.plugin.getString(StringContent.Load)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Load %s')) %
|
||||
self.PluginNameShort,
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Load a new %s')) %
|
||||
self.pluginNameVisible,
|
||||
load_string[u'title'],
|
||||
load_string[u'tooltip'],
|
||||
u':/general/general_open.png', self.onFileClick)
|
||||
## New Button ##
|
||||
if self.hasNewIcon:
|
||||
new_string = self.plugin.getString(StringContent.New)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'New %s')) %
|
||||
self.PluginNameShort,
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Add a new %s')) %
|
||||
self.pluginNameVisible,
|
||||
new_string[u'title'],
|
||||
new_string[u'tooltip'],
|
||||
u':/general/general_new.png', self.onNewClick)
|
||||
## Edit Button ##
|
||||
if self.hasEditIcon:
|
||||
edit_string = self.plugin.getString(StringContent.Edit)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Edit %s')) %
|
||||
self.PluginNameShort,
|
||||
unicode(translate(
|
||||
'OpenLP.MediaManagerItem', 'Edit the selected %s')) %
|
||||
self.pluginNameVisible,
|
||||
edit_string[u'title'],
|
||||
edit_string[u'tooltip'],
|
||||
u':/general/general_edit.png', self.onEditClick)
|
||||
## Delete Button ##
|
||||
if self.hasDeleteIcon:
|
||||
delete_string = self.plugin.getString(StringContent.Delete)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Delete %s')) %
|
||||
self.PluginNameShort,
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'Delete the selected item'),
|
||||
delete_string[u'title'],
|
||||
delete_string[u'tooltip'],
|
||||
u':/general/general_delete.png', self.onDeleteClick)
|
||||
## Separator Line ##
|
||||
self.addToolbarSeparator()
|
||||
## Preview ##
|
||||
preview_string = self.plugin.getString(StringContent.Preview)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Preview %s')) %
|
||||
self.PluginNameShort,
|
||||
translate('OpenLP.MediaManagerItem', 'Preview the selected item'),
|
||||
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(
|
||||
u'Go Live',
|
||||
translate('OpenLP.MediaManagerItem', 'Send the selected item live'),
|
||||
live_string[u'title'],
|
||||
live_string[u'tooltip'],
|
||||
u':/general/general_live.png', self.onLiveClick)
|
||||
## Add to service Button ##
|
||||
service_string = self.plugin.getString(StringContent.Service)
|
||||
self.addToolbarButton(
|
||||
unicode(translate('OpenLP.MediaManagerItem', 'Add %s to Service')) %
|
||||
self.PluginNameShort,
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'Add the selected item(s) to the service'),
|
||||
service_string[u'title'],
|
||||
service_string[u'tooltip'],
|
||||
u':/general/general_add.png', self.onAddClick)
|
||||
|
||||
def addListViewToToolBar(self):
|
||||
@ -281,17 +274,18 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
QtGui.QAbstractItemView.ExtendedSelection)
|
||||
self.listView.setAlternatingRowColors(True)
|
||||
self.listView.setDragEnabled(True)
|
||||
self.listView.setObjectName(u'%sListView' % self.PluginNameShort)
|
||||
self.listView.setObjectName(u'%sListView' % self.plugin.name)
|
||||
#Add to pageLayout
|
||||
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(
|
||||
self.listView, u':/general/general_edit.png',
|
||||
unicode(translate('OpenLP.MediaManagerItem', '&Edit %s')) %
|
||||
self.pluginNameVisible,
|
||||
name_string[u'singular'],
|
||||
self.onEditClick))
|
||||
self.listView.addAction(context_menu_separator(self.listView))
|
||||
if self.hasDeleteIcon:
|
||||
@ -300,14 +294,14 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.listView, u':/general/general_delete.png',
|
||||
unicode(translate('OpenLP.MediaManagerItem',
|
||||
'&Delete %s')) %
|
||||
self.pluginNameVisible,
|
||||
name_string[u'singular'],
|
||||
self.onDeleteClick))
|
||||
self.listView.addAction(context_menu_separator(self.listView))
|
||||
self.listView.addAction(
|
||||
context_menu_action(
|
||||
self.listView, u':/general/general_preview.png',
|
||||
unicode(translate('OpenLP.MediaManagerItem', '&Preview %s')) %
|
||||
self.pluginNameVisible,
|
||||
name_string[u'singular'],
|
||||
self.onPreviewClick))
|
||||
self.listView.addAction(
|
||||
context_menu_action(
|
||||
@ -447,7 +441,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'You must select one or more items to preview.'))
|
||||
else:
|
||||
log.debug(self.PluginNameShort + u' Preview requested')
|
||||
log.debug(self.plugin.name + u' Preview requested')
|
||||
service_item = self.buildServiceItem()
|
||||
if service_item:
|
||||
service_item.from_plugin = True
|
||||
@ -464,7 +458,7 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'You must select one or more items to send live.'))
|
||||
else:
|
||||
log.debug(self.PluginNameShort + u' Live requested')
|
||||
log.debug(self.plugin.name + u' Live requested')
|
||||
service_item = self.buildServiceItem()
|
||||
if service_item:
|
||||
service_item.from_plugin = True
|
||||
@ -480,10 +474,10 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'You must select one or more items.'))
|
||||
else:
|
||||
#Is it posssible to process multiple list items to generate multiple
|
||||
#service items?
|
||||
# Is it posssible to process multiple list items to generate multiple
|
||||
# service items?
|
||||
if self.singleServiceItem or self.remoteTriggered:
|
||||
log.debug(self.PluginNameShort + u' Add requested')
|
||||
log.debug(self.plugin.name + u' Add requested')
|
||||
service_item = self.buildServiceItem()
|
||||
if service_item:
|
||||
service_item.from_plugin = False
|
||||
@ -507,10 +501,10 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'You must select one or more items'))
|
||||
else:
|
||||
log.debug(self.PluginNameShort + u' Add requested')
|
||||
log.debug(self.plugin.name + u' Add requested')
|
||||
service_item = self.parent.serviceManager.getServiceItem()
|
||||
if not service_item:
|
||||
QtGui.QMessageBox.information(self,
|
||||
QtGui.QMessageBox.information(self,
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
'No Service Item Selected'),
|
||||
translate('OpenLP.MediaManagerItem',
|
||||
@ -540,3 +534,11 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
return service_item
|
||||
else:
|
||||
return None
|
||||
|
||||
def serviceLoad(self, message):
|
||||
"""
|
||||
Method to add processing when a service has been loaded and
|
||||
individual service items need to be processed by the plugins
|
||||
"""
|
||||
pass
|
||||
|
||||
|
@ -42,6 +42,18 @@ class PluginStatus(object):
|
||||
Inactive = 0
|
||||
Disabled = -1
|
||||
|
||||
class StringContent(object):
|
||||
Name = u'name'
|
||||
Import = u'import'
|
||||
Load = u'load'
|
||||
New = u'new'
|
||||
Edit = u'edit'
|
||||
Delete = u'delete'
|
||||
Preview = u'preview'
|
||||
Live = u'live'
|
||||
Service = u'service'
|
||||
VisibleName = u'visible_name'
|
||||
|
||||
class Plugin(QtCore.QObject):
|
||||
"""
|
||||
Base class for openlp plugins to inherit from.
|
||||
@ -117,6 +129,8 @@ class Plugin(QtCore.QObject):
|
||||
"""
|
||||
QtCore.QObject.__init__(self)
|
||||
self.name = name
|
||||
self.textStrings = {}
|
||||
self.setPluginTextStrings()
|
||||
if version:
|
||||
self.version = version
|
||||
self.settingsSection = self.name.lower()
|
||||
@ -257,9 +271,9 @@ class Plugin(QtCore.QObject):
|
||||
Called by the plugin to remove toolbar
|
||||
"""
|
||||
if self.mediaItem:
|
||||
self.mediadock.remove_dock(self.name)
|
||||
self.mediadock.remove_dock(self.mediaItem)
|
||||
if self.settings_tab:
|
||||
self.settingsForm.removeTab(self.name)
|
||||
self.settingsForm.removeTab(self.settings_tab)
|
||||
|
||||
def insertToolboxItem(self):
|
||||
"""
|
||||
@ -289,3 +303,15 @@ class Plugin(QtCore.QObject):
|
||||
The new name the plugin should now use.
|
||||
"""
|
||||
pass
|
||||
|
||||
def getString(self, name):
|
||||
"""
|
||||
encapsulate access of plugins translated text strings
|
||||
"""
|
||||
return self.textStrings[name]
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
pass
|
||||
|
@ -30,7 +30,7 @@ import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Plugin, PluginStatus
|
||||
from openlp.core.lib import Plugin, StringContent, PluginStatus
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -152,12 +152,13 @@ class PluginManager(object):
|
||||
for plugin in self.plugins:
|
||||
if plugin.status is not PluginStatus.Disabled:
|
||||
plugin.settings_tab = plugin.getSettingsTab()
|
||||
visible_title = plugin.getString(StringContent.VisibleName)
|
||||
if plugin.settings_tab:
|
||||
log.debug(u'Inserting settings tab item from %s' %
|
||||
plugin.name)
|
||||
settingsform.addTab(plugin.name, plugin.settings_tab)
|
||||
visible_title[u'title'])
|
||||
settingsform.addTab(visible_title[u'title'], plugin.settings_tab)
|
||||
else:
|
||||
log.debug(u'No tab settings in %s' % plugin.name)
|
||||
log.debug(u'No tab settings in %s' % visible_title[u'title'])
|
||||
|
||||
def hook_import_menu(self, import_menu):
|
||||
"""
|
||||
|
@ -58,6 +58,9 @@ class ItemCapabilities(object):
|
||||
AllowsLoop = 5
|
||||
AllowsAdditions = 6
|
||||
NoLineBreaks = 7
|
||||
OnLoadUpdate = 8
|
||||
AddIfNewItem = 9
|
||||
|
||||
|
||||
class ServiceItem(object):
|
||||
"""
|
||||
@ -98,6 +101,9 @@ class ServiceItem(object):
|
||||
self.main = None
|
||||
self.footer = None
|
||||
self.bg_image_bytes = None
|
||||
self.search_string = u''
|
||||
self.data_string = u''
|
||||
self._new_item()
|
||||
|
||||
def _new_item(self):
|
||||
"""
|
||||
@ -149,15 +155,15 @@ class ServiceItem(object):
|
||||
line_break = True
|
||||
if self.is_capable(ItemCapabilities.NoLineBreaks):
|
||||
line_break = False
|
||||
theme = None
|
||||
if self.theme:
|
||||
theme = self.theme
|
||||
self.main, self.footer = \
|
||||
self.render_manager.set_override_theme(theme, useOverride)
|
||||
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
|
||||
self.themedata = self.render_manager.renderer._theme
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
log.debug(u'Formatting slides')
|
||||
theme = None
|
||||
if self.theme:
|
||||
theme = self.theme
|
||||
self.main, self.footer = \
|
||||
self.render_manager.set_override_theme(theme, useOverride)
|
||||
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
|
||||
self.themedata = self.render_manager.renderer._theme
|
||||
for slide in self._raw_frames:
|
||||
before = time.time()
|
||||
formatted = self.render_manager \
|
||||
@ -170,7 +176,6 @@ class ServiceItem(object):
|
||||
u'verseTag': slide[u'verseTag'] })
|
||||
log.log(15, u'Formatting took %4s' % (time.time() - before))
|
||||
elif self.service_item_type == ServiceItemType.Image:
|
||||
self.themedata = self.render_manager.global_theme_data
|
||||
for slide in self._raw_frames:
|
||||
slide[u'image'] = resize_image(slide[u'image'],
|
||||
self.render_manager.width, self.render_manager.height)
|
||||
@ -255,7 +260,9 @@ class ServiceItem(object):
|
||||
u'audit':self.audit,
|
||||
u'notes':self.notes,
|
||||
u'from_plugin':self.from_plugin,
|
||||
u'capabilities':self.capabilities
|
||||
u'capabilities':self.capabilities,
|
||||
u'search':self.search_string,
|
||||
u'data':self.data_string
|
||||
}
|
||||
service_data = []
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
@ -293,6 +300,10 @@ class ServiceItem(object):
|
||||
self.notes = header[u'notes']
|
||||
self.from_plugin = header[u'from_plugin']
|
||||
self.capabilities = header[u'capabilities']
|
||||
# Added later so may not be present in older services.
|
||||
if u'search' in header:
|
||||
self.search_string = header[u'search']
|
||||
self.data_string = header[u'data']
|
||||
if self.service_item_type == ServiceItemType.Text:
|
||||
for slide in serviceitem[u'serviceitem'][u'data']:
|
||||
self._raw_frames.append(slide)
|
||||
@ -306,6 +317,7 @@ class ServiceItem(object):
|
||||
filename = os.path.join(path, text_image[u'title'])
|
||||
self.add_from_command(
|
||||
path, text_image[u'title'], text_image[u'image'] )
|
||||
self._new_item()
|
||||
|
||||
def merge(self, other):
|
||||
"""
|
||||
|
@ -31,16 +31,19 @@ class SettingsTab(QtGui.QWidget):
|
||||
SettingsTab is a helper widget for plugins to define Tabs for the settings
|
||||
dialog.
|
||||
"""
|
||||
def __init__(self, title):
|
||||
def __init__(self, title, visible_title=None):
|
||||
"""
|
||||
Constructor to create the Settings tab item.
|
||||
|
||||
``title``
|
||||
The title of the tab, which is used internally for the tab handling.
|
||||
|
||||
``visible_title``
|
||||
The title of the tab, which is usually displayed on the tab.
|
||||
"""
|
||||
QtGui.QWidget.__init__(self)
|
||||
self.tabTitle = title
|
||||
self.tabTitleVisible = None
|
||||
self.tabTitleVisible = visible_title
|
||||
self.settingsSection = self.tabTitle.lower()
|
||||
self.setupUi()
|
||||
self.retranslateUi()
|
||||
|
@ -82,6 +82,9 @@ class AdvancedTab(SettingsTab):
|
||||
self.doubleClickLiveCheckBox.setObjectName(u'doubleClickLiveCheckBox')
|
||||
self.uiLayout.addWidget(self.doubleClickLiveCheckBox)
|
||||
self.leftLayout.addWidget(self.uiGroupBox)
|
||||
self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox)
|
||||
self.expandServiceItemCheckBox.setObjectName(u'expandServiceItemCheckBox')
|
||||
self.uiLayout.addWidget(self.expandServiceItemCheckBox)
|
||||
# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftWidget)
|
||||
# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox')
|
||||
# self.sharedDirGroupBox.setGeometry(QtCore.QRect(0, 65, 500, 85))
|
||||
@ -140,6 +143,8 @@ class AdvancedTab(SettingsTab):
|
||||
'Remember active media manager tab on startup'))
|
||||
self.doubleClickLiveCheckBox.setText(translate('OpenLP.AdvancedTab',
|
||||
'Double-click to send items straight to live (requires restart)'))
|
||||
self.expandServiceItemCheckBox.setText(translate('OpenLP.AdvancedTab',
|
||||
'Expand new service items on creation'))
|
||||
# self.sharedDirGroupBox.setTitle(
|
||||
# translate('AdvancedTab', 'Central Data Store'))
|
||||
# self.sharedCheckBox.setText(
|
||||
@ -167,6 +172,9 @@ class AdvancedTab(SettingsTab):
|
||||
self.doubleClickLiveCheckBox.setChecked(
|
||||
settings.value(u'double click live',
|
||||
QtCore.QVariant(False)).toBool())
|
||||
self.expandServiceItemCheckBox.setChecked(
|
||||
settings.value(u'expand service item',
|
||||
QtCore.QVariant(False)).toBool())
|
||||
settings.endGroup()
|
||||
|
||||
def save(self):
|
||||
@ -181,6 +189,8 @@ class AdvancedTab(SettingsTab):
|
||||
QtCore.QVariant(self.mediaPluginCheckBox.isChecked()))
|
||||
settings.setValue(u'double click live',
|
||||
QtCore.QVariant(self.doubleClickLiveCheckBox.isChecked()))
|
||||
settings.setValue(u'expand service item',
|
||||
QtCore.QVariant(self.expandServiceItemCheckBox.isChecked()))
|
||||
settings.endGroup()
|
||||
|
||||
def onSharedCheckBoxChanged(self, checked):
|
||||
|
@ -114,21 +114,23 @@ class MainDisplay(DisplayWidget):
|
||||
"""
|
||||
log.debug(u'Setup live = %s for %s ' % (self.isLive,
|
||||
self.screens.monitor_number))
|
||||
self.usePhonon = QtCore.QSettings().value(
|
||||
u'media/use phonon', QtCore.QVariant(True)).toBool()
|
||||
self.phononActive = False
|
||||
self.screen = self.screens.current
|
||||
self.setVisible(False)
|
||||
self.setGeometry(self.screen[u'size'])
|
||||
try:
|
||||
self.webView = QtWebKit.QGraphicsWebView()
|
||||
self.scene = QtGui.QGraphicsScene(self)
|
||||
self.setScene(self.scene)
|
||||
self.scene.addItem(self.webView)
|
||||
self.webView.setGeometry(QtCore.QRectF(0, 0,
|
||||
self.screen[u'size'].width(), self.screen[u'size'].height()))
|
||||
except AttributeError:
|
||||
# QGraphicsWebView a recent addition, so fall back to QWebView
|
||||
self.webView = QtWebKit.QWebView(self)
|
||||
self.webView.setGeometry(0, 0,
|
||||
self.screen[u'size'].width(), self.screen[u'size'].height())
|
||||
self.videoWidget = Phonon.VideoWidget(self)
|
||||
self.videoWidget.setVisible(False)
|
||||
self.videoWidget.setGeometry(QtCore.QRect(0, 0,
|
||||
self.screen[u'size'].width(), self.screen[u'size'].height()))
|
||||
self.mediaObject = Phonon.MediaObject(self)
|
||||
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
|
||||
Phonon.createPath(self.mediaObject, self.videoWidget)
|
||||
Phonon.createPath(self.mediaObject, self.audio)
|
||||
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,
|
||||
@ -199,7 +201,7 @@ class MainDisplay(DisplayWidget):
|
||||
"""
|
||||
log.debug(u'alert')
|
||||
if self.height() != self.screen[u'size'].height() \
|
||||
or not self.isVisible():
|
||||
or not self.isVisible() or self.videoWidget.isVisible():
|
||||
shrink = True
|
||||
else:
|
||||
shrink = False
|
||||
@ -208,12 +210,17 @@ class MainDisplay(DisplayWidget):
|
||||
u'top' if shrink else u'')
|
||||
height = self.frame.evaluateJavaScript(js)
|
||||
if shrink:
|
||||
if text:
|
||||
self.resize(self.width(), int(height.toString()))
|
||||
self.setVisible(True)
|
||||
if self.phononActive:
|
||||
shrinkItem = self.webView
|
||||
else:
|
||||
self.setGeometry(self.screen[u'size'])
|
||||
self.setVisible(False)
|
||||
shrinkItem = self
|
||||
if text:
|
||||
shrinkItem.resize(self.width(), int(height.toString()))
|
||||
shrinkItem.setVisible(True)
|
||||
else:
|
||||
shrinkItem.setVisible(False)
|
||||
shrinkItem.resize(self.screen[u'size'].width(),
|
||||
self.screen[u'size'].height())
|
||||
|
||||
def image(self, image):
|
||||
"""
|
||||
@ -259,14 +266,24 @@ class MainDisplay(DisplayWidget):
|
||||
Used after Video plugin has changed the background
|
||||
"""
|
||||
log.debug(u'resetVideo')
|
||||
self.frame.evaluateJavaScript(u'show_video("close");')
|
||||
if self.phononActive:
|
||||
self.mediaObject.stop()
|
||||
self.mediaObject.clearQueue()
|
||||
self.webView.setVisible(True)
|
||||
self.videoWidget.setVisible(False)
|
||||
self.phononActive = False
|
||||
else:
|
||||
self.frame.evaluateJavaScript(u'show_video("close");')
|
||||
|
||||
def videoPlay(self):
|
||||
"""
|
||||
Responds to the request to play a loaded video
|
||||
"""
|
||||
log.debug(u'videoPlay')
|
||||
self.frame.evaluateJavaScript(u'show_video("play");')
|
||||
if self.phononActive:
|
||||
self.mediaObject.play()
|
||||
else:
|
||||
self.frame.evaluateJavaScript(u'show_video("play");')
|
||||
# show screen
|
||||
if self.isLive:
|
||||
self.setVisible(True)
|
||||
@ -276,32 +293,54 @@ class MainDisplay(DisplayWidget):
|
||||
Responds to the request to pause a loaded video
|
||||
"""
|
||||
log.debug(u'videoPause')
|
||||
self.frame.evaluateJavaScript(u'show_video("pause");')
|
||||
if self.phononActive:
|
||||
self.mediaObject.pause()
|
||||
else:
|
||||
self.frame.evaluateJavaScript(u'show_video("pause");')
|
||||
|
||||
def videoStop(self):
|
||||
"""
|
||||
Responds to the request to stop a loaded video
|
||||
"""
|
||||
log.debug(u'videoStop')
|
||||
self.frame.evaluateJavaScript(u'show_video("stop");')
|
||||
if self.phononActive:
|
||||
self.mediaObject.stop()
|
||||
else:
|
||||
self.frame.evaluateJavaScript(u'show_video("stop");')
|
||||
|
||||
def videoVolume(self, volume):
|
||||
"""
|
||||
Changes the volume of a running video
|
||||
"""
|
||||
log.debug(u'videoVolume %d' % volume)
|
||||
self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
|
||||
str(float(volume)/float(10)))
|
||||
vol = float(volume)/float(10)
|
||||
if self.phononActive:
|
||||
self.audio.setVolume(vol)
|
||||
else:
|
||||
self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
|
||||
str(vol))
|
||||
|
||||
def video(self, videoPath, volume):
|
||||
def video(self, videoPath, volume, isBackground=False):
|
||||
"""
|
||||
Loads and starts a video to run with the option of sound
|
||||
"""
|
||||
log.debug(u'video')
|
||||
self.loaded = True
|
||||
js = u'show_video("init", "%s", %s, true); show_video("play");' % \
|
||||
(videoPath.replace(u'\\', u'\\\\'), str(float(volume)/float(10)))
|
||||
self.frame.evaluateJavaScript(js)
|
||||
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))
|
||||
self.frame.evaluateJavaScript(js)
|
||||
else:
|
||||
self.phononActive = True
|
||||
self.mediaObject.stop()
|
||||
self.mediaObject.clearQueue()
|
||||
self.mediaObject.setCurrentSource(Phonon.MediaSource(videoPath))
|
||||
self.mediaObject.play()
|
||||
self.webView.setVisible(False)
|
||||
self.videoWidget.setVisible(True)
|
||||
self.audio.setVolume(vol)
|
||||
return self.preview()
|
||||
|
||||
def isLoaded(self):
|
||||
@ -382,6 +421,8 @@ class MainDisplay(DisplayWidget):
|
||||
Store the images so they can be replaced when required
|
||||
"""
|
||||
log.debug(u'hideDisplay mode = %d', mode)
|
||||
if self.phononActive:
|
||||
self.videoPause()
|
||||
if mode == HideMode.Screen:
|
||||
self.frame.evaluateJavaScript(u'show_blank("desktop");')
|
||||
self.setVisible(False)
|
||||
@ -389,8 +430,11 @@ class MainDisplay(DisplayWidget):
|
||||
self.frame.evaluateJavaScript(u'show_blank("black");')
|
||||
else:
|
||||
self.frame.evaluateJavaScript(u'show_blank("theme");')
|
||||
if mode != HideMode.Screen and self.isHidden():
|
||||
self.setVisible(True)
|
||||
if mode != HideMode.Screen:
|
||||
if self.isHidden():
|
||||
self.setVisible(True)
|
||||
if self.phononActive:
|
||||
self.webView.setVisible(True)
|
||||
self.hide_mode = mode
|
||||
|
||||
def showDisplay(self):
|
||||
@ -403,6 +447,9 @@ class MainDisplay(DisplayWidget):
|
||||
self.frame.evaluateJavaScript('show_blank("show");')
|
||||
if self.isHidden():
|
||||
self.setVisible(True)
|
||||
if self.phononActive:
|
||||
self.webView.setVisible(False)
|
||||
self.videoPlay()
|
||||
# Trigger actions when display is active again
|
||||
Receiver.send_message(u'maindisplay_active')
|
||||
self.hide_mode = None
|
||||
@ -484,3 +531,4 @@ class AudioPlayer(QtCore.QObject):
|
||||
"""
|
||||
log.debug(u'AudioPlayer Reached end of media playlist')
|
||||
self.mediaObject.clearQueue()
|
||||
|
||||
|
@ -175,19 +175,13 @@ class Ui_MainWindow(object):
|
||||
QtCore.Qt.DockWidgetArea(2), self.ThemeManagerDock)
|
||||
# Create the menu items
|
||||
self.FileNewItem = QtGui.QAction(MainWindow)
|
||||
self.FileNewItem.setIcon(
|
||||
self.ServiceManagerContents.toolbar.getIconFromTitle(
|
||||
u'New Service'))
|
||||
self.FileNewItem.setIcon(build_icon(u':/general/general_new.png'))
|
||||
self.FileNewItem.setObjectName(u'FileNewItem')
|
||||
self.FileOpenItem = QtGui.QAction(MainWindow)
|
||||
self.FileOpenItem.setIcon(
|
||||
self.ServiceManagerContents.toolbar.getIconFromTitle(
|
||||
u'Open Service'))
|
||||
self.FileOpenItem.setIcon(build_icon(u':/general/general_open.png'))
|
||||
self.FileOpenItem.setObjectName(u'FileOpenItem')
|
||||
self.FileSaveItem = QtGui.QAction(MainWindow)
|
||||
self.FileSaveItem.setIcon(
|
||||
self.ServiceManagerContents.toolbar.getIconFromTitle(
|
||||
u'Save Service'))
|
||||
self.FileSaveItem.setIcon(build_icon(u':/general/general_save.png'))
|
||||
self.FileSaveItem.setObjectName(u'FileSaveItem')
|
||||
self.FileSaveAsItem = QtGui.QAction(MainWindow)
|
||||
self.FileSaveAsItem.setObjectName(u'FileSaveAsItem')
|
||||
@ -343,7 +337,6 @@ class Ui_MainWindow(object):
|
||||
Set up the translation system
|
||||
"""
|
||||
MainWindow.mainTitle = translate('OpenLP.MainWindow', 'OpenLP 2.0')
|
||||
# MainWindow.language = translate('OpenLP.MainWindow', 'English')
|
||||
MainWindow.setWindowTitle(MainWindow.mainTitle)
|
||||
self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
|
||||
self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import StringContent
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class MediaDockManager(object):
|
||||
@ -48,8 +50,9 @@ class MediaDockManager(object):
|
||||
``icon``
|
||||
An icon for this dock item
|
||||
"""
|
||||
log.info(u'Adding %s dock' % media_item.title)
|
||||
self.media_dock.addItem(media_item, icon, media_item.title)
|
||||
visible_title = media_item.plugin.getString(StringContent.VisibleName)
|
||||
log.info(u'Adding %s dock' % visible_title)
|
||||
self.media_dock.addItem(media_item, icon, visible_title[u'title'])
|
||||
|
||||
def insert_dock(self, media_item, icon, weight):
|
||||
"""
|
||||
@ -57,27 +60,29 @@ class MediaDockManager(object):
|
||||
This does not work as it gives a Segmentation error.
|
||||
For now add at end of stack if not present
|
||||
"""
|
||||
log.debug(u'Inserting %s dock' % media_item.title)
|
||||
visible_title = media_item.plugin.getString(StringContent.VisibleName)
|
||||
log.debug(u'Inserting %s dock' % visible_title[u'title'])
|
||||
match = False
|
||||
for dock_index in range(0, self.media_dock.count()):
|
||||
if self.media_dock.widget(dock_index).settingsSection == \
|
||||
media_item.title.lower():
|
||||
media_item.plugin.name.lower():
|
||||
match = True
|
||||
break
|
||||
if not match:
|
||||
self.media_dock.addItem(media_item, icon, media_item.title)
|
||||
self.media_dock.addItem(media_item, icon, visible_title[u'title'])
|
||||
|
||||
def remove_dock(self, name):
|
||||
def remove_dock(self, media_item):
|
||||
"""
|
||||
Removes a MediaManagerItem from the dock
|
||||
|
||||
``name``
|
||||
The item to remove
|
||||
``media_item``
|
||||
The item to add to the dock
|
||||
"""
|
||||
log.debug(u'remove %s dock' % name)
|
||||
visible_title = media_item.plugin.getString(StringContent.VisibleName)
|
||||
log.debug(u'remove %s dock' % visible_title[u'title'])
|
||||
for dock_index in range(0, self.media_dock.count()):
|
||||
if self.media_dock.widget(dock_index):
|
||||
if self.media_dock.widget(dock_index).settingsSection == \
|
||||
name.lower():
|
||||
media_item.plugin.name.lower():
|
||||
self.media_dock.widget(dock_index).hide()
|
||||
self.media_dock.removeItem(dock_index)
|
||||
|
@ -28,7 +28,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import PluginStatus, translate
|
||||
from openlp.core.lib import PluginStatus, StringContent, translate
|
||||
from plugindialog import Ui_PluginViewDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -78,7 +78,8 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
elif plugin.status == PluginStatus.Disabled:
|
||||
status_text = unicode(
|
||||
translate('OpenLP.PluginForm', '%s (Disabled)'))
|
||||
item.setText(status_text % plugin.name)
|
||||
name_string = plugin.getString(StringContent.Name)
|
||||
item.setText(status_text % name_string[u'plural'])
|
||||
# If the plugin has an icon, set it!
|
||||
if plugin.icon:
|
||||
item.setIcon(plugin.icon)
|
||||
@ -106,10 +107,11 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
if self.pluginListWidget.currentItem() is None:
|
||||
self._clearDetails()
|
||||
return
|
||||
plugin_name = self.pluginListWidget.currentItem().text().split(u' ')[0]
|
||||
plugin_name_plural = self.pluginListWidget.currentItem().text().split(u' ')[0]
|
||||
self.activePlugin = None
|
||||
for plugin in self.parent.plugin_manager.plugins:
|
||||
if plugin.name == plugin_name:
|
||||
name_string = plugin.getString(StringContent.Name)
|
||||
if name_string[u'plural'] == plugin_name_plural:
|
||||
self.activePlugin = plugin
|
||||
break
|
||||
if self.activePlugin:
|
||||
@ -137,5 +139,6 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
|
||||
elif self.activePlugin.status == PluginStatus.Disabled:
|
||||
status_text = unicode(
|
||||
translate('OpenLP.PluginForm', '%s (Disabled)'))
|
||||
name_string = self.activePlugin.getString(StringContent.Name)
|
||||
self.pluginListWidget.currentItem().setText(
|
||||
status_text % self.activePlugin.name)
|
||||
status_text % name_string[u'plural'])
|
||||
|
@ -107,6 +107,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.serviceName = u''
|
||||
self.suffixes = []
|
||||
self.droppos = 0
|
||||
self.expandTabs = False
|
||||
#is a new service and has not been saved
|
||||
self.isNew = True
|
||||
self.serviceNoteForm = ServiceNoteForm(self.parent)
|
||||
@ -199,6 +200,19 @@ class ServiceManager(QtGui.QWidget):
|
||||
translate('OpenLP.ServiceManager',
|
||||
'Delete the selected item from the service.'),
|
||||
self.onDeleteFromService)
|
||||
self.orderToolbar.addSeparator()
|
||||
self.orderToolbar.addToolbarButton(
|
||||
translate('OpenLP.ServiceManager', '&Expand all'),
|
||||
u':/services/service_top.png',
|
||||
translate('OpenLP.ServiceManager',
|
||||
'Expand all the service items.'),
|
||||
self.onExpandAll)
|
||||
self.orderToolbar.addToolbarButton(
|
||||
translate('OpenLP.ServiceManager', '&Collapse all'),
|
||||
u':/services/service_bottom.png',
|
||||
translate('OpenLP.ServiceManager',
|
||||
'Collapse all the service items.'),
|
||||
self.onCollapseAll)
|
||||
self.layout.addWidget(self.orderToolbar)
|
||||
# Connect up our signals and slots
|
||||
QtCore.QObject.connect(self.themeComboBox,
|
||||
@ -220,9 +234,11 @@ class ServiceManager(QtGui.QWidget):
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_updated'), self.regenerateServiceItems)
|
||||
QtCore.SIGNAL(u'config_updated'), self.configUpdated)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'theme_update_global'), self.themeChange)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate)
|
||||
# Last little bits of setting up
|
||||
self.service_theme = unicode(QtCore.QSettings().value(
|
||||
self.parent.serviceSettingsSection + u'/service theme',
|
||||
@ -263,6 +279,17 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.themeMenu = QtGui.QMenu(
|
||||
translate('OpenLP.ServiceManager', '&Change Item Theme'))
|
||||
self.menu.addMenu(self.themeMenu)
|
||||
self.configUpdated(True)
|
||||
|
||||
def configUpdated(self, firstTime=False):
|
||||
"""
|
||||
Triggered when Config dialog is updated.
|
||||
"""
|
||||
self.expandTabs = QtCore.QSettings().value(
|
||||
u'advanced/expand service item',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
if not firstTime:
|
||||
self.regenerateServiceItems()
|
||||
|
||||
def supportedSuffixes(self, suffix):
|
||||
self.suffixes.append(suffix)
|
||||
@ -319,7 +346,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.serviceItems[item][u'service_item'])
|
||||
if self.serviceItemEditForm.exec_():
|
||||
self.addServiceItem(self.serviceItemEditForm.getServiceItem(),
|
||||
replace=True)
|
||||
replace=True, expand=self.serviceItems[item][u'expand'])
|
||||
|
||||
def nextItem(self):
|
||||
"""
|
||||
@ -421,6 +448,14 @@ class ServiceManager(QtGui.QWidget):
|
||||
if setSelected:
|
||||
firstItem.setSelected(True)
|
||||
|
||||
def onCollapseAll(self):
|
||||
"""
|
||||
Collapse all the service items
|
||||
"""
|
||||
for item in self.serviceItems:
|
||||
item[u'expanded'] = False
|
||||
self.regenerateServiceItems()
|
||||
|
||||
def collapsed(self, item):
|
||||
"""
|
||||
Record if an item is collapsed
|
||||
@ -429,6 +464,14 @@ class ServiceManager(QtGui.QWidget):
|
||||
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
|
||||
self.serviceItems[pos -1 ][u'expanded'] = False
|
||||
|
||||
def onExpandAll(self):
|
||||
"""
|
||||
Collapse all the service items
|
||||
"""
|
||||
for item in self.serviceItems:
|
||||
item[u'expanded'] = True
|
||||
self.regenerateServiceItems()
|
||||
|
||||
def expanded(self, item):
|
||||
"""
|
||||
Record if an item is collapsed
|
||||
@ -526,12 +569,12 @@ class ServiceManager(QtGui.QWidget):
|
||||
Used when moving items as the move takes place in supporting array,
|
||||
and when regenerating all the items due to theme changes
|
||||
"""
|
||||
#Correct order of items in array
|
||||
# Correct order of items in array
|
||||
count = 1
|
||||
for item in self.serviceItems:
|
||||
item[u'order'] = count
|
||||
count += 1
|
||||
#Repaint the screen
|
||||
# Repaint the screen
|
||||
self.serviceManagerList.clear()
|
||||
for itemcount, item in enumerate(self.serviceItems):
|
||||
serviceitem = item[u'service_item']
|
||||
@ -600,6 +643,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
zip = None
|
||||
file = None
|
||||
try:
|
||||
write_list = []
|
||||
zip = zipfile.ZipFile(unicode(filename), 'w')
|
||||
for item in self.serviceItems:
|
||||
service.append({u'serviceitem':item[u'service_item']
|
||||
@ -609,7 +653,10 @@ class ServiceManager(QtGui.QWidget):
|
||||
path_from = unicode(os.path.join(
|
||||
frame[u'path'],
|
||||
frame[u'title']))
|
||||
zip.write(path_from.encode(u'utf-8'))
|
||||
# On write a file once
|
||||
if not path_from in write_list:
|
||||
write_list.append(path_from)
|
||||
zip.write(path_from.encode(u'utf-8'))
|
||||
file = open(servicefile, u'wb')
|
||||
cPickle.dump(service, file)
|
||||
file.close()
|
||||
@ -711,6 +758,9 @@ class ServiceManager(QtGui.QWidget):
|
||||
serviceitem.set_from_service(item, self.servicePath)
|
||||
self.validateItem(serviceitem)
|
||||
self.addServiceItem(serviceitem)
|
||||
if serviceitem.is_capable(ItemCapabilities.OnLoadUpdate):
|
||||
Receiver.send_message(u'%s_service_load' %
|
||||
serviceitem.name.lower(), serviceitem)
|
||||
try:
|
||||
if os.path.isfile(p_file):
|
||||
os.remove(p_file)
|
||||
@ -796,19 +846,48 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.isNew = True
|
||||
for item in tempServiceItems:
|
||||
self.addServiceItem(
|
||||
item[u'service_item'], False, item[u'expanded'])
|
||||
item[u'service_item'], False, expand=item[u'expanded'])
|
||||
# Set to False as items may have changed rendering
|
||||
# does not impact the saved song so True may also be valid
|
||||
self.parent.serviceChanged(False, self.serviceName)
|
||||
|
||||
def addServiceItem(self, item, rebuild=False, expand=True, replace=False):
|
||||
def serviceItemUpdate(self, message):
|
||||
"""
|
||||
Triggered from plugins to update service items.
|
||||
"""
|
||||
editId, uuid = message.split(u':')
|
||||
for item in self.serviceItems:
|
||||
if item[u'service_item']._uuid == uuid:
|
||||
item[u'service_item'].editId = editId
|
||||
|
||||
def replaceServiceItem(self, newItem):
|
||||
"""
|
||||
Using the service item passed replace the one with the same edit id
|
||||
if found.
|
||||
"""
|
||||
newItem.render()
|
||||
for itemcount, item in enumerate(self.serviceItems):
|
||||
if item[u'service_item'].editId == newItem.editId and \
|
||||
item[u'service_item'].name == newItem.name:
|
||||
newItem.merge(item[u'service_item'])
|
||||
item[u'service_item'] = newItem
|
||||
self.repaintServiceList(itemcount + 1, 0)
|
||||
self.parent.LiveController.replaceServiceManagerItem(newItem)
|
||||
self.parent.serviceChanged(False, self.serviceName)
|
||||
|
||||
def addServiceItem(self, item, rebuild=False, expand=None, replace=False):
|
||||
"""
|
||||
Add a Service item to the list
|
||||
|
||||
``item``
|
||||
Service Item to be added
|
||||
|
||||
``expand``
|
||||
Override the default expand settings. (Tristate)
|
||||
"""
|
||||
log.debug(u'addServiceItem')
|
||||
if expand == None:
|
||||
expand = self.expandTabs
|
||||
sitem = self.findServiceItem()[0]
|
||||
item.render()
|
||||
if replace:
|
||||
@ -817,7 +896,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.repaintServiceList(sitem + 1, 0)
|
||||
self.parent.LiveController.replaceServiceManagerItem(item)
|
||||
else:
|
||||
#nothing selected for dnd
|
||||
# nothing selected for dnd
|
||||
if self.droppos == 0:
|
||||
if isinstance(item, list):
|
||||
for inditem in item:
|
||||
@ -834,7 +913,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
u'order': self.droppos,
|
||||
u'expanded':expand})
|
||||
self.repaintServiceList(self.droppos, 0)
|
||||
#if rebuilding list make sure live is fixed.
|
||||
# if rebuilding list make sure live is fixed.
|
||||
if rebuild:
|
||||
self.parent.LiveController.replaceServiceManagerItem(item)
|
||||
self.droppos = 0
|
||||
@ -914,7 +993,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
else:
|
||||
pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
|
||||
count = item.data(0, QtCore.Qt.UserRole).toInt()[0]
|
||||
#adjust for zero based arrays
|
||||
# adjust for zero based arrays
|
||||
pos = pos - 1
|
||||
return pos, count
|
||||
|
||||
@ -940,7 +1019,7 @@ class ServiceManager(QtGui.QWidget):
|
||||
if link.hasText():
|
||||
plugin = event.mimeData().text()
|
||||
item = self.serviceManagerList.itemAt(event.pos())
|
||||
#ServiceManager started the drag and drop
|
||||
# ServiceManager started the drag and drop
|
||||
if plugin == u'ServiceManager':
|
||||
startpos, startCount = self.findServiceItem()
|
||||
if item is None:
|
||||
@ -952,22 +1031,22 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.serviceItems.insert(endpos, serviceItem)
|
||||
self.repaintServiceList(endpos, startCount)
|
||||
else:
|
||||
#we are not over anything so drop
|
||||
# we are not over anything so drop
|
||||
replace = False
|
||||
if item is None:
|
||||
self.droppos = len(self.serviceItems)
|
||||
else:
|
||||
#we are over somthing so lets investigate
|
||||
# we are over somthing so lets investigate
|
||||
pos = self._getParentItemData(item) - 1
|
||||
serviceItem = self.serviceItems[pos]
|
||||
if (plugin == serviceItem[u'service_item'].name and
|
||||
serviceItem[u'service_item'].is_capable(
|
||||
ItemCapabilities.AllowsAdditions)):
|
||||
action = self.dndMenu.exec_(QtGui.QCursor.pos())
|
||||
#New action required
|
||||
# New action required
|
||||
if action == self.newAction:
|
||||
self.droppos = self._getParentItemData(item)
|
||||
#Append to existing action
|
||||
# Append to existing action
|
||||
if action == self.addToAction:
|
||||
self.droppos = self._getParentItemData(item)
|
||||
item.setSelected(True)
|
||||
|
@ -72,14 +72,15 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
|
||||
self.settingsTabWidget.insertTab(
|
||||
location + 14, tab, tab.tabTitleVisible)
|
||||
|
||||
def removeTab(self, name):
|
||||
def removeTab(self, tab):
|
||||
"""
|
||||
Remove a tab from the form
|
||||
"""
|
||||
log.debug(u'remove %s tab' % name)
|
||||
log.debug(u'remove %s tab' % tab.tabTitleVisible)
|
||||
for tabIndex in range(0, self.settingsTabWidget.count()):
|
||||
if self.settingsTabWidget.widget(tabIndex):
|
||||
if self.settingsTabWidget.widget(tabIndex).tabTitle == name:
|
||||
if self.settingsTabWidget.widget(tabIndex).tabTitleVisible == \
|
||||
tab.tabTitleVisible:
|
||||
self.settingsTabWidget.removeTab(tabIndex)
|
||||
|
||||
def accept(self):
|
||||
|
@ -179,19 +179,24 @@ class SlideController(QtGui.QWidget):
|
||||
self.HideMenu.setMenu(QtGui.QMenu(
|
||||
translate('OpenLP.SlideController', 'Hide'), self.Toolbar))
|
||||
self.BlankScreen = QtGui.QAction(QtGui.QIcon(
|
||||
u':/slides/slide_blank.png'), u'Blank Screen', self.HideMenu)
|
||||
u':/slides/slide_blank.png'),
|
||||
translate('OpenLP.SlideController',
|
||||
'Blank Screen'), self.HideMenu)
|
||||
self.BlankScreen.setCheckable(True)
|
||||
QtCore.QObject.connect(self.BlankScreen,
|
||||
QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay)
|
||||
self.ThemeScreen = QtGui.QAction(QtGui.QIcon(
|
||||
u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu)
|
||||
u':/slides/slide_theme.png'),
|
||||
translate('OpenLP.SlideController',
|
||||
'Blank to Theme'), self.HideMenu)
|
||||
self.ThemeScreen.setCheckable(True)
|
||||
QtCore.QObject.connect(self.ThemeScreen,
|
||||
QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay)
|
||||
if self.screens.display_count > 1:
|
||||
self.DesktopScreen = QtGui.QAction(QtGui.QIcon(
|
||||
u':/slides/slide_desktop.png'), u'Show Desktop',
|
||||
self.HideMenu)
|
||||
u':/slides/slide_desktop.png'),
|
||||
translate('OpenLP.SlideController',
|
||||
'Show Desktop'), self.HideMenu)
|
||||
self.DesktopScreen.setCheckable(True)
|
||||
QtCore.QObject.connect(self.DesktopScreen,
|
||||
QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay)
|
||||
@ -538,7 +543,7 @@ class SlideController(QtGui.QWidget):
|
||||
Receiver.send_message(u'%s_stop' %
|
||||
self.serviceItem.name.lower(), [serviceItem, self.isLive])
|
||||
if self.serviceItem.is_media():
|
||||
self.onMediaStop()
|
||||
self.onMediaClose()
|
||||
if self.isLive:
|
||||
blanked = self.BlankScreen.isChecked()
|
||||
else:
|
||||
@ -926,14 +931,13 @@ class SlideController(QtGui.QWidget):
|
||||
Respond to the arrival of a media service item
|
||||
"""
|
||||
log.debug(u'SlideController onMediaStart')
|
||||
file = os.path.join(item.get_frame_path(), item.get_frame_title())
|
||||
if self.isLive:
|
||||
file = os.path.join(item.get_frame_path(), item.get_frame_title())
|
||||
self.display.video(file, self.volume)
|
||||
self.volumeSlider.setValue(self.volume)
|
||||
else:
|
||||
self.mediaObject.stop()
|
||||
self.mediaObject.clearQueue()
|
||||
file = os.path.join(item.get_frame_path(), item.get_frame_title())
|
||||
self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
|
||||
self.seekSlider.setMediaObject(self.mediaObject)
|
||||
self.seekSlider.show()
|
||||
@ -981,3 +985,18 @@ class SlideController(QtGui.QWidget):
|
||||
self.video.hide()
|
||||
self.SlidePreview.clear()
|
||||
self.SlidePreview.show()
|
||||
|
||||
def onMediaClose(self):
|
||||
"""
|
||||
Respond to a request to close the Video
|
||||
"""
|
||||
log.debug(u'SlideController onMediaStop')
|
||||
if self.isLive:
|
||||
self.display.resetVideo()
|
||||
else:
|
||||
self.mediaObject.stop()
|
||||
self.mediaObject.clearQueue()
|
||||
self.video.hide()
|
||||
self.SlidePreview.clear()
|
||||
self.SlidePreview.show()
|
||||
|
||||
|
@ -28,7 +28,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.alerts.lib import AlertsManager, AlertsTab
|
||||
from openlp.plugins.alerts.lib.db import init_schema
|
||||
@ -101,3 +101,18 @@ class AlertsPlugin(Plugin):
|
||||
'<br />The alert plugin controls the displaying of nursery alerts '
|
||||
'on the display screen')
|
||||
return about_text
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('AlertsPlugin', 'Alert'),
|
||||
u'plural': translate('AlertsPlugin', 'Alerts')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('AlertsPlugin', 'Alerts')
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
|
||||
"""
|
||||
Provide UI for the alert system
|
||||
"""
|
||||
def __init__(self, plugin):
|
||||
def __init__(self, title, visible_title):
|
||||
"""
|
||||
Initialise the alert form
|
||||
"""
|
||||
|
@ -32,14 +32,13 @@ class AlertsTab(SettingsTab):
|
||||
"""
|
||||
AlertsTab is the alerts settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent, visible_title):
|
||||
self.parent = parent
|
||||
self.manager = parent.manager
|
||||
SettingsTab.__init__(self, parent.name)
|
||||
SettingsTab.__init__(self, parent.name, visible_title)
|
||||
|
||||
def setupUi(self):
|
||||
self.setObjectName(u'AlertsTab')
|
||||
self.tabTitleVisible = translate('AlertsPlugin.AlertsTab', 'Alerts')
|
||||
self.AlertsLayout = QtGui.QHBoxLayout(self)
|
||||
self.AlertsLayout.setSpacing(8)
|
||||
self.AlertsLayout.setMargin(8)
|
||||
@ -296,4 +295,3 @@ class AlertsTab(SettingsTab):
|
||||
self.FontPreview.setFont(font)
|
||||
self.FontPreview.setStyleSheet(u'background-color: %s; color: %s' %
|
||||
(self.bg_color, self.font_color))
|
||||
|
||||
|
@ -24,6 +24,6 @@
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`bibles' module provides the Bible plugin to enable OpenLP to display
|
||||
The :mod:`bibles` module provides the Bible plugin to enable OpenLP to display
|
||||
scripture.
|
||||
"""
|
||||
|
@ -28,7 +28,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -58,11 +58,12 @@ class BiblePlugin(Plugin):
|
||||
self.exportBibleItem.setVisible(False)
|
||||
|
||||
def getSettingsTab(self):
|
||||
return BiblesTab(self.name)
|
||||
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.icon, self.name)
|
||||
return BibleMediaItem(self, self, self.icon)
|
||||
|
||||
def addImportMenuItem(self, import_menu):
|
||||
self.importBibleItem = QtGui.QAction(import_menu)
|
||||
@ -79,8 +80,7 @@ class BiblePlugin(Plugin):
|
||||
self.exportBibleItem = QtGui.QAction(export_menu)
|
||||
self.exportBibleItem.setObjectName(u'exportBibleItem')
|
||||
export_menu.addAction(self.exportBibleItem)
|
||||
self.exportBibleItem.setText(translate(
|
||||
'BiblesPlugin', '&Bible'))
|
||||
self.exportBibleItem.setText(translate('BiblesPlugin', '&Bible'))
|
||||
self.exportBibleItem.setVisible(False)
|
||||
|
||||
def onBibleImportClick(self):
|
||||
@ -96,7 +96,6 @@ class BiblePlugin(Plugin):
|
||||
def usesTheme(self, theme):
|
||||
"""
|
||||
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:
|
||||
@ -116,3 +115,60 @@ class BiblePlugin(Plugin):
|
||||
The new name the plugin should now use.
|
||||
"""
|
||||
self.settings_tab.bible_theme = newTheme
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('BiblesPlugin', 'Bible'),
|
||||
u'plural': translate('BiblesPlugin', 'Bibles')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('BiblesPlugin', 'Bibles')
|
||||
}
|
||||
# Middle Header Bar
|
||||
## Import Button ##
|
||||
self.textStrings[StringContent.Import] = {
|
||||
u'title': translate('BiblesPlugin', 'Import'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Import a Bible')
|
||||
}
|
||||
## New Button ##
|
||||
self.textStrings[StringContent.New] = {
|
||||
u'title': translate('BiblesPlugin', 'Add'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Add a new Bible')
|
||||
}
|
||||
## Edit Button ##
|
||||
self.textStrings[StringContent.Edit] = {
|
||||
u'title': translate('BiblesPlugin', 'Edit'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Edit the selected Bible')
|
||||
}
|
||||
## Delete Button ##
|
||||
self.textStrings[StringContent.Delete] = {
|
||||
u'title': translate('BiblesPlugin', 'Delete'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Delete the selected Bible')
|
||||
}
|
||||
## Preview ##
|
||||
self.textStrings[StringContent.Preview] = {
|
||||
u'title': translate('BiblesPlugin', 'Preview'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Preview the selected Bible')
|
||||
}
|
||||
## Live Button ##
|
||||
self.textStrings[StringContent.Live] = {
|
||||
u'title': translate('BiblesPlugin', 'Live'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Send the selected Bible live')
|
||||
}
|
||||
## Add to service Button ##
|
||||
self.textStrings[StringContent.Service] = {
|
||||
u'title': translate('BiblesPlugin', 'Service'),
|
||||
u'tooltip': translate('BiblesPlugin',
|
||||
'Add the selected Bible to the service')
|
||||
}
|
@ -275,14 +275,14 @@ class Ui_BibleImportWizard(object):
|
||||
self.CopyrightEdit.setObjectName(u'CopyrightEdit')
|
||||
self.LicenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
|
||||
self.CopyrightEdit)
|
||||
self.PermissionLabel = QtGui.QLabel(self.LicenseDetailsPage)
|
||||
self.PermissionLabel.setObjectName(u'PermissionLabel')
|
||||
self.PermissionsLabel = QtGui.QLabel(self.LicenseDetailsPage)
|
||||
self.PermissionsLabel.setObjectName(u'PermissionsLabel')
|
||||
self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
|
||||
self.PermissionLabel)
|
||||
self.PermissionEdit = QtGui.QLineEdit(self.LicenseDetailsPage)
|
||||
self.PermissionEdit.setObjectName(u'PermissionEdit')
|
||||
self.PermissionsLabel)
|
||||
self.PermissionsEdit = QtGui.QLineEdit(self.LicenseDetailsPage)
|
||||
self.PermissionsEdit.setObjectName(u'PermissionsEdit')
|
||||
self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
|
||||
self.PermissionEdit)
|
||||
self.PermissionsEdit)
|
||||
BibleImportWizard.addPage(self.LicenseDetailsPage)
|
||||
self.ImportPage = QtGui.QWizardPage()
|
||||
self.ImportPage.setObjectName(u'ImportPage')
|
||||
@ -372,8 +372,8 @@ class Ui_BibleImportWizard(object):
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Version name:'))
|
||||
self.CopyrightLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Copyright:'))
|
||||
self.PermissionLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Permission:'))
|
||||
self.PermissionsLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Permissions:'))
|
||||
self.ImportPage.setTitle(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Importing'))
|
||||
self.ImportPage.setSubTitle(
|
||||
|
@ -282,7 +282,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
self.LicenseDetailsPage.registerField(
|
||||
u'license_copyright', self.CopyrightEdit)
|
||||
self.LicenseDetailsPage.registerField(
|
||||
u'license_permission', self.PermissionEdit)
|
||||
u'license_permissions', self.PermissionsEdit)
|
||||
|
||||
def setDefaults(self):
|
||||
settings = QtCore.QSettings()
|
||||
@ -308,8 +308,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
QtCore.QVariant(self.VersionNameEdit.text()))
|
||||
self.setField(u'license_copyright',
|
||||
QtCore.QVariant(self.CopyrightEdit.text()))
|
||||
self.setField(u'license_permission',
|
||||
QtCore.QVariant(self.PermissionEdit.text()))
|
||||
self.setField(u'license_permissions',
|
||||
QtCore.QVariant(self.PermissionsEdit.text()))
|
||||
self.onLocationComboBoxChanged(WebDownload.Crosswalk)
|
||||
settings.endGroup()
|
||||
|
||||
@ -391,8 +391,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
bible_type = self.field(u'source_format').toInt()[0]
|
||||
license_version = unicode(self.field(u'license_version').toString())
|
||||
license_copyright = unicode(self.field(u'license_copyright').toString())
|
||||
license_permission = \
|
||||
unicode(self.field(u'license_permission').toString())
|
||||
license_permissions = \
|
||||
unicode(self.field(u'license_permissions').toString())
|
||||
importer = None
|
||||
if bible_type == BibleFormat.OSIS:
|
||||
# Import an OSIS bible
|
||||
@ -436,7 +436,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
|
||||
)
|
||||
if importer.do_import():
|
||||
self.manager.save_meta_data(license_version, license_version,
|
||||
license_copyright, license_permission)
|
||||
license_copyright, license_permissions)
|
||||
self.manager.reload_bibles()
|
||||
self.ImportProgressLabel.setText(
|
||||
translate('BiblesPlugin.ImportWizardForm', 'Finished import.'))
|
||||
|
@ -60,22 +60,32 @@ def parse_reference(reference):
|
||||
and converts it to a reference list, a list of references to be queried
|
||||
from the Bible database files.
|
||||
|
||||
BIBLE_REFERENCE regular expression produces the following match groups:
|
||||
0 This is a special group consisting of the whole string that matched.
|
||||
1 [\w ]+ The book the reference is from.
|
||||
2 [0-9]+ The first (or only) chapter in the reference.
|
||||
3 None|[0-9]+ None or the only verse or the first verse in a
|
||||
verse range or the start verse in a chapter range.
|
||||
4 None|[0-9]+|end None or the end verse of the first verse range or
|
||||
the end chapter of a chapter range.
|
||||
5 None|[0-9]+ None or the second chapter in multiple
|
||||
(non-ranged) chapters.
|
||||
6 None|[0-9]+|end None, the start of the second verse range or the
|
||||
end of a chapter range.
|
||||
7 None|[0-9]+|end None or the end of the second verse range.
|
||||
The ``BIBLE_REFERENCE`` constant regular expression produces the following
|
||||
match groups:
|
||||
|
||||
0. (match string)
|
||||
This is a special group consisting of the whole string that matched.
|
||||
1. ``[\w ]+``
|
||||
The book the reference is from.
|
||||
2. ``[0-9]+``
|
||||
The first (or only) chapter in the reference.
|
||||
3. ``None`` or ``[0-9]+``
|
||||
``None``, or the only verse, or the first verse in a verse range or,
|
||||
the start verse in a chapter range.
|
||||
4. ``None`` or ``[0-9]+`` or ``end``
|
||||
``None``, or the end verse of the first verse range, or the end chapter
|
||||
of a chapter range.
|
||||
5. ``None`` or ``[0-9]+``
|
||||
``None``, or the second chapter in multiple (non-ranged) chapters.
|
||||
6. ``None`` or ``[0-9]+`` or ``end``
|
||||
``None``, the start of the second verse range. or the end of a chapter
|
||||
range.
|
||||
7. ``None`` or ``[0-9]+`` or ``end``
|
||||
``None``, or the end of the second verse range.
|
||||
|
||||
The reference list is a list of tuples, with each tuple structured like
|
||||
this::
|
||||
|
||||
(book, chapter, start_verse, end_verse)
|
||||
|
||||
``reference``
|
||||
@ -154,7 +164,7 @@ def parse_reference(reference):
|
||||
|
||||
class SearchResults(object):
|
||||
"""
|
||||
Encapsulate a set of search results. This is Bible-type independant.
|
||||
Encapsulate a set of search results. This is Bible-type independent.
|
||||
"""
|
||||
def __init__(self, book, chapter, verselist):
|
||||
"""
|
||||
|
@ -38,15 +38,14 @@ class BiblesTab(SettingsTab):
|
||||
"""
|
||||
log.info(u'Bible Tab loaded')
|
||||
|
||||
def __init__(self, title):
|
||||
def __init__(self, title, visible_title):
|
||||
self.paragraph_style = True
|
||||
self.show_new_chapters = False
|
||||
self.display_style = 0
|
||||
SettingsTab.__init__(self, title)
|
||||
SettingsTab.__init__(self, title, visible_title)
|
||||
|
||||
def setupUi(self):
|
||||
self.setObjectName(u'BiblesTab')
|
||||
self.tabTitleVisible = translate('BiblesPlugin.BiblesTab', 'Bibles')
|
||||
self.BibleLayout = QtGui.QHBoxLayout(self)
|
||||
self.BibleLayout.setSpacing(8)
|
||||
self.BibleLayout.setMargin(8)
|
||||
|
@ -64,10 +64,10 @@ class Verse(BaseModel):
|
||||
|
||||
def init_schema(url):
|
||||
"""
|
||||
Setup a bible database connection and initialise the database schema
|
||||
Setup a bible database connection and initialise the database schema.
|
||||
|
||||
``url``
|
||||
The database to setup
|
||||
The database to setup.
|
||||
"""
|
||||
session, metadata = init_db(url)
|
||||
|
||||
@ -240,7 +240,7 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
and the value is the verse text.
|
||||
"""
|
||||
log.debug(u'create_chapter %s,%s', book_id, chapter)
|
||||
#text list has book and chapter as first two elements of the array
|
||||
# text list has book and chapter as first two elements of the array
|
||||
for verse_number, verse_text in textlist.iteritems():
|
||||
verse = Verse.populate(
|
||||
book_id = book_id,
|
||||
@ -281,23 +281,23 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
|
||||
def create_meta(self, key, value):
|
||||
"""
|
||||
Utility method to save BibleMeta objects in a Bible database
|
||||
Utility method to save BibleMeta objects in a Bible database.
|
||||
|
||||
``key``
|
||||
The key for this instance
|
||||
The key for this instance.
|
||||
|
||||
``value``
|
||||
The value for this instance
|
||||
The value for this instance.
|
||||
"""
|
||||
log.debug(u'save_meta %s/%s', key, value)
|
||||
self.save_object(BibleMeta.populate(key=key, value=value))
|
||||
|
||||
def get_book(self, book):
|
||||
"""
|
||||
Return a book object from the database
|
||||
Return a book object from the database.
|
||||
|
||||
``book``
|
||||
The name of the book to return
|
||||
The name of the book to return.
|
||||
"""
|
||||
log.debug(u'BibleDb.get_book("%s")', book)
|
||||
db_book = self.get_object_filtered(Book, Book.name.like(book + u'%'))
|
||||
@ -353,9 +353,9 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
QtGui.QMessageBox.information(self.bible_plugin.mediaItem,
|
||||
translate('BiblesPlugin.BibleDB', 'Book not found'),
|
||||
translate('BiblesPlugin.BibleDB', 'The book you requested '
|
||||
'could not be found in this bible. Please check your '
|
||||
'spelling and that this is a complete bible not just '
|
||||
'one testament.'))
|
||||
'could not be found in this Bible. Please check your '
|
||||
'spelling and that this is a complete Bible not just '
|
||||
'one testament.'))
|
||||
return verse_list
|
||||
|
||||
def verse_search(self, text):
|
||||
@ -387,10 +387,10 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
|
||||
def get_chapter_count(self, book):
|
||||
"""
|
||||
Return the number of chapters in a book
|
||||
Return the number of chapters in a book.
|
||||
|
||||
``book``
|
||||
The book to get the chapter count for
|
||||
The book to get the chapter count for.
|
||||
"""
|
||||
log.debug(u'BibleDB.get_chapter_count("%s")', book)
|
||||
count = self.session.query(Verse.chapter).join(Book)\
|
||||
@ -403,13 +403,13 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
|
||||
def get_verse_count(self, book, chapter):
|
||||
"""
|
||||
Return the number of verses in a chapter
|
||||
Return the number of verses in a chapter.
|
||||
|
||||
``book``
|
||||
The book containing the chapter
|
||||
The book containing the chapter.
|
||||
|
||||
``chapter``
|
||||
The chapter to get the verse count for
|
||||
The chapter to get the verse count for.
|
||||
"""
|
||||
log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter)
|
||||
count = self.session.query(Verse).join(Book)\
|
||||
@ -423,7 +423,7 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
|
||||
def dump_bible(self):
|
||||
"""
|
||||
Utility debugging method to dump the contents of a bible
|
||||
Utility debugging method to dump the contents of a bible.
|
||||
"""
|
||||
log.debug(u'.........Dumping Bible Database')
|
||||
log.debug('...............................Books ')
|
||||
|
@ -187,16 +187,16 @@ class BGExtract(object):
|
||||
|
||||
def get_bible_chapter(self, version, bookname, chapter):
|
||||
"""
|
||||
Access and decode bibles via the BibleGateway website
|
||||
Access and decode bibles via the BibleGateway website.
|
||||
|
||||
``version``
|
||||
The version of the bible like 31 for New International version
|
||||
The version of the bible like 31 for New International version.
|
||||
|
||||
``bookname``
|
||||
Name of the Book
|
||||
Name of the Book.
|
||||
|
||||
``chapter``
|
||||
Chapter number
|
||||
Chapter number.
|
||||
"""
|
||||
log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter)
|
||||
url_params = urllib.urlencode(
|
||||
@ -298,13 +298,13 @@ class CWExtract(object):
|
||||
versetext = versetext + part
|
||||
elif part and part.attrMap and \
|
||||
(part.attrMap[u'class'] == u'WordsOfChrist' or \
|
||||
part.attrMap[u'class'] == u'strongs'):
|
||||
part.attrMap[u'class'] == u'strongs'):
|
||||
for subpart in part.contents:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
if isinstance(subpart, NavigableString):
|
||||
versetext = versetext + subpart
|
||||
elif subpart and subpart.attrMap and \
|
||||
subpart.attrMap[u'class'] == u'strongs':
|
||||
subpart.attrMap[u'class'] == u'strongs':
|
||||
for subsub in subpart.contents:
|
||||
Receiver.send_message(u'openlp_process_events')
|
||||
if isinstance(subsub, NavigableString):
|
||||
@ -428,7 +428,7 @@ class HTTPBible(BibleDB):
|
||||
|
||||
def get_chapter(self, book, chapter):
|
||||
"""
|
||||
Receive the request and call the relevant handler methods
|
||||
Receive the request and call the relevant handler methods.
|
||||
"""
|
||||
log.debug(u'get_chapter %s, %s', book, chapter)
|
||||
log.debug(u'source = %s', self.download_source)
|
||||
|
@ -137,7 +137,7 @@ class BibleManager(object):
|
||||
name = bible.get_name()
|
||||
log.debug(u'Bible Name: "%s"', name)
|
||||
self.db_cache[name] = bible
|
||||
# look to see if lazy load bible exists and get create getter.
|
||||
# Look to see if lazy load bible exists and get create getter.
|
||||
source = self.db_cache[name].get_object(BibleMeta,
|
||||
u'download source')
|
||||
if source:
|
||||
@ -181,10 +181,10 @@ class BibleManager(object):
|
||||
|
||||
def get_bibles(self):
|
||||
"""
|
||||
Returns a list of the names of available Bibles.
|
||||
Returns a dict with all available Bibles.
|
||||
"""
|
||||
log.debug(u'get_bibles')
|
||||
return self.db_cache.keys()
|
||||
return self.db_cache
|
||||
|
||||
def get_books(self, bible):
|
||||
"""
|
||||
@ -204,7 +204,7 @@ class BibleManager(object):
|
||||
|
||||
def get_chapter_count(self, bible, book):
|
||||
"""
|
||||
Returns the number of Chapters for a given book
|
||||
Returns the number of Chapters for a given book.
|
||||
"""
|
||||
log.debug(u'get_book_chapter_count %s', book)
|
||||
return self.db_cache[bible].get_chapter_count(book)
|
||||
@ -212,7 +212,7 @@ class BibleManager(object):
|
||||
def get_verse_count(self, bible, book, chapter):
|
||||
"""
|
||||
Returns all the number of verses for a given
|
||||
book and chapterMaxBibleBookVerses
|
||||
book and chapterMaxBibleBookVerses.
|
||||
"""
|
||||
log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)',
|
||||
bible, book, chapter)
|
||||
@ -254,12 +254,35 @@ class BibleManager(object):
|
||||
'Book Chapter:Verse-Verse\n'
|
||||
'Book Chapter:Verse-Verse,Verse-Verse\n'
|
||||
'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n'
|
||||
'Book Chapter:Verse-Chapter:Verse\n'))
|
||||
'Book Chapter:Verse-Chapter:Verse'))
|
||||
return None
|
||||
|
||||
def verse_search(self, bible, text):
|
||||
"""
|
||||
Does a verse search for the given bible and text.
|
||||
|
||||
``bible``
|
||||
The bible to seach in (unicode).
|
||||
|
||||
``text``
|
||||
The text to search for (unicode).
|
||||
"""
|
||||
log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text)
|
||||
if text:
|
||||
return self.db_cache[bible].verse_search(text)
|
||||
else:
|
||||
QtGui.QMessageBox.information(self.parent.mediaItem,
|
||||
translate('BiblesPlugin.BibleManager',
|
||||
'Scripture Reference Error'),
|
||||
translate('BiblesPlugin.BibleManager', 'You did not enter a '
|
||||
'search keyword.\nYou can separate different keywords by a '
|
||||
'space to search for all of your keywords and you can seperate '
|
||||
'them by a comma to search for one of them.'))
|
||||
return None
|
||||
|
||||
def save_meta_data(self, bible, version, copyright, permissions):
|
||||
"""
|
||||
Saves the bibles meta data
|
||||
Saves the bibles meta data.
|
||||
"""
|
||||
log.debug(u'save_meta data %s,%s, %s,%s',
|
||||
bible, version, copyright, permissions)
|
||||
@ -269,14 +292,14 @@ class BibleManager(object):
|
||||
|
||||
def get_meta_data(self, bible, key):
|
||||
"""
|
||||
Returns the meta data for a given key
|
||||
Returns the meta data for a given key.
|
||||
"""
|
||||
log.debug(u'get_meta %s,%s', bible, key)
|
||||
return self.db_cache[bible].get_object(BibleMeta, key)
|
||||
|
||||
def exists(self, name):
|
||||
"""
|
||||
Check cache to see if new bible
|
||||
Check cache to see if new bible.
|
||||
"""
|
||||
if not isinstance(name, unicode):
|
||||
name = unicode(name)
|
||||
|
@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui
|
||||
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
|
||||
ItemCapabilities, translate
|
||||
from openlp.plugins.bibles.forms import ImportWizardForm
|
||||
from openlp.plugins.bibles.lib.db import BibleDB
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -374,7 +375,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.AdvancedSecondBibleComboBox.clear()
|
||||
self.QuickSecondBibleComboBox.addItem(u'')
|
||||
self.AdvancedSecondBibleComboBox.addItem(u'')
|
||||
bibles = self.parent.manager.get_bibles()
|
||||
bibles = self.parent.manager.get_bibles().keys()
|
||||
# load bibles into the combo boxes
|
||||
first = True
|
||||
for bible in bibles:
|
||||
@ -407,21 +408,21 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.initialiseChapterVerse(bible, book[u'name'],
|
||||
book[u'chapters'])
|
||||
|
||||
def initialiseChapterVerse(self, bible, book, chapters):
|
||||
def initialiseChapterVerse(self, bible, book, chapter_count):
|
||||
log.debug(u'initialiseChapterVerse %s, %s', bible, book)
|
||||
self.chapters_from = chapters
|
||||
self.verses = self.parent.manager.get_verse_count(bible, book, 1)
|
||||
if self.verses == 0:
|
||||
self.chapter_count = chapter_count
|
||||
verse_count = self.parent.manager.get_verse_count(bible, book, 1)
|
||||
if verse_count == 0:
|
||||
self.AdvancedSearchButton.setEnabled(False)
|
||||
self.AdvancedMessage.setText(
|
||||
translate('BiblesPlugin.MediaItem', 'Bible not fully loaded.'))
|
||||
else:
|
||||
self.AdvancedSearchButton.setEnabled(True)
|
||||
self.AdvancedMessage.setText(u'')
|
||||
self.adjustComboBox(1, self.chapters_from, self.AdvancedFromChapter)
|
||||
self.adjustComboBox(1, self.chapters_from, self.AdvancedToChapter)
|
||||
self.adjustComboBox(1, self.verses, self.AdvancedFromVerse)
|
||||
self.adjustComboBox(1, self.verses, self.AdvancedToVerse)
|
||||
self.adjustComboBox(1, self.chapter_count, self.AdvancedFromChapter)
|
||||
self.adjustComboBox(1, self.chapter_count, self.AdvancedToChapter)
|
||||
self.adjustComboBox(1, verse_count, self.AdvancedFromVerse)
|
||||
self.adjustComboBox(1, verse_count, self.AdvancedToVerse)
|
||||
|
||||
def onAdvancedVersionComboBox(self):
|
||||
self.initialiseBible(
|
||||
@ -435,47 +436,69 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.AdvancedBookComboBox.itemData(item).toInt()[0])
|
||||
|
||||
def onAdvancedFromVerse(self):
|
||||
frm = int(self.AdvancedFromVerse.currentText())
|
||||
chapter_frm = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_from = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
if chapter_frm == chapter_to:
|
||||
if chapter_from == chapter_to:
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
verses = self.parent.manager.get_verse_count(bible, book, chapter_to)
|
||||
self.adjustComboBox(frm, verses, self.AdvancedToVerse)
|
||||
verse_from = int(self.AdvancedFromVerse.currentText())
|
||||
verse_count = self.parent.manager.get_verse_count(bible, book,
|
||||
chapter_to)
|
||||
self.adjustComboBox(verse_from, verse_count,
|
||||
self.AdvancedToVerse, True)
|
||||
|
||||
def onAdvancedToChapter(self):
|
||||
chapter_frm = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
verses = self.parent.manager.get_verse_count(bible, book, chapter_to)
|
||||
if chapter_frm != chapter_to:
|
||||
self.adjustComboBox(1, verses, self.AdvancedToVerse)
|
||||
chapter_from = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
verse_from = int(self.AdvancedFromVerse.currentText())
|
||||
verse_to = int(self.AdvancedToVerse.currentText())
|
||||
verse_count = self.parent.manager.get_verse_count(bible, book,
|
||||
chapter_to)
|
||||
if chapter_from == chapter_to and verse_from > verse_to:
|
||||
self.adjustComboBox(verse_from, verse_count, self.AdvancedToVerse)
|
||||
else:
|
||||
frm = int(self.AdvancedFromVerse.currentText())
|
||||
to = int(self.AdvancedToVerse.currentText())
|
||||
if to < frm:
|
||||
self.adjustComboBox(frm, verses, self.AdvancedToVerse)
|
||||
self.adjustComboBox(1, verse_count, self.AdvancedToVerse)
|
||||
|
||||
def onAdvancedFromChapter(self):
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
chapter_frm = int(self.AdvancedFromChapter.currentText())
|
||||
self.adjustComboBox(chapter_frm, self.chapters_from,
|
||||
self.AdvancedToChapter)
|
||||
verse = self.parent.manager.get_verse_count(bible, book, chapter_frm)
|
||||
self.adjustComboBox(1, verse, self.AdvancedToVerse)
|
||||
self.adjustComboBox(1, verse, self.AdvancedFromVerse)
|
||||
chapter_from = int(self.AdvancedFromChapter.currentText())
|
||||
chapter_to = int(self.AdvancedToChapter.currentText())
|
||||
verse_count = self.parent.manager.get_verse_count(bible, book,
|
||||
chapter_from)
|
||||
self.adjustComboBox(1, verse_count, self.AdvancedFromVerse)
|
||||
if chapter_from > chapter_to:
|
||||
self.adjustComboBox(1, verse_count, self.AdvancedToVerse)
|
||||
self.adjustComboBox(chapter_from, self.chapter_count,
|
||||
self.AdvancedToChapter)
|
||||
elif chapter_from == chapter_to:
|
||||
self.adjustComboBox(chapter_from, self.chapter_count,
|
||||
self.AdvancedToChapter)
|
||||
self.adjustComboBox(1, verse_count, self.AdvancedToVerse, True)
|
||||
else:
|
||||
self.adjustComboBox(chapter_from, self.chapter_count,
|
||||
self.AdvancedToChapter, True)
|
||||
|
||||
def adjustComboBox(self, range_from, range_to, combo):
|
||||
def adjustComboBox(self, range_from, range_to, combo, restore=False):
|
||||
"""
|
||||
``restore``
|
||||
If True, then the combo's currentText will be restored after
|
||||
adjusting (if possible).
|
||||
"""
|
||||
log.debug(u'adjustComboBox %s, %s, %s', combo, range_from, range_to)
|
||||
if restore:
|
||||
old_text = unicode(combo.currentText())
|
||||
combo.clear()
|
||||
for i in range(int(range_from), int(range_to) + 1):
|
||||
combo.addItem(unicode(i))
|
||||
if restore and combo.findText(old_text) != -1:
|
||||
combo.setCurrentIndex(combo.findText(old_text))
|
||||
|
||||
def onAdvancedSearchButton(self):
|
||||
log.debug(u'Advanced Search Button pressed')
|
||||
self.AdvancedSearchButton.setEnabled(False)
|
||||
bible = unicode(self.AdvancedVersionComboBox.currentText())
|
||||
dual_bible = unicode(self.AdvancedSecondBibleComboBox.currentText())
|
||||
book = unicode(self.AdvancedBookComboBox.currentText())
|
||||
@ -508,16 +531,30 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.displayResults(bible, dual_bible)
|
||||
else:
|
||||
self.displayResults(bible, dual_bible)
|
||||
self.AdvancedSearchButton.setEnabled(True)
|
||||
|
||||
def onQuickSearchButton(self):
|
||||
log.debug(u'Quick Search Button pressed')
|
||||
self.QuickSearchButton.setEnabled(False)
|
||||
bible = unicode(self.QuickVersionComboBox.currentText())
|
||||
dual_bible = unicode(self.QuickSecondBibleComboBox.currentText())
|
||||
text = unicode(self.QuickSearchEdit.text())
|
||||
self.search_results = self.parent.manager.get_verses(bible, text)
|
||||
if dual_bible:
|
||||
self.dual_search_results = self.parent.manager.get_verses(
|
||||
dual_bible, text)
|
||||
if self.QuickSearchComboBox.currentIndex() == 0:
|
||||
# We are doing a 'Verse Search'.
|
||||
self.search_results = self.parent.manager.get_verses(bible, text)
|
||||
if dual_bible and self.search_results:
|
||||
self.dual_search_results = self.parent.manager.get_verses(
|
||||
dual_bible, text)
|
||||
else:
|
||||
# We are doing a ' Text Search'.
|
||||
bibles = self.parent.manager.get_bibles()
|
||||
self.search_results = self.parent.manager.verse_search(bible, text)
|
||||
if dual_bible and self.search_results:
|
||||
text = []
|
||||
for verse in self.search_results:
|
||||
text.append((verse.book.name, verse.chapter, verse.verse,
|
||||
verse.verse))
|
||||
self.dual_search_results = bibles[dual_bible].get_verses(text)
|
||||
if self.ClearQuickSearchComboBox.currentIndex() == 0:
|
||||
self.listView.clear()
|
||||
if self.listView.count() != 0 and self.search_results:
|
||||
@ -537,6 +574,7 @@ class BibleMediaItem(MediaManagerItem):
|
||||
self.displayResults(bible, dual_bible)
|
||||
elif self.search_results:
|
||||
self.displayResults(bible, dual_bible)
|
||||
self.QuickSearchButton.setEnabled(True)
|
||||
|
||||
def displayResults(self, bible, dual_bible=u''):
|
||||
"""
|
||||
@ -545,16 +583,16 @@ class BibleMediaItem(MediaManagerItem):
|
||||
"""
|
||||
version = self.parent.manager.get_meta_data(bible, u'Version')
|
||||
copyright = self.parent.manager.get_meta_data(bible, u'Copyright')
|
||||
permission = self.parent.manager.get_meta_data(bible, u'Permissions')
|
||||
permissions = self.parent.manager.get_meta_data(bible, u'Permissions')
|
||||
if dual_bible:
|
||||
dual_version = self.parent.manager.get_meta_data(dual_bible,
|
||||
u'Version')
|
||||
dual_copyright = self.parent.manager.get_meta_data(dual_bible,
|
||||
u'Copyright')
|
||||
dual_permission = self.parent.manager.get_meta_data(dual_bible,
|
||||
dual_permissions = self.parent.manager.get_meta_data(dual_bible,
|
||||
u'Permissions')
|
||||
if not dual_permission:
|
||||
dual_permission = u''
|
||||
if not dual_permissions:
|
||||
dual_permissions = u''
|
||||
# We count the number of rows which are maybe already present.
|
||||
start_count = self.listView.count()
|
||||
for count, verse in enumerate(self.search_results):
|
||||
@ -566,12 +604,12 @@ class BibleMediaItem(MediaManagerItem):
|
||||
'bible': QtCore.QVariant(bible),
|
||||
'version': QtCore.QVariant(version.value),
|
||||
'copyright': QtCore.QVariant(copyright.value),
|
||||
'permission': QtCore.QVariant(permission.value),
|
||||
'permissions': QtCore.QVariant(permissions.value),
|
||||
'text': QtCore.QVariant(verse.text),
|
||||
'dual_bible': QtCore.QVariant(dual_bible),
|
||||
'dual_version': QtCore.QVariant(dual_version.value),
|
||||
'dual_copyright': QtCore.QVariant(dual_copyright.value),
|
||||
'dual_permission': QtCore.QVariant(dual_permission.value),
|
||||
'dual_permissions': QtCore.QVariant(dual_permissions.value),
|
||||
'dual_text': QtCore.QVariant(
|
||||
self.dual_search_results[count].text)
|
||||
}
|
||||
@ -586,12 +624,12 @@ class BibleMediaItem(MediaManagerItem):
|
||||
'bible': QtCore.QVariant(bible),
|
||||
'version': QtCore.QVariant(version.value),
|
||||
'copyright': QtCore.QVariant(copyright.value),
|
||||
'permission': QtCore.QVariant(permission.value),
|
||||
'permissions': QtCore.QVariant(permissions.value),
|
||||
'text': QtCore.QVariant(verse.text),
|
||||
'dual_bible': QtCore.QVariant(u''),
|
||||
'dual_version': QtCore.QVariant(u''),
|
||||
'dual_copyright': QtCore.QVariant(u''),
|
||||
'dual_permission': QtCore.QVariant(u''),
|
||||
'dual_permissions': QtCore.QVariant(u''),
|
||||
'dual_text': QtCore.QVariant(u'')
|
||||
}
|
||||
bible_text = u' %s %d:%d (%s)' % (verse.book.name,
|
||||
@ -637,20 +675,20 @@ class BibleMediaItem(MediaManagerItem):
|
||||
bible = self._decodeQtObject(bitem, 'bible')
|
||||
version = self._decodeQtObject(bitem, 'version')
|
||||
copyright = self._decodeQtObject(bitem, 'copyright')
|
||||
permission = self._decodeQtObject(bitem, 'permission')
|
||||
permissions = self._decodeQtObject(bitem, 'permissions')
|
||||
text = self._decodeQtObject(bitem, 'text')
|
||||
dual_bible = self._decodeQtObject(bitem, 'dual_bible')
|
||||
dual_version = self._decodeQtObject(bitem, 'dual_version')
|
||||
dual_copyright = self._decodeQtObject(bitem, 'dual_copyright')
|
||||
dual_permission = self._decodeQtObject(bitem, 'dual_permission')
|
||||
dual_permissions = self._decodeQtObject(bitem, 'dual_permissions')
|
||||
dual_text = self._decodeQtObject(bitem, 'dual_text')
|
||||
verse_text = self.formatVerse(old_chapter, chapter, verse)
|
||||
footer = u'%s (%s %s %s)' % (book, version, copyright, permission)
|
||||
footer = u'%s (%s %s %s)' % (book, version, copyright, permissions)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
if dual_bible:
|
||||
footer = u'%s (%s %s %s)' % (book, dual_version, dual_copyright,
|
||||
dual_permission)
|
||||
dual_permissions)
|
||||
if footer not in raw_footer:
|
||||
raw_footer.append(footer)
|
||||
bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text,
|
||||
|
@ -28,7 +28,7 @@ import logging
|
||||
|
||||
from forms import EditCustomForm
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.custom.lib import CustomMediaItem, CustomTab
|
||||
from openlp.plugins.custom.lib.db import CustomSlide, init_schema
|
||||
@ -55,11 +55,12 @@ class CustomPlugin(Plugin):
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
||||
def getSettingsTab(self):
|
||||
return CustomTab(self.name)
|
||||
visible_name = self.getString(StringContent.VisibleName)
|
||||
return CustomTab(self.name, visible_name[u'title'])
|
||||
|
||||
def getMediaManagerItem(self):
|
||||
# Create the CustomManagerItem object
|
||||
return CustomMediaItem(self, self.icon, self.name)
|
||||
return CustomMediaItem(self, self, self.icon)
|
||||
|
||||
def about(self):
|
||||
about_text = translate('CustomPlugin', '<strong>Custom Plugin</strong>'
|
||||
@ -96,3 +97,66 @@ class CustomPlugin(Plugin):
|
||||
for custom in customsUsingTheme:
|
||||
custom.theme_name = newTheme
|
||||
self.custommanager.save_object(custom)
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('CustomsPlugin', 'Custom'),
|
||||
u'plural': translate('CustomsPlugin', 'Customs')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('CustomsPlugin', 'Customs')
|
||||
}
|
||||
# Middle Header Bar
|
||||
## Import Button ##
|
||||
self.textStrings[StringContent.Import] = {
|
||||
u'title': translate('CustomsPlugin', 'Import'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Import a Custom')
|
||||
}
|
||||
## Load Button ##
|
||||
self.textStrings[StringContent.Load] = {
|
||||
u'title': translate('CustomsPlugin', 'Load'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Load a new Custom')
|
||||
}
|
||||
## New Button ##
|
||||
self.textStrings[StringContent.New] = {
|
||||
u'title': translate('CustomsPlugin', 'Add'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Add a new Custom')
|
||||
}
|
||||
## Edit Button ##
|
||||
self.textStrings[StringContent.Edit] = {
|
||||
u'title': translate('CustomsPlugin', 'Edit'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Edit the selected Custom')
|
||||
}
|
||||
## Delete Button ##
|
||||
self.textStrings[StringContent.Delete] = {
|
||||
u'title': translate('CustomsPlugin', 'Delete'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Delete the selected Custom')
|
||||
}
|
||||
## Preview ##
|
||||
self.textStrings[StringContent.Preview] = {
|
||||
u'title': translate('CustomsPlugin', 'Preview'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Preview the selected Custom')
|
||||
}
|
||||
## Live Button ##
|
||||
self.textStrings[StringContent.Live] = {
|
||||
u'title': translate('CustomsPlugin', 'Live'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Send the selected Custom live')
|
||||
}
|
||||
## Add to service Button ##
|
||||
self.textStrings[StringContent.Service] = {
|
||||
u'title': translate('CustomsPlugin', 'Service'),
|
||||
u'tooltip': translate('CustomsPlugin',
|
||||
'Add the selected Custom to the service')
|
||||
}
|
@ -25,3 +25,4 @@
|
||||
###############################################################################
|
||||
|
||||
from editcustomform import EditCustomForm
|
||||
from editcustomslideform import EditCustomSlideForm
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import build_icon, translate, SpellTextEdit
|
||||
from openlp.core.lib import build_icon, translate
|
||||
|
||||
class Ui_CustomEditDialog(object):
|
||||
def setupUi(self, customEditDialog):
|
||||
@ -36,6 +36,70 @@ class Ui_CustomEditDialog(object):
|
||||
build_icon(u':/icon/openlp.org-icon-32.bmp'))
|
||||
self.gridLayout = QtGui.QGridLayout(customEditDialog)
|
||||
self.gridLayout.setObjectName(u'gridLayout')
|
||||
self.horizontalLayout3 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout3.setObjectName(u'horizontalLayout3')
|
||||
self.themeLabel = QtGui.QLabel(customEditDialog)
|
||||
self.themeLabel.setObjectName(u'themeLabel')
|
||||
self.horizontalLayout3.addWidget(self.themeLabel)
|
||||
self.themeComboBox = QtGui.QComboBox(customEditDialog)
|
||||
self.themeLabel.setBuddy(self.themeComboBox)
|
||||
self.themeComboBox.setObjectName(u'themeComboBox')
|
||||
self.horizontalLayout3.addWidget(self.themeComboBox)
|
||||
self.gridLayout.addLayout(self.horizontalLayout3, 2, 0, 1, 1)
|
||||
self.horizontalLayout2 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout2.setObjectName(u'horizontalLayout2')
|
||||
self.creditLabel = QtGui.QLabel(customEditDialog)
|
||||
self.creditLabel.setObjectName(u'creditLabel')
|
||||
self.horizontalLayout2.addWidget(self.creditLabel)
|
||||
self.creditEdit = QtGui.QLineEdit(customEditDialog)
|
||||
self.creditLabel.setBuddy(self.creditEdit)
|
||||
self.creditEdit.setObjectName(u'creditEdit')
|
||||
self.horizontalLayout2.addWidget(self.creditEdit)
|
||||
self.gridLayout.addLayout(self.horizontalLayout2, 3, 0, 1, 1)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(customEditDialog)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
|
||||
QtGui.QDialogButtonBox.Save)
|
||||
self.buttonBox.setObjectName(u'buttonBox')
|
||||
self.gridLayout.addWidget(self.buttonBox, 4, 0, 1, 1)
|
||||
self.horizontalLayout4 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout4.setObjectName(u'horizontalLayout4')
|
||||
self.slideListView = QtGui.QListWidget(customEditDialog)
|
||||
self.slideListView.setAlternatingRowColors(True)
|
||||
self.slideListView.setObjectName(u'slideListView')
|
||||
self.horizontalLayout4.addWidget(self.slideListView)
|
||||
self.verticalLayout = QtGui.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName(u'verticalLayout')
|
||||
self.addButton = QtGui.QPushButton(customEditDialog)
|
||||
self.addButton.setObjectName(u'addButton')
|
||||
self.verticalLayout.addWidget(self.addButton)
|
||||
self.editButton = QtGui.QPushButton(customEditDialog)
|
||||
self.editButton.setObjectName(u'editButton')
|
||||
self.verticalLayout.addWidget(self.editButton)
|
||||
self.editAllButton = QtGui.QPushButton(customEditDialog)
|
||||
self.editAllButton.setObjectName(u'editAllButton')
|
||||
self.verticalLayout.addWidget(self.editAllButton)
|
||||
self.deleteButton = QtGui.QPushButton(customEditDialog)
|
||||
self.deleteButton.setObjectName(u'deleteButton')
|
||||
self.verticalLayout.addWidget(self.deleteButton)
|
||||
spacerItem = QtGui.QSpacerItem(20, 128, QtGui.QSizePolicy.Minimum,
|
||||
QtGui.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.upButton = QtGui.QPushButton(customEditDialog)
|
||||
icon1 = QtGui.QIcon()
|
||||
icon1.addPixmap(QtGui.QPixmap(u':/services/service_up.png'),
|
||||
QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.upButton.setIcon(icon1)
|
||||
self.upButton.setObjectName(u'upButton')
|
||||
self.verticalLayout.addWidget(self.upButton)
|
||||
self.downButton = QtGui.QPushButton(customEditDialog)
|
||||
icon2 = QtGui.QIcon()
|
||||
icon2.addPixmap(QtGui.QPixmap(u':/services/service_down.png'),
|
||||
QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.downButton.setIcon(icon2)
|
||||
self.downButton.setObjectName(u'downButton')
|
||||
self.verticalLayout.addWidget(self.downButton)
|
||||
self.horizontalLayout4.addLayout(self.verticalLayout)
|
||||
self.gridLayout.addLayout(self.horizontalLayout4, 1, 0, 1, 1)
|
||||
self.horizontalLayout = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName(u'horizontalLayout')
|
||||
self.titleLabel = QtGui.QLabel(customEditDialog)
|
||||
@ -46,91 +110,6 @@ class Ui_CustomEditDialog(object):
|
||||
self.titleEdit.setObjectName(u'titleEdit')
|
||||
self.horizontalLayout.addWidget(self.titleEdit)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
|
||||
self.horizontalLayout4 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout4.setObjectName(u'horizontalLayout4')
|
||||
self.verseListView = QtGui.QListWidget(customEditDialog)
|
||||
self.verseListView.setAlternatingRowColors(True)
|
||||
self.verseListView.setObjectName(u'verseListView')
|
||||
self.horizontalLayout4.addWidget(self.verseListView)
|
||||
self.verticalLayout = QtGui.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName(u'verticalLayout')
|
||||
self.upButton = QtGui.QPushButton(customEditDialog)
|
||||
self.upButton.setIcon(build_icon(u':/services/service_up.png'))
|
||||
self.upButton.setObjectName(u'upButton')
|
||||
self.verticalLayout.addWidget(self.upButton)
|
||||
spacerItem = QtGui.QSpacerItem(20, 128, QtGui.QSizePolicy.Minimum,
|
||||
QtGui.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.downButton = QtGui.QPushButton(customEditDialog)
|
||||
self.downButton.setIcon(build_icon(u':/services/service_down.png'))
|
||||
self.downButton.setObjectName(u'downButton')
|
||||
self.verticalLayout.addWidget(self.downButton)
|
||||
self.horizontalLayout4.addLayout(self.verticalLayout)
|
||||
self.gridLayout.addLayout(self.horizontalLayout4, 1, 0, 1, 1)
|
||||
self.editWidget = QtGui.QWidget(customEditDialog)
|
||||
self.editWidget.setObjectName(u'editWidget')
|
||||
self.editLayout3 = QtGui.QHBoxLayout(self.editWidget)
|
||||
self.editLayout3.setSpacing(8)
|
||||
self.editLayout3.setMargin(0)
|
||||
self.editLayout3.setObjectName(u'editLayout3')
|
||||
self.verseTextEdit = SpellTextEdit(self)
|
||||
self.verseTextEdit.setObjectName(u'verseTextEdit')
|
||||
self.editLayout3.addWidget(self.verseTextEdit)
|
||||
self.buttonWidget = QtGui.QWidget(self.editWidget)
|
||||
self.buttonWidget.setObjectName(u'buttonWidget')
|
||||
self.verticalLayout2 = QtGui.QVBoxLayout(self.buttonWidget)
|
||||
self.verticalLayout2.setObjectName(u'verticalLayout2')
|
||||
self.addButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.addButton.setObjectName(u'addButton')
|
||||
self.verticalLayout2.addWidget(self.addButton)
|
||||
self.editButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.editButton.setObjectName(u'editButton')
|
||||
self.verticalLayout2.addWidget(self.editButton)
|
||||
self.editAllButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.editAllButton.setObjectName(u'editAllButton')
|
||||
self.verticalLayout2.addWidget(self.editAllButton)
|
||||
self.saveButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.saveButton.setObjectName(u'saveButton')
|
||||
self.verticalLayout2.addWidget(self.saveButton)
|
||||
self.deleteButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.deleteButton.setObjectName(u'deleteButton')
|
||||
self.verticalLayout2.addWidget(self.deleteButton)
|
||||
self.clearButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.clearButton.setObjectName(u'clearButton')
|
||||
self.verticalLayout2.addWidget(self.clearButton)
|
||||
self.splitButton = QtGui.QPushButton(self.buttonWidget)
|
||||
self.splitButton.setObjectName(u'splitButton')
|
||||
self.verticalLayout2.addWidget(self.splitButton)
|
||||
spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
|
||||
QtGui.QSizePolicy.Expanding)
|
||||
self.verticalLayout2.addItem(spacerItem1)
|
||||
self.editLayout3.addWidget(self.buttonWidget)
|
||||
self.gridLayout.addWidget(self.editWidget, 2, 0, 1, 1)
|
||||
self.horizontalLayout3 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout3.setObjectName(u'horizontalLayout3')
|
||||
self.themeLabel = QtGui.QLabel(customEditDialog)
|
||||
self.themeLabel.setObjectName(u'themeLabel')
|
||||
self.horizontalLayout3.addWidget(self.themeLabel)
|
||||
self.themeComboBox = QtGui.QComboBox(customEditDialog)
|
||||
self.themeLabel.setBuddy(self.themeComboBox)
|
||||
self.themeComboBox.setObjectName(u'themeComboBox')
|
||||
self.horizontalLayout3.addWidget(self.themeComboBox)
|
||||
self.gridLayout.addLayout(self.horizontalLayout3, 3, 0, 1, 1)
|
||||
self.horizontalLayout2 = QtGui.QHBoxLayout()
|
||||
self.horizontalLayout2.setObjectName(u'horizontalLayout2')
|
||||
self.creditLabel = QtGui.QLabel(customEditDialog)
|
||||
self.creditLabel.setObjectName(u'creditLabel')
|
||||
self.horizontalLayout2.addWidget(self.creditLabel)
|
||||
self.creditEdit = QtGui.QLineEdit(customEditDialog)
|
||||
self.creditLabel.setBuddy(self.creditEdit)
|
||||
self.creditEdit.setObjectName(u'creditEdit')
|
||||
self.horizontalLayout2.addWidget(self.creditEdit)
|
||||
self.gridLayout.addLayout(self.horizontalLayout2, 4, 0, 1, 1)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(customEditDialog)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
|
||||
QtGui.QDialogButtonBox.Save)
|
||||
self.buttonBox.setObjectName(u'buttonBox')
|
||||
self.gridLayout.addWidget(self.buttonBox, 5, 0, 1, 1)
|
||||
self.retranslateUi(customEditDialog)
|
||||
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
|
||||
customEditDialog.accept)
|
||||
@ -143,46 +122,32 @@ class Ui_CustomEditDialog(object):
|
||||
translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides'))
|
||||
self.upButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Move slide up one '
|
||||
'position.'))
|
||||
'position.'))
|
||||
self.downButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Move slide down one '
|
||||
'position.'))
|
||||
'position.'))
|
||||
self.titleLabel.setText(
|
||||
translate('CustomPlugin.EditCustomForm', '&Title:'))
|
||||
self.addButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Add New'))
|
||||
translate('CustomPlugin.EditCustomForm', '&Add'))
|
||||
self.addButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Add a new slide at '
|
||||
'bottom.'))
|
||||
'bottom.'))
|
||||
self.editButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Edit'))
|
||||
translate('CustomPlugin.EditCustomForm', '&Edit'))
|
||||
self.editButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Edit the selected '
|
||||
'slide.'))
|
||||
'slide.'))
|
||||
self.editAllButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Edit All'))
|
||||
translate('CustomPlugin.EditCustomForm', 'Ed&it All'))
|
||||
self.editAllButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Edit all the slides at '
|
||||
'once.'))
|
||||
self.saveButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Save'))
|
||||
self.saveButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Save the slide currently '
|
||||
'being edited.'))
|
||||
'once.'))
|
||||
self.deleteButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Delete'))
|
||||
translate('CustomPlugin.EditCustomForm', '&Delete'))
|
||||
self.deleteButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Delete the selected '
|
||||
'slide.'))
|
||||
self.clearButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Clear'))
|
||||
self.clearButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Clear edit area'))
|
||||
self.splitButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Split Slide'))
|
||||
self.splitButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
|
||||
'by inserting a slide splitter.'))
|
||||
'slide.'))
|
||||
self.themeLabel.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'The&me:'))
|
||||
self.creditLabel.setText(
|
||||
|
@ -32,6 +32,7 @@ from openlp.core.lib import Receiver, translate
|
||||
from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser
|
||||
from openlp.plugins.custom.lib.db import CustomSlide
|
||||
from editcustomdialog import Ui_CustomEditDialog
|
||||
from editcustomslideform import EditCustomSlideForm
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -40,7 +41,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
Class documentation goes here.
|
||||
"""
|
||||
log.info(u'Custom Editor loaded')
|
||||
def __init__(self, custommanager, parent = None):
|
||||
def __init__(self, custommanager, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
@ -61,28 +62,20 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
QtCore.SIGNAL(u'pressed()'), self.onEditButtonPressed)
|
||||
QtCore.QObject.connect(self.editAllButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onEditAllButtonPressed)
|
||||
QtCore.QObject.connect(self.saveButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onSaveButtonPressed)
|
||||
QtCore.QObject.connect(self.deleteButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onDeleteButtonPressed)
|
||||
QtCore.QObject.connect(self.clearButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onClearButtonPressed)
|
||||
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.splitButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onSplitButtonPressed)
|
||||
QtCore.QObject.connect(self.verseListView,
|
||||
QtCore.SIGNAL(u'itemDoubleClicked(QListWidgetItem*)'),
|
||||
self.onVerseListViewSelected)
|
||||
QtCore.QObject.connect(self.verseListView,
|
||||
QtCore.QObject.connect(self.slideListView,
|
||||
QtCore.SIGNAL(u'itemClicked(QListWidgetItem*)'),
|
||||
self.onVerseListViewPressed)
|
||||
self.onSlideListViewPressed)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
|
||||
# Create other objects and forms
|
||||
# Create other objects and forms.
|
||||
self.custommanager = custommanager
|
||||
self.editSlideForm = EditCustomSlideForm(self)
|
||||
self.initialise()
|
||||
|
||||
def onPreview(self, button):
|
||||
@ -92,21 +85,15 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
Receiver.send_message(u'custom_preview')
|
||||
|
||||
def initialise(self):
|
||||
self.editAll = False
|
||||
self.addButton.setEnabled(True)
|
||||
self.deleteButton.setEnabled(False)
|
||||
self.editButton.setEnabled(False)
|
||||
self.editAllButton.setEnabled(True)
|
||||
self.saveButton.setEnabled(False)
|
||||
self.clearButton.setEnabled(False)
|
||||
self.splitButton.setEnabled(False)
|
||||
self.titleEdit.setText(u'')
|
||||
self.creditEdit.setText(u'')
|
||||
self.verseTextEdit.clear()
|
||||
self.verseListView.clear()
|
||||
#make sure we have a new item
|
||||
self.slideListView.clear()
|
||||
# Make sure we have a new item.
|
||||
self.customSlide = CustomSlide()
|
||||
self.themeComboBox.addItem(u'')
|
||||
|
||||
def loadThemes(self, themelist):
|
||||
self.themeComboBox.clear()
|
||||
@ -115,6 +102,16 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
self.themeComboBox.addItem(themename)
|
||||
|
||||
def loadCustom(self, id, preview=False):
|
||||
"""
|
||||
Called when editing or creating a new custom.
|
||||
|
||||
``id``
|
||||
The cutom's id. If zero, then a new custom is created.
|
||||
|
||||
``preview``
|
||||
States whether the custom is edited while being previewed in the
|
||||
preview panel.
|
||||
"""
|
||||
self.customSlide = CustomSlide()
|
||||
self.initialise()
|
||||
if id != 0:
|
||||
@ -122,9 +119,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
self.titleEdit.setText(self.customSlide.title)
|
||||
self.creditEdit.setText(self.customSlide.credits)
|
||||
customXML = CustomXMLParser(self.customSlide.text)
|
||||
verseList = customXML.get_verses()
|
||||
for verse in verseList:
|
||||
self.verseListView.addItem(verse[1])
|
||||
slideList = customXML.get_verses()
|
||||
for slide in slideList:
|
||||
self.slideListView.addItem(slide[1])
|
||||
theme = self.customSlide.theme_name
|
||||
id = self.themeComboBox.findText(theme, QtCore.Qt.MatchExactly)
|
||||
if id == -1:
|
||||
@ -132,7 +129,8 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
self.themeComboBox.setCurrentIndex(id)
|
||||
else:
|
||||
self.themeComboBox.setCurrentIndex(0)
|
||||
#if not preview hide the preview button
|
||||
self.editAllButton.setEnabled(False)
|
||||
# If not preview hide the preview button.
|
||||
self.previewButton.setVisible(False)
|
||||
if preview:
|
||||
self.previewButton.setVisible(True)
|
||||
@ -148,6 +146,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
self.close()
|
||||
|
||||
def saveCustom(self):
|
||||
"""
|
||||
Saves the custom.
|
||||
"""
|
||||
valid, message = self._validate()
|
||||
if not valid:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
@ -157,9 +158,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
sxml.new_document()
|
||||
sxml.add_lyrics_to_song()
|
||||
count = 1
|
||||
for i in range(0, self.verseListView.count()):
|
||||
for i in range(0, self.slideListView.count()):
|
||||
sxml.add_verse_to_lyrics(u'custom', unicode(count),
|
||||
unicode(self.verseListView.item(i).text()))
|
||||
unicode(self.slideListView.item(i).text()))
|
||||
count += 1
|
||||
self.customSlide.title = unicode(self.titleEdit.displayText(), u'utf-8')
|
||||
self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8')
|
||||
@ -170,114 +171,103 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
return self.custommanager.save_object(self.customSlide)
|
||||
|
||||
def onUpButtonPressed(self):
|
||||
selectedRow = self.verseListView.currentRow()
|
||||
selectedRow = self.slideListView.currentRow()
|
||||
if selectedRow != 0:
|
||||
qw = self.verseListView.takeItem(selectedRow)
|
||||
self.verseListView.insertItem(selectedRow - 1, qw)
|
||||
self.verseListView.setCurrentRow(selectedRow - 1)
|
||||
qw = self.slideListView.takeItem(selectedRow)
|
||||
self.slideListView.insertItem(selectedRow - 1, qw)
|
||||
self.slideListView.setCurrentRow(selectedRow - 1)
|
||||
|
||||
def onDownButtonPressed(self):
|
||||
selectedRow = self.verseListView.currentRow()
|
||||
selectedRow = self.slideListView.currentRow()
|
||||
# zero base arrays
|
||||
if selectedRow != self.verseListView.count() - 1:
|
||||
qw = self.verseListView.takeItem(selectedRow)
|
||||
self.verseListView.insertItem(selectedRow + 1, qw)
|
||||
self.verseListView.setCurrentRow(selectedRow + 1)
|
||||
if selectedRow != self.slideListView.count() - 1:
|
||||
qw = self.slideListView.takeItem(selectedRow)
|
||||
self.slideListView.insertItem(selectedRow + 1, qw)
|
||||
self.slideListView.setCurrentRow(selectedRow + 1)
|
||||
|
||||
def onClearButtonPressed(self):
|
||||
self.verseTextEdit.clear()
|
||||
self.editAll = False
|
||||
self.addButton.setEnabled(True)
|
||||
self.editAllButton.setEnabled(True)
|
||||
self.saveButton.setEnabled(False)
|
||||
|
||||
def onVerseListViewPressed(self, item):
|
||||
def onSlideListViewPressed(self, item):
|
||||
self.deleteButton.setEnabled(True)
|
||||
self.editButton.setEnabled(True)
|
||||
|
||||
def onVerseListViewSelected(self, item):
|
||||
self.editText(item.text())
|
||||
|
||||
def onAddButtonPressed(self):
|
||||
self.verseListView.addItem(self.verseTextEdit.toPlainText())
|
||||
self.deleteButton.setEnabled(False)
|
||||
self.verseTextEdit.clear()
|
||||
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.editText(self.verseListView.currentItem().text())
|
||||
self.editSlideForm.setText(self.slideListView.currentItem().text())
|
||||
if self.editSlideForm.exec_():
|
||||
self.updateSlideList(self.editSlideForm.getText())
|
||||
|
||||
def onEditAllButtonPressed(self):
|
||||
self.editAll = True
|
||||
self.addButton.setEnabled(False)
|
||||
self.splitButton.setEnabled(True)
|
||||
if self.verseListView.count() > 0:
|
||||
verse_list = u''
|
||||
for row in range(0, self.verseListView.count()):
|
||||
item = self.verseListView.item(row)
|
||||
verse_list += item.text()
|
||||
if row != self.verseListView.count() - 1:
|
||||
verse_list += u'\n[---]\n'
|
||||
self.editText(verse_list)
|
||||
"""
|
||||
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)
|
||||
|
||||
def editText(self, text):
|
||||
self.beforeText = text
|
||||
self.verseTextEdit.setPlainText(text)
|
||||
self.deleteButton.setEnabled(False)
|
||||
self.editButton.setEnabled(False)
|
||||
self.editAllButton.setEnabled(False)
|
||||
self.saveButton.setEnabled(True)
|
||||
self.clearButton.setEnabled(True)
|
||||
def updateSlideList(self, slides, edit_all=False):
|
||||
"""
|
||||
Updates the slide list after editing slides.
|
||||
|
||||
def onSaveButtonPressed(self):
|
||||
if self.editAll:
|
||||
self.verseListView.clear()
|
||||
for row in unicode(self.verseTextEdit.toPlainText()).split(
|
||||
u'\n[---]\n'):
|
||||
self.verseListView.addItem(row)
|
||||
``slides``
|
||||
A list of all slides which have been edited.
|
||||
|
||||
``edit_all``
|
||||
Indicates if all slides or only one slide has been edited.
|
||||
"""
|
||||
if len(slides) == 1:
|
||||
self.slideListView.currentItem().setText(slides[0])
|
||||
else:
|
||||
self.verseListView.currentItem().setText(
|
||||
self.verseTextEdit.toPlainText())
|
||||
#number of lines has change
|
||||
if len(self.beforeText.split(u'\n')) != \
|
||||
len(self.verseTextEdit.toPlainText().split(u'\n')):
|
||||
tempList = {}
|
||||
for row in range(0, self.verseListView.count()):
|
||||
tempList[row] = self.verseListView.item(row).text()
|
||||
self.verseListView.clear()
|
||||
for row in range (0, len(tempList)):
|
||||
self.verseListView.addItem(tempList[row])
|
||||
self.verseListView.repaint()
|
||||
self.addButton.setEnabled(True)
|
||||
self.saveButton.setEnabled(False)
|
||||
self.editButton.setEnabled(False)
|
||||
self.editAllButton.setEnabled(True)
|
||||
self.splitButton.setEnabled(False)
|
||||
self.verseTextEdit.clear()
|
||||
|
||||
def onSplitButtonPressed(self):
|
||||
if self.verseTextEdit.textCursor().columnNumber() != 0:
|
||||
self.verseTextEdit.insertPlainText(u'\n')
|
||||
self.verseTextEdit.insertPlainText(u'[---]\n' )
|
||||
self.verseTextEdit.setFocus()
|
||||
if edit_all:
|
||||
self.slideListView.clear()
|
||||
for slide in slides:
|
||||
self.slideListView.addItem(slide)
|
||||
else:
|
||||
old_slides = []
|
||||
old_row = self.slideListView.currentRow()
|
||||
# Create a list with all (old/unedited) slides.
|
||||
old_slides = [self.slideListView.item(row).text() for row in \
|
||||
range(0, self.slideListView.count())]
|
||||
self.slideListView.clear()
|
||||
old_slides.pop(old_row)
|
||||
# Insert all slides to make the old_slides list complete.
|
||||
for slide in slides:
|
||||
old_slides.insert(old_row, slide)
|
||||
for slide in old_slides:
|
||||
self.slideListView.addItem(slide)
|
||||
self.slideListView.repaint()
|
||||
|
||||
def onDeleteButtonPressed(self):
|
||||
self.verseListView.takeItem(self.verseListView.currentRow())
|
||||
self.editButton.setEnabled(False)
|
||||
self.slideListView.takeItem(self.slideListView.currentRow())
|
||||
self.editButton.setEnabled(True)
|
||||
self.editAllButton.setEnabled(True)
|
||||
if self.slideListView.count() == 0:
|
||||
self.deleteButton.setEnabled(False)
|
||||
self.editButton.setEnabled(False)
|
||||
self.editAllButton.setEnabled(False)
|
||||
|
||||
def _validate(self):
|
||||
"""
|
||||
Checks whether a custom is valid or not.
|
||||
"""
|
||||
# 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.')
|
||||
# must have 1 slide
|
||||
if self.verseListView.count() == 0:
|
||||
self.verseTextEdit.setFocus()
|
||||
# We must have one slide.
|
||||
if self.slideListView.count() == 0:
|
||||
return False, translate('CustomPlugin.EditCustomForm',
|
||||
'You need to add at least one slide')
|
||||
if self.verseTextEdit.toPlainText():
|
||||
self.verseTextEdit.setFocus()
|
||||
return False, translate('CustomPlugin.EditCustomForm',
|
||||
'You have one or more unsaved slides, please either save your '
|
||||
'slide(s) or clear your changes.')
|
||||
return True, u''
|
||||
|
59
openlp/plugins/custom/forms/editcustomslidedialog.py
Normal file
59
openlp/plugins/custom/forms/editcustomslidedialog.py
Normal file
@ -0,0 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
||||
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
||||
# Carsten Tinggaard, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import translate, SpellTextEdit
|
||||
|
||||
class Ui_CustomSlideEditDialog(object):
|
||||
def setupUi(self, customSlideEditDialog):
|
||||
customSlideEditDialog.setObjectName(u'customSlideEditDialog')
|
||||
customSlideEditDialog.resize(474, 442)
|
||||
self.buttonBox = QtGui.QDialogButtonBox(customSlideEditDialog)
|
||||
self.buttonBox.setGeometry(QtCore.QRect(8, 407, 458, 32))
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
|
||||
QtGui.QDialogButtonBox.Save)
|
||||
self.buttonBox.setObjectName(u'buttonBox')
|
||||
self.slideTextEdit = SpellTextEdit(self)
|
||||
self.slideTextEdit.setGeometry(QtCore.QRect(8, 8, 458, 349))
|
||||
self.slideTextEdit.setObjectName(u'slideTextEdit')
|
||||
self.splitButton = QtGui.QPushButton(customSlideEditDialog)
|
||||
self.splitButton.setGeometry(QtCore.QRect(380, 370, 85, 27))
|
||||
self.splitButton.setObjectName(u'splitButton')
|
||||
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):
|
||||
self.splitButton.setText(
|
||||
translate('CustomPlugin.EditCustomForm', 'Split Slide'))
|
||||
self.splitButton.setToolTip(
|
||||
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
|
||||
'by inserting a slide splitter.'))
|
76
openlp/plugins/custom/forms/editcustomslideform.py
Normal file
76
openlp/plugins/custom/forms/editcustomslideform.py
Normal file
@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
||||
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
||||
# Carsten Tinggaard, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Receiver, translate
|
||||
from editcustomslidedialog import Ui_CustomSlideEditDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
|
||||
"""
|
||||
Class documentation goes here.
|
||||
"""
|
||||
log.info(u'Custom Verse Editor loaded')
|
||||
def __init__(self, parent=None):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setupUi(self)
|
||||
# Connecting signals and slots
|
||||
QtCore.QObject.connect(self.splitButton,
|
||||
QtCore.SIGNAL(u'pressed()'), self.onSplitButtonPressed)
|
||||
|
||||
def setText(self, text):
|
||||
"""
|
||||
Set the text for slideTextEdit.
|
||||
|
||||
``text``
|
||||
The text (unicode).
|
||||
"""
|
||||
self.slideTextEdit.clear()
|
||||
if text:
|
||||
self.slideTextEdit.setPlainText(text)
|
||||
self.slideTextEdit.setFocus()
|
||||
|
||||
def getText(self):
|
||||
"""
|
||||
Returns a list with all slides.
|
||||
"""
|
||||
return self.slideTextEdit.toPlainText().split(u'\n[---]\n')
|
||||
|
||||
def onSplitButtonPressed(self):
|
||||
"""
|
||||
Splits a slide in two slides.
|
||||
"""
|
||||
if self.slideTextEdit.textCursor().columnNumber() != 0:
|
||||
self.slideTextEdit.insertPlainText(u'\n')
|
||||
self.slideTextEdit.insertPlainText(u'[---]\n' )
|
||||
self.slideTextEdit.setFocus()
|
@ -32,12 +32,11 @@ class CustomTab(SettingsTab):
|
||||
"""
|
||||
CustomTab is the Custom 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'CustomTab')
|
||||
self.tabTitleVisible = translate('CustomPlugin.CustomTab', 'Custom')
|
||||
self.customLayout = QtGui.QFormLayout(self)
|
||||
self.customLayout.setSpacing(8)
|
||||
self.customLayout.setMargin(8)
|
||||
|
@ -46,14 +46,12 @@ class CustomMediaItem(MediaManagerItem):
|
||||
"""
|
||||
log.info(u'Custom Media Item loaded')
|
||||
|
||||
def __init__(self, parent, icon, title):
|
||||
self.PluginNameShort = u'Custom'
|
||||
self.pluginNameVisible = translate('CustomPlugin.MediaItem', 'Custom')
|
||||
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, icon, title)
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
self.singleServiceItem = False
|
||||
# Holds information about whether the edit is remotly triggered and
|
||||
# which Custom is required.
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.plugins.images.lib import ImageMediaItem
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -42,7 +42,7 @@ class ImagePlugin(Plugin):
|
||||
|
||||
def getMediaManagerItem(self):
|
||||
# Create the MediaManagerItem object
|
||||
return ImageMediaItem(self, self.icon, self.name)
|
||||
return ImageMediaItem(self, self, self.icon)
|
||||
|
||||
def about(self):
|
||||
about_text = translate('ImagePlugin', '<strong>Image Plugin</strong>'
|
||||
@ -57,3 +57,60 @@ class ImagePlugin(Plugin):
|
||||
'selected image as a background instead of the background '
|
||||
'provided by the theme.')
|
||||
return about_text
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('ImagePlugin', 'Image'),
|
||||
u'plural': translate('ImagePlugin', 'Images')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('ImagePlugin', 'Images')
|
||||
}
|
||||
# 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',
|
||||
'Add the selected Image to the service')
|
||||
}
|
@ -49,14 +49,12 @@ class ImageMediaItem(MediaManagerItem):
|
||||
"""
|
||||
log.info(u'Image Media Item loaded')
|
||||
|
||||
def __init__(self, parent, icon, title):
|
||||
self.PluginNameShort = u'Image'
|
||||
self.pluginNameVisible = translate('ImagePlugin.MediaItem', 'Image')
|
||||
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, icon, title)
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.OnNewPrompt = translate('ImagePlugin.MediaItem',
|
||||
|
@ -25,5 +25,6 @@
|
||||
###############################################################################
|
||||
|
||||
from mediaitem import MediaMediaItem
|
||||
from mediatab import MediaTab
|
||||
|
||||
__all__ = ['MediaMediaItem']
|
||||
|
@ -46,9 +46,7 @@ class MediaMediaItem(MediaManagerItem):
|
||||
"""
|
||||
log.info(u'%s MediaMediaItem loaded', __name__)
|
||||
|
||||
def __init__(self, parent, icon, title):
|
||||
self.PluginNameShort = u'Media'
|
||||
self.pluginNameVisible = translate('MediaPlugin.MediaItem', 'Media')
|
||||
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
|
||||
@ -56,7 +54,7 @@ class MediaMediaItem(MediaManagerItem):
|
||||
self.ListViewWithDnD_class = MediaListView
|
||||
self.PreviewFunction = QtGui.QPixmap(
|
||||
u':/media/media_video.png').toImage()
|
||||
MediaManagerItem.__init__(self, parent, icon, title)
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
self.singleServiceItem = False
|
||||
self.serviceItemIconName = u':/media/media_video.png'
|
||||
|
||||
@ -115,7 +113,7 @@ class MediaMediaItem(MediaManagerItem):
|
||||
'You must select a media file to replace the background with.')):
|
||||
item = self.listView.currentItem()
|
||||
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
|
||||
self.parent.liveController.display.video(filename, 0)
|
||||
self.parent.liveController.display.video(filename, 0, True)
|
||||
self.resetButton.setVisible(True)
|
||||
|
||||
def generateSlideData(self, service_item, item=None):
|
||||
|
84
openlp/plugins/media/lib/mediatab.py
Normal file
84
openlp/plugins/media/lib/mediatab.py
Normal file
@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
||||
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
||||
# Carsten Tinggaard, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import SettingsTab, translate, Receiver
|
||||
|
||||
class MediaTab(SettingsTab):
|
||||
"""
|
||||
MediaTab is the Media settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, title):
|
||||
SettingsTab.__init__(self, title)
|
||||
|
||||
def setupUi(self):
|
||||
self.setObjectName(u'MediaTab')
|
||||
self.tabTitleVisible = translate('MediaPlugin.MediaTab', 'Media')
|
||||
self.mediaLayout = QtGui.QFormLayout(self)
|
||||
self.mediaLayout.setSpacing(8)
|
||||
self.mediaLayout.setMargin(8)
|
||||
self.mediaLayout.setObjectName(u'mediaLayout')
|
||||
self.mediaModeGroupBox = QtGui.QGroupBox(self)
|
||||
self.mediaModeGroupBox.setObjectName(u'mediaModeGroupBox')
|
||||
self.mediaModeLayout = QtGui.QVBoxLayout(self.mediaModeGroupBox)
|
||||
self.mediaModeLayout.setSpacing(8)
|
||||
self.mediaModeLayout.setMargin(8)
|
||||
self.mediaModeLayout.setObjectName(u'mediaModeLayout')
|
||||
self.usePhononCheckBox = QtGui.QCheckBox(self.mediaModeGroupBox)
|
||||
self.usePhononCheckBox.setObjectName(u'usePhononCheckBox')
|
||||
self.mediaModeLayout.addWidget(self.usePhononCheckBox)
|
||||
self.mediaLayout.setWidget(
|
||||
0, QtGui.QFormLayout.LabelRole, self.mediaModeGroupBox)
|
||||
QtCore.QObject.connect(self.usePhononCheckBox,
|
||||
QtCore.SIGNAL(u'stateChanged(int)'),
|
||||
self.onUsePhononCheckBoxChanged)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.mediaModeGroupBox.setTitle(translate('MediaPlugin.MediaTab',
|
||||
'Media Display'))
|
||||
self.usePhononCheckBox.setText(
|
||||
translate('MediaPlugin.MediaTab', 'Use Phonon for video playback'))
|
||||
|
||||
def onUsePhononCheckBoxChanged(self, check_state):
|
||||
self.usePhonon = (check_state == QtCore.Qt.Checked)
|
||||
self.usePhononChanged = True
|
||||
|
||||
def load(self):
|
||||
self.usePhonon = QtCore.QSettings().value(
|
||||
self.settingsSection + u'/use phonon',
|
||||
QtCore.QVariant(True)).toBool()
|
||||
self.usePhononCheckBox.setChecked(self.usePhonon)
|
||||
|
||||
def save(self):
|
||||
oldUsePhonon = QtCore.QSettings().value(
|
||||
u'media/use phonon', QtCore.QVariant(True)).toBool()
|
||||
if oldUsePhonon != self.usePhonon:
|
||||
QtCore.QSettings().setValue(self.settingsSection + u'/use phonon',
|
||||
QtCore.QVariant(self.usePhonon))
|
||||
Receiver.send_message(u'config_screen_changed')
|
||||
|
||||
|
@ -28,8 +28,8 @@ import logging
|
||||
|
||||
from PyQt4.phonon import Phonon
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.plugins.media.lib import MediaMediaItem
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.plugins.media.lib import MediaMediaItem, MediaTab
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -68,11 +68,71 @@ class MediaPlugin(Plugin):
|
||||
type = u''
|
||||
return list, type
|
||||
|
||||
def getSettingsTab(self):
|
||||
return MediaTab(self.name)
|
||||
|
||||
def getMediaManagerItem(self):
|
||||
# Create the MediaManagerItem object
|
||||
return MediaMediaItem(self, self.icon, self.name)
|
||||
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.')
|
||||
return about_text
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('MediaPlugin', 'Media'),
|
||||
u'plural': translate('MediaPlugin', 'Media')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('MediaPlugin', 'Media')
|
||||
}
|
||||
# Middle Header Bar
|
||||
## Load Button ##
|
||||
self.textStrings[StringContent.Load] = {
|
||||
u'title': translate('MediaPlugin', 'Load'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Load a new Media')
|
||||
}
|
||||
## New Button ##
|
||||
self.textStrings[StringContent.New] = {
|
||||
u'title': translate('MediaPlugin', 'Add'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Add a new Media')
|
||||
}
|
||||
## Edit Button ##
|
||||
self.textStrings[StringContent.Edit] = {
|
||||
u'title': translate('MediaPlugin', 'Edit'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Edit the selected Media')
|
||||
}
|
||||
## Delete Button ##
|
||||
self.textStrings[StringContent.Delete] = {
|
||||
u'title': translate('MediaPlugin', 'Delete'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Delete the selected Media')
|
||||
}
|
||||
## Preview ##
|
||||
self.textStrings[StringContent.Preview] = {
|
||||
u'title': translate('MediaPlugin', 'Preview'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Preview the selected Media')
|
||||
}
|
||||
## Live Button ##
|
||||
self.textStrings[StringContent.Live] = {
|
||||
u'title': translate('MediaPlugin', 'Live'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Send the selected Media live')
|
||||
}
|
||||
## Add to service Button ##
|
||||
self.textStrings[StringContent.Service] = {
|
||||
u'title': translate('MediaPlugin', 'Service'),
|
||||
u'tooltip': translate('MediaPlugin',
|
||||
'Add the selected Media to the service')
|
||||
}
|
||||
|
@ -58,15 +58,12 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
Constructor. Setup defaults
|
||||
"""
|
||||
self.controllers = controllers
|
||||
self.PluginNameShort = u'Presentation'
|
||||
self.pluginNameVisible = translate('PresentationPlugin.MediaItem',
|
||||
'Presentation')
|
||||
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, icon, title)
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
self.message_listener = MessageListener(self)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'mediaitem_presentation_rebuild'), self.rebuild)
|
||||
|
@ -125,7 +125,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
Opens the PowerPoint file using the process created earlier
|
||||
|
||||
``presentation``
|
||||
The file name of the presentations to run.
|
||||
The file name of the presentations to run.
|
||||
"""
|
||||
log.debug(u'LoadPresentation')
|
||||
if not self.controller.process or not self.controller.process.Visible:
|
||||
@ -143,11 +143,14 @@ class PowerpointDocument(PresentationDocument):
|
||||
def create_thumbnails(self):
|
||||
"""
|
||||
Create the thumbnail images for the current presentation.
|
||||
Note an alternative and quicker method would be do
|
||||
|
||||
Note an alternative and quicker method would be do::
|
||||
|
||||
self.presentation.Slides[n].Copy()
|
||||
thumbnail = QApplication.clipboard.image()
|
||||
But for now we want a physical file since it makes
|
||||
life easier elsewhere
|
||||
|
||||
However, for the moment, we want a physical file since it makes life
|
||||
easier elsewhere.
|
||||
"""
|
||||
if self.check_thumbnails():
|
||||
return
|
||||
@ -156,9 +159,8 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def close_presentation(self):
|
||||
"""
|
||||
Close presentation and clean up objects
|
||||
Triggerent by new object being added to SlideController orOpenLP
|
||||
being shut down
|
||||
Close presentation and clean up objects. This is triggered by a new
|
||||
object being added to SlideController or OpenLP being shut down.
|
||||
"""
|
||||
log.debug(u'ClosePresentation')
|
||||
if self.presentation:
|
||||
@ -171,7 +173,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def is_loaded(self):
|
||||
"""
|
||||
Returns true if a presentation is loaded
|
||||
Returns ``True`` if a presentation is loaded.
|
||||
"""
|
||||
try:
|
||||
if not self.controller.process.Visible:
|
||||
@ -187,7 +189,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def is_active(self):
|
||||
"""
|
||||
Returns true if a presentation is currently active
|
||||
Returns ``True`` if a presentation is currently active.
|
||||
"""
|
||||
if not self.is_loaded():
|
||||
return False
|
||||
@ -202,7 +204,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def unblank_screen(self):
|
||||
"""
|
||||
Unblanks (restores) the presentationn
|
||||
Unblanks (restores) the presentation.
|
||||
"""
|
||||
self.presentation.SlideShowSettings.Run()
|
||||
self.presentation.SlideShowWindow.View.State = 1
|
||||
@ -210,13 +212,13 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def blank_screen(self):
|
||||
"""
|
||||
Blanks the screen
|
||||
Blanks the screen.
|
||||
"""
|
||||
self.presentation.SlideShowWindow.View.State = 3
|
||||
|
||||
def is_blank(self):
|
||||
"""
|
||||
Returns true if screen is blank
|
||||
Returns ``True`` if screen is blank.
|
||||
"""
|
||||
if self.is_active():
|
||||
return self.presentation.SlideShowWindow.View.State == 3
|
||||
@ -225,14 +227,14 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def stop_presentation(self):
|
||||
"""
|
||||
Stops the current presentation and hides the output
|
||||
Stops the current presentation and hides the output.
|
||||
"""
|
||||
self.presentation.SlideShowWindow.View.Exit()
|
||||
|
||||
if os.name == u'nt':
|
||||
def start_presentation(self):
|
||||
"""
|
||||
Starts a presentation from the beginning
|
||||
Starts a presentation from the beginning.
|
||||
"""
|
||||
#SlideShowWindow measures its size/position by points, not pixels
|
||||
try:
|
||||
@ -254,40 +256,40 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def get_slide_number(self):
|
||||
"""
|
||||
Returns the current slide number
|
||||
Returns the current slide number.
|
||||
"""
|
||||
return self.presentation.SlideShowWindow.View.CurrentShowPosition
|
||||
|
||||
def get_slide_count(self):
|
||||
"""
|
||||
Returns total number of slides
|
||||
Returns total number of slides.
|
||||
"""
|
||||
return self.presentation.Slides.Count
|
||||
|
||||
def goto_slide(self, slideno):
|
||||
"""
|
||||
Moves to a specific slide in the presentation
|
||||
Moves to a specific slide in the presentation.
|
||||
"""
|
||||
self.presentation.SlideShowWindow.View.GotoSlide(slideno)
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
Triggers the next effect of slide on the running presentation
|
||||
Triggers the next effect of slide on the running presentation.
|
||||
"""
|
||||
self.presentation.SlideShowWindow.View.Next()
|
||||
|
||||
def previous_step(self):
|
||||
"""
|
||||
Triggers the previous slide on the running presentation
|
||||
Triggers the previous slide on the running presentation.
|
||||
"""
|
||||
self.presentation.SlideShowWindow.View.Previous()
|
||||
|
||||
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.
|
||||
"""
|
||||
text = ''
|
||||
shapes = self.presentation.Slides(slide_no).Shapes
|
||||
@ -299,10 +301,10 @@ class PowerpointDocument(PresentationDocument):
|
||||
|
||||
def get_slide_notes(self, slide_no):
|
||||
"""
|
||||
Returns the text on the slide
|
||||
Returns the text on the slide.
|
||||
|
||||
``slide_no``
|
||||
The slide the notes are required for, starting at 1
|
||||
The slide the notes are required for, starting at 1.
|
||||
"""
|
||||
text = ''
|
||||
shapes = self.presentation.Slides(slide_no).NotesPage.Shapes
|
||||
|
@ -37,16 +37,21 @@ log = logging.getLogger(__name__)
|
||||
|
||||
class PresentationController(object):
|
||||
"""
|
||||
Base class for presentation controllers to inherit from
|
||||
Class to control interactions with presentations.
|
||||
It creates the runtime environment
|
||||
To create a new controller, take a copy of this file and name it
|
||||
so it ends in controller.py, i.e. foobarcontroller.py
|
||||
Make sure it inherits PresentationController
|
||||
Then fill in the blanks. If possible try and make sure it loads
|
||||
on all platforms, using for example os.name checks, although
|
||||
__init__, check_available and presentation_deleted should always work.
|
||||
See impresscontroller, powerpointcontroller or pptviewcontroller
|
||||
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**
|
||||
|
@ -32,20 +32,18 @@ class PresentationTab(SettingsTab):
|
||||
"""
|
||||
PresentationsTab is the Presentations settings tab in the settings dialog.
|
||||
"""
|
||||
def __init__(self, title, controllers):
|
||||
def __init__(self, title, visible_title, controllers):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
self.controllers = controllers
|
||||
SettingsTab.__init__(self, title)
|
||||
SettingsTab.__init__(self, title, visible_title)
|
||||
|
||||
def setupUi(self):
|
||||
"""
|
||||
Create the controls for the settings tab
|
||||
"""
|
||||
self.setObjectName(u'PresentationTab')
|
||||
self.tabTitleVisible = translate('PresentationPlugin.PresentationTab',
|
||||
'Presentations')
|
||||
self.PresentationLayout = QtGui.QHBoxLayout(self)
|
||||
self.PresentationLayout.setSpacing(8)
|
||||
self.PresentationLayout.setMargin(8)
|
||||
|
@ -30,7 +30,7 @@ presentations from a variety of document formats.
|
||||
import os
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.utils import AppLocation
|
||||
from openlp.plugins.presentations.lib import PresentationController, \
|
||||
PresentationMediaItem, PresentationTab
|
||||
@ -60,7 +60,8 @@ class PresentationPlugin(Plugin):
|
||||
"""
|
||||
Create the settings Tab
|
||||
"""
|
||||
return PresentationTab(self.name, self.controllers)
|
||||
visible_name = self.getString(StringContent.VisibleName)
|
||||
return PresentationTab(self.name, visible_name[u'title'], self.controllers)
|
||||
|
||||
def initialise(self):
|
||||
"""
|
||||
@ -143,3 +144,48 @@ class PresentationPlugin(Plugin):
|
||||
'programs. The choice of available presentation programs is '
|
||||
'available to the user in a drop down box.')
|
||||
return about_text
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('PresentationPlugin', 'Presentation'),
|
||||
u'plural': translate('PresentationPlugin', 'Presentations')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('PresentationPlugin', 'Presentations')
|
||||
}
|
||||
# Middle Header Bar
|
||||
## Load Button ##
|
||||
self.textStrings[StringContent.Load] = {
|
||||
u'title': translate('PresentationPlugin', 'Load'),
|
||||
u'tooltip': translate('PresentationPlugin',
|
||||
'Load a new Presentation')
|
||||
}
|
||||
## Delete Button ##
|
||||
self.textStrings[StringContent.Delete] = {
|
||||
u'title': translate('PresentationPlugin', 'Delete'),
|
||||
u'tooltip': translate('PresentationPlugin',
|
||||
'Delete the selected Presentation')
|
||||
}
|
||||
## Preview ##
|
||||
self.textStrings[StringContent.Preview] = {
|
||||
u'title': translate('PresentationPlugin', 'Preview'),
|
||||
u'tooltip': translate('PresentationPlugin',
|
||||
'Preview the selected Presentation')
|
||||
}
|
||||
## Live Button ##
|
||||
self.textStrings[StringContent.Live] = {
|
||||
u'title': translate('PresentationPlugin', 'Live'),
|
||||
u'tooltip': translate('PresentationPlugin',
|
||||
'Send the selected Presentation live')
|
||||
}
|
||||
## Add to service Button ##
|
||||
self.textStrings[StringContent.Service] = {
|
||||
u'title': translate('PresentationPlugin', 'Service'),
|
||||
u'tooltip': translate('PresentationPlugin',
|
||||
'Add the selected Presentation to the service')
|
||||
}
|
@ -32,12 +32,11 @@ class RemoteTab(SettingsTab):
|
||||
"""
|
||||
RemoteTab is the Remotes 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'RemoteTab')
|
||||
self.tabTitleVisible = translate('RemotePlugin.RemoteTab', 'Remotes')
|
||||
self.remoteLayout = QtGui.QFormLayout(self)
|
||||
self.remoteLayout.setSpacing(8)
|
||||
self.remoteLayout.setMargin(8)
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import Plugin, translate, build_icon
|
||||
from openlp.core.lib import Plugin, StringContent, translate, build_icon
|
||||
from openlp.plugins.remotes.lib import RemoteTab, HttpServer
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -65,7 +65,8 @@ class RemotesPlugin(Plugin):
|
||||
"""
|
||||
Create the settings Tab
|
||||
"""
|
||||
return RemoteTab(self.name)
|
||||
visible_name = self.getString(StringContent.VisibleName)
|
||||
return RemoteTab(self.name, visible_name[u'title'])
|
||||
|
||||
def about(self):
|
||||
"""
|
||||
@ -76,3 +77,17 @@ class RemotesPlugin(Plugin):
|
||||
'a running version of OpenLP on a different computer via a web '
|
||||
'browser or through the remote API.')
|
||||
return about_text
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('RemotePlugin', 'Remote'),
|
||||
u'plural': translate('RemotePlugin', 'Remotes')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('RemotePlugin', 'Remotes')
|
||||
}
|
@ -483,6 +483,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.VerseListWidget.resizeRowsToContents()
|
||||
self.VerseListWidget.repaint()
|
||||
self.tagRows()
|
||||
self.VerseEditButton.setEnabled(False)
|
||||
self.VerseDeleteButton.setEnabled(False)
|
||||
|
||||
def onVerseDeleteButtonClicked(self):
|
||||
self.VerseListWidget.removeRow(self.VerseListWidget.currentRow())
|
||||
|
@ -53,6 +53,9 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
||||
QtCore.QObject.connect(self.verseTextEdit,
|
||||
QtCore.SIGNAL(u'cursorPositionChanged()'),
|
||||
self.onCursorPositionChanged)
|
||||
QtCore.QObject.connect(self.verseTypeComboBox,
|
||||
QtCore.SIGNAL(u'currentIndexChanged(int)'),
|
||||
self.onVerseTypeComboBoxChanged)
|
||||
self.verse_regex = re.compile(r'---\[([-\w]+):([\d]+)\]---')
|
||||
|
||||
def contextMenu(self, point):
|
||||
@ -66,27 +69,43 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
|
||||
self.verseTextEdit.setFocus()
|
||||
|
||||
def onInsertButtonClicked(self):
|
||||
if self.verseTextEdit.textCursor().columnNumber() != 0:
|
||||
self.verseTextEdit.insertPlainText(u'\n')
|
||||
verse_type = self.verseTypeComboBox.currentIndex()
|
||||
if verse_type == VerseType.Verse:
|
||||
self.insertVerse(VerseType.to_string(VerseType.Verse),
|
||||
if VerseType.to_string(verse_type) is not None:
|
||||
self.insertVerse(VerseType.to_string(verse_type),
|
||||
self.verseNumberBox.value())
|
||||
elif verse_type == VerseType.Chorus:
|
||||
self.insertVerse(VerseType.to_string(VerseType.Chorus),
|
||||
self.verseNumberBox.value())
|
||||
elif verse_type == VerseType.Bridge:
|
||||
self.insertVerse(VerseType.to_string(VerseType.Bridge))
|
||||
elif verse_type == VerseType.PreChorus:
|
||||
self.insertVerse(VerseType.to_string(VerseType.PreChorus))
|
||||
elif verse_type == VerseType.Intro:
|
||||
self.insertVerse(VerseType.to_string(VerseType.Intro))
|
||||
elif verse_type == VerseType.Ending:
|
||||
self.insertVerse(VerseType.to_string(VerseType.Ending))
|
||||
elif verse_type == VerseType.Other:
|
||||
self.insertVerse(VerseType.to_string(VerseType.Other))
|
||||
|
||||
def onVerseTypeComboBoxChanged(self):
|
||||
"""
|
||||
Adjusts the verse number SpinBox in regard to the selected verse type
|
||||
and the cursor's position.
|
||||
"""
|
||||
position = self.verseTextEdit.textCursor().position()
|
||||
text = unicode(self.verseTextEdit.toPlainText())
|
||||
verse_type = VerseType.to_string(self.verseTypeComboBox.currentIndex())
|
||||
if not text:
|
||||
return
|
||||
position = text.rfind(u'---[%s' % verse_type, 0, position)
|
||||
if position == -1:
|
||||
self.verseNumberBox.setValue(1)
|
||||
return
|
||||
text = text[position:]
|
||||
position = text.find(u']---')
|
||||
if position == -1:
|
||||
return
|
||||
text = text[:position + 4]
|
||||
match = self.verse_regex.match(text)
|
||||
if match:
|
||||
verse_type = match.group(1)
|
||||
verse_number = int(match.group(2))
|
||||
verse_type_index = VerseType.from_string(verse_type)
|
||||
if verse_type_index is not None:
|
||||
self.verseNumberBox.setValue(verse_number)
|
||||
|
||||
def onCursorPositionChanged(self):
|
||||
"""
|
||||
Determines the previous verse type and number in regard to the cursor's
|
||||
position and adjusts the ComboBox and SpinBox to these values.
|
||||
"""
|
||||
position = self.verseTextEdit.textCursor().position()
|
||||
text = unicode(self.verseTextEdit.toPlainText())
|
||||
if not text:
|
||||
|
@ -112,6 +112,12 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
QtCore.QObject.connect(self.ewBrowseButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onEWBrowseButtonClicked)
|
||||
QtCore.QObject.connect(self.songBeamerAddButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onSongBeamerAddButtonClicked)
|
||||
QtCore.QObject.connect(self.songBeamerRemoveButton,
|
||||
QtCore.SIGNAL(u'clicked()'),
|
||||
self.onSongBeamerRemoveButtonClicked)
|
||||
QtCore.QObject.connect(self.cancelButton,
|
||||
QtCore.SIGNAL(u'clicked(bool)'),
|
||||
self.onCancelButtonClicked)
|
||||
@ -227,23 +233,39 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
'file to import from.'))
|
||||
self.ewBrowseButton.setFocus()
|
||||
return False
|
||||
elif source_format == SongFormat.SongBeamer:
|
||||
if self.songBeamerFileListWidget.count() == 0:
|
||||
QtGui.QMessageBox.critical(self,
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'No SongBeamer File Selected'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'You need to add at least one SongBeamer '
|
||||
'file to import from.'))
|
||||
self.songBeamerAddButton.setFocus()
|
||||
return False
|
||||
return True
|
||||
elif self.currentId() == 2:
|
||||
# Progress page
|
||||
return True
|
||||
|
||||
def getFileName(self, title, editbox):
|
||||
def getFileName(self, title, editbox,
|
||||
filters = '%s (*)' % translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files')):
|
||||
filename = QtGui.QFileDialog.getOpenFileName(self, title,
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1))
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
|
||||
filters)
|
||||
if filename:
|
||||
editbox.setText(filename)
|
||||
SettingsManager.set_last_dir(
|
||||
self.plugin.settingsSection,
|
||||
os.path.split(unicode(filename))[0], 1)
|
||||
|
||||
def getFiles(self, title, listbox):
|
||||
def getFiles(self, title, listbox,
|
||||
filters = u'%s (*)' % translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files')):
|
||||
filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1))
|
||||
SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
|
||||
filters)
|
||||
if filenames:
|
||||
listbox.addItems(filenames)
|
||||
SettingsManager.set_last_dir(
|
||||
@ -265,14 +287,24 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFileName(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select OpenLP 2.0 Database File'),
|
||||
self.openLP2FilenameEdit
|
||||
self.openLP2FilenameEdit,
|
||||
u'%s (*.sqlite);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'OpenLP 2.0 Databases'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
)
|
||||
|
||||
def onOpenLP1BrowseButtonClicked(self):
|
||||
self.getFileName(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select openlp.org 1.x Database File'),
|
||||
self.openLP1FilenameEdit
|
||||
self.openLP1FilenameEdit,
|
||||
u'%s (*.olp);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'openlp.org v1.x Databases'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
)
|
||||
|
||||
#def onOpenLyricsAddButtonClicked(self):
|
||||
@ -299,7 +331,12 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select Words of Worship Files'),
|
||||
self.wordsOfWorshipFileListWidget
|
||||
self.wordsOfWorshipFileListWidget,
|
||||
u'%s (*.wsg *.wow-song);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'Words Of Worship Song Files'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
)
|
||||
|
||||
def onWordsOfWorshipRemoveButtonClicked(self):
|
||||
@ -319,7 +356,12 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select Songs of Fellowship Files'),
|
||||
self.songsOfFellowshipFileListWidget
|
||||
self.songsOfFellowshipFileListWidget,
|
||||
u'%s (*.rtf);;%s (*)'
|
||||
% (translate('SongsPlugin.ImportWizardForm',
|
||||
'Songs Of Felloship Song Files'),
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'All Files'))
|
||||
)
|
||||
|
||||
def onSongsOfFellowshipRemoveButtonClicked(self):
|
||||
@ -342,6 +384,16 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.ewFilenameEdit
|
||||
)
|
||||
|
||||
def onSongBeamerAddButtonClicked(self):
|
||||
self.getFiles(
|
||||
translate('SongsPlugin.ImportWizardForm',
|
||||
'Select SongBeamer Files'),
|
||||
self.songBeamerFileListWidget
|
||||
)
|
||||
|
||||
def onSongBeamerRemoveButtonClicked(self):
|
||||
self.removeSelectedItems(self.songBeamerFileListWidget)
|
||||
|
||||
def onCancelButtonClicked(self, checked):
|
||||
"""
|
||||
Stop the import on pressing the cancel button.
|
||||
@ -373,6 +425,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
self.songsOfFellowshipFileListWidget.clear()
|
||||
self.genericFileListWidget.clear()
|
||||
self.ewFilenameEdit.setText(u'')
|
||||
self.songBeamerFileListWidget.clear()
|
||||
#self.csvFilenameEdit.setText(u'')
|
||||
|
||||
def incrementProgressBar(self, status_text, increment=1):
|
||||
@ -448,6 +501,12 @@ class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard):
|
||||
importer = self.plugin.importSongs(SongFormat.EasyWorship,
|
||||
filename=unicode(self.ewFilenameEdit.text())
|
||||
)
|
||||
elif source_format == SongFormat.SongBeamer:
|
||||
# Import SongBeamer songs
|
||||
importer = self.plugin.importSongs(SongFormat.SongBeamer,
|
||||
filenames=self.getListOfFiles(
|
||||
self.songBeamerFileListWidget)
|
||||
)
|
||||
success = importer.do_import()
|
||||
if success:
|
||||
# reload songs
|
||||
|
@ -116,6 +116,8 @@ class Ui_SongImportWizard(object):
|
||||
self.addMultiFileSelectItem(u'generic', None, True)
|
||||
# EasyWorship
|
||||
self.addSingleFileSelectItem(u'ew')
|
||||
# Words of Worship
|
||||
self.addMultiFileSelectItem(u'songBeamer')
|
||||
# Commented out for future use.
|
||||
# self.addSingleFileSelectItem(u'csv', u'CSV')
|
||||
self.sourceLayout.addWidget(self.formatStackedWidget)
|
||||
@ -180,6 +182,8 @@ class Ui_SongImportWizard(object):
|
||||
'Generic Document/Presentation'))
|
||||
self.formatComboBox.setItemText(8,
|
||||
translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
|
||||
self.formatComboBox.setItemText(9,
|
||||
translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
|
||||
# self.formatComboBox.setItemText(9,
|
||||
# translate('SongsPlugin.ImportWizardForm', 'CSV'))
|
||||
self.openLP2FilenameLabel.setText(
|
||||
@ -236,6 +240,10 @@ class Ui_SongImportWizard(object):
|
||||
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
self.ewBrowseButton.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Browse...'))
|
||||
self.songBeamerAddButton.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
|
||||
self.songBeamerRemoveButton.setText(
|
||||
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
|
||||
# self.csvFilenameLabel.setText(
|
||||
# translate('SongsPlugin.ImportWizardForm', 'Filename:'))
|
||||
# self.csvBrowseButton.setText(
|
||||
|
@ -38,9 +38,9 @@ class CCLIFileImportError(Exception):
|
||||
|
||||
class CCLIFileImport(SongImport):
|
||||
"""
|
||||
The :class:`CCLIFileImport` class provides OpenLP with the
|
||||
ability to import CCLI SongSelect song files in both .txt and
|
||||
.usr formats. See http://www.ccli.com
|
||||
The :class:`CCLIFileImport` class provides OpenLP with the ability to
|
||||
import CCLI SongSelect song files in both .txt and .usr formats.
|
||||
See http://www.ccli.com/ for more details.
|
||||
"""
|
||||
|
||||
def __init__(self, manager, **kwargs):
|
||||
@ -49,6 +49,7 @@ class CCLIFileImport(SongImport):
|
||||
|
||||
``manager``
|
||||
The song manager for the running OpenLP installation.
|
||||
|
||||
``filenames``
|
||||
The files to be imported.
|
||||
"""
|
||||
@ -97,7 +98,7 @@ class CCLIFileImport(SongImport):
|
||||
|
||||
def do_import_usr_file(self, textList):
|
||||
"""
|
||||
The :method:`do_import_usr_file` method provides OpenLP
|
||||
The :func:`do_import_usr_file` method provides OpenLP
|
||||
with the ability to import CCLI SongSelect songs in
|
||||
*USR* file format
|
||||
|
||||
@ -105,6 +106,7 @@ class CCLIFileImport(SongImport):
|
||||
An array of strings containing the usr file content.
|
||||
|
||||
**SongSelect .usr file format**
|
||||
|
||||
``[File]``
|
||||
USR file format first line
|
||||
``Type=``
|
||||
@ -140,6 +142,7 @@ class CCLIFileImport(SongImport):
|
||||
Contains the songs various lyrics in order as shown by the
|
||||
*Fields* description
|
||||
e.g. *Words=Above all powers....* [/n = CR, /n/t = CRLF]
|
||||
|
||||
"""
|
||||
log.debug(u'USR file text: %s', textList)
|
||||
lyrics = []
|
||||
@ -191,48 +194,32 @@ class CCLIFileImport(SongImport):
|
||||
|
||||
def do_import_txt_file(self, textList):
|
||||
"""
|
||||
The :method:`do_import_txt_file` method provides OpenLP
|
||||
The :func:`do_import_txt_file` method provides OpenLP
|
||||
with the ability to import CCLI SongSelect songs in
|
||||
*TXT* file format
|
||||
|
||||
``textList``
|
||||
An array of strings containing the txt file content.
|
||||
|
||||
**SongSelect .txt file format**
|
||||
SongSelect .txt file format::
|
||||
|
||||
``Song Title``
|
||||
Contains the song title
|
||||
|
||||
<Empty line>
|
||||
|
||||
``Title of following verse/chorus and number``
|
||||
e.g. Verse 1, Chorus 1
|
||||
|
||||
``Verse/Chorus lyrics``
|
||||
|
||||
<Empty line>
|
||||
|
||||
<Empty line>
|
||||
|
||||
``Title of next verse/chorus (repeats)``
|
||||
|
||||
``Verse/Chorus lyrics``
|
||||
|
||||
<Empty line>
|
||||
|
||||
<Empty line>
|
||||
|
||||
``Song CCLI Number``
|
||||
e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885)
|
||||
``Song Copyright``
|
||||
e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing
|
||||
``Song Authors``
|
||||
e.g. Lenny LeBlanc | Paul Baloche
|
||||
``Licencing info``
|
||||
e.g. For use solely with the SongSelect Terms of Use.
|
||||
Song Title # Contains the song title
|
||||
<Empty line>
|
||||
Verse type and number # e.g. Verse 1, Chorus 1
|
||||
Verse lyrics
|
||||
<Empty line>
|
||||
<Empty line>
|
||||
Verse type and number (repeats)
|
||||
Verse lyrics
|
||||
<Empty line>
|
||||
<Empty line>
|
||||
Song CCLI number # e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885)
|
||||
Song copyright # e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing
|
||||
Song authors # e.g. Lenny LeBlanc | Paul Baloche
|
||||
Licencing info # e.g. For use solely with the SongSelect Terms of Use.
|
||||
All rights Reserved. www.ccli.com
|
||||
``CCLI Licence number of user``
|
||||
e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
|
||||
CCLI Licence number of user # e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
|
||||
|
||||
"""
|
||||
log.debug(u'TXT file text: %s', textList)
|
||||
self.set_defaults()
|
||||
|
@ -35,7 +35,7 @@ import struct
|
||||
from openlp.core.lib import translate
|
||||
from songimport import SongImport
|
||||
|
||||
def strip_rtf(blob):
|
||||
def strip_rtf(blob, encoding):
|
||||
depth = 0
|
||||
control = False
|
||||
clear_text = []
|
||||
@ -69,12 +69,42 @@ def strip_rtf(blob):
|
||||
if control_str == 'par' or control_str == 'line':
|
||||
clear_text.append(u'\n')
|
||||
elif control_str == 'tab':
|
||||
clear_text.append(u'\n')
|
||||
clear_text.append(u'\t')
|
||||
# Prefer the encoding specified by the RTF data to that
|
||||
# specified by the Paradox table header
|
||||
# West European encoding
|
||||
elif control_str == 'fcharset0':
|
||||
encoding = u'cp1252'
|
||||
# Greek encoding
|
||||
elif control_str == 'fcharset161':
|
||||
encoding = u'cp1253'
|
||||
# Turkish encoding
|
||||
elif control_str == 'fcharset162':
|
||||
encoding = u'cp1254'
|
||||
# Vietnamese encoding
|
||||
elif control_str == 'fcharset163':
|
||||
encoding = u'cp1258'
|
||||
# Hebrew encoding
|
||||
elif control_str == 'fcharset177':
|
||||
encoding = u'cp1255'
|
||||
# Arabic encoding
|
||||
elif control_str == 'fcharset178':
|
||||
encoding = u'cp1256'
|
||||
# Baltic encoding
|
||||
elif control_str == 'fcharset186':
|
||||
encoding = u'cp1257'
|
||||
# Cyrillic encoding
|
||||
elif control_str == 'fcharset204':
|
||||
encoding = u'cp1251'
|
||||
# Thai encoding
|
||||
elif control_str == 'fcharset222':
|
||||
encoding = u'cp874'
|
||||
# Central+East European encoding
|
||||
elif control_str == 'fcharset238':
|
||||
encoding = u'cp1250'
|
||||
elif control_str[0] == '\'':
|
||||
# Really should take RTF character set into account but
|
||||
# for now assume ANSI (Windows-1252) and call it good
|
||||
s = chr(int(control_str[1:3], 16))
|
||||
clear_text.append(s.decode(u'windows-1252'))
|
||||
clear_text.append(s.decode(encoding))
|
||||
del control_word[:]
|
||||
if c == '\\' and new_control:
|
||||
control = True
|
||||
@ -126,6 +156,30 @@ class EasyWorshipSongImport(SongImport):
|
||||
db_file.close()
|
||||
self.memo_file.close()
|
||||
return False
|
||||
# Take a stab at how text is encoded
|
||||
self.encoding = u'cp1252'
|
||||
db_file.seek(106)
|
||||
code_page, = struct.unpack('<h', db_file.read(2))
|
||||
if code_page == 852:
|
||||
self.encoding = u'cp1250'
|
||||
# The following codepage to actual encoding mappings have not been
|
||||
# observed, but merely guessed. Actual example files are needed.
|
||||
#if code_page == 737:
|
||||
# self.encoding = u'cp1253'
|
||||
#if code_page == 775:
|
||||
# self.encoding = u'cp1257'
|
||||
#if code_page == 855:
|
||||
# self.encoding = u'cp1251'
|
||||
#if code_page == 857:
|
||||
# self.encoding = u'cp1254'
|
||||
#if code_page == 866:
|
||||
# self.encoding = u'cp1251'
|
||||
#if code_page == 869:
|
||||
# self.encoding = u'cp1253'
|
||||
#if code_page == 862:
|
||||
# self.encoding = u'cp1255'
|
||||
#if code_page == 874:
|
||||
# self.encoding = u'cp874'
|
||||
# There does not appear to be a _reliable_ way of getting the number
|
||||
# of songs/records, so let's use file blocks for measuring progress.
|
||||
total_blocks = (db_size - header_size) / (block_size * 1024)
|
||||
@ -204,7 +258,7 @@ class EasyWorshipSongImport(SongImport):
|
||||
self.add_author(author_name.strip())
|
||||
if words:
|
||||
# Format the lyrics
|
||||
words = strip_rtf(words)
|
||||
words = strip_rtf(words, self.encoding)
|
||||
for verse in words.split(u'\n\n'):
|
||||
self.add_verse(verse.strip(), u'V')
|
||||
if self.stop_import_flag:
|
||||
@ -263,7 +317,7 @@ class EasyWorshipSongImport(SongImport):
|
||||
# Format the field depending on the field type
|
||||
if field_desc.type == 1:
|
||||
# string
|
||||
return field.rstrip('\0').decode(u'windows-1252')
|
||||
return field.rstrip('\0').decode(self.encoding)
|
||||
elif field_desc.type == 3:
|
||||
# 16-bit int
|
||||
return field ^ 0x8000
|
||||
|
@ -29,6 +29,7 @@ from olpimport import OpenLPSongImport
|
||||
from wowimport import WowImport
|
||||
from cclifileimport import CCLIFileImport
|
||||
from ewimport import EasyWorshipSongImport
|
||||
from songbeamerimport import SongBeamerImport
|
||||
# Imports that might fail
|
||||
try:
|
||||
from olp1import import OpenLP1SongImport
|
||||
@ -64,6 +65,7 @@ class SongFormat(object):
|
||||
Generic = 7
|
||||
#CSV = 8
|
||||
EasyWorship = 8
|
||||
SongBeamer = 9
|
||||
|
||||
@staticmethod
|
||||
def get_class(format):
|
||||
@ -89,6 +91,8 @@ class SongFormat(object):
|
||||
return CCLIFileImport
|
||||
elif format == SongFormat.EasyWorship:
|
||||
return EasyWorshipSongImport
|
||||
elif format == SongFormat.SongBeamer:
|
||||
return SongBeamerImport
|
||||
# else:
|
||||
return None
|
||||
|
||||
@ -106,7 +110,8 @@ class SongFormat(object):
|
||||
SongFormat.CCLI,
|
||||
SongFormat.SongsOfFellowship,
|
||||
SongFormat.Generic,
|
||||
SongFormat.EasyWorship
|
||||
SongFormat.EasyWorship,
|
||||
SongFormat.SongBeamer
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
|
@ -48,12 +48,10 @@ class SongMediaItem(MediaManagerItem):
|
||||
"""
|
||||
log.info(u'Song Media Item loaded')
|
||||
|
||||
def __init__(self, parent, icon, title):
|
||||
self.PluginNameShort = u'Song'
|
||||
self.pluginNameVisible = translate('SongsPlugin.MediaItem', 'Song')
|
||||
def __init__(self, parent, plugin, icon):
|
||||
self.IconPath = u'songs/song'
|
||||
self.ListViewWithDnD_class = SongListView
|
||||
MediaManagerItem.__init__(self, parent, icon, title)
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
self.edit_song_form = EditSongForm(self, self.parent.manager)
|
||||
self.singleServiceItem = False
|
||||
#self.edit_song_form = EditSongForm(self.parent.manager, self)
|
||||
@ -62,6 +60,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
# Holds information about whether the edit is remotly triggered and
|
||||
# which Song is required.
|
||||
self.remoteSong = -1
|
||||
self.editItem = None
|
||||
|
||||
def requiredIcons(self):
|
||||
MediaManagerItem.requiredIcons(self)
|
||||
@ -125,7 +124,7 @@ class SongMediaItem(MediaManagerItem):
|
||||
QtCore.SIGNAL(u'textChanged(const QString&)'),
|
||||
self.onSearchTextEditChanged)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'songs_load_list'), self.onSearchTextButtonClick)
|
||||
QtCore.SIGNAL(u'songs_load_list'), self.onSongListLoad)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'config_updated'), self.configUpdated)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
@ -139,6 +138,12 @@ class SongMediaItem(MediaManagerItem):
|
||||
self.searchAsYouType = QtCore.QSettings().value(
|
||||
self.settingsSection + u'/search as type',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
self.updateServiceOnEdit = QtCore.QSettings().value(
|
||||
self.settingsSection + u'/update service on edit',
|
||||
QtCore.QVariant(u'False')).toBool()
|
||||
self.AddSongFromServide = QtCore.QSettings().value(
|
||||
self.settingsSection + u'/add song from service',
|
||||
QtCore.QVariant(u'True')).toBool()
|
||||
|
||||
def retranslateUi(self):
|
||||
self.SearchTextLabel.setText(
|
||||
@ -181,14 +186,26 @@ class SongMediaItem(MediaManagerItem):
|
||||
Author.display_name.like(u'%' + search_keywords + u'%'),
|
||||
Author.display_name.asc())
|
||||
self.displayResultsAuthor(search_results)
|
||||
#Called to redisplay the song list screen edith from a search
|
||||
#or from the exit of the Song edit dialog. If remote editing is active
|
||||
#Trigger it and clean up so it will not update again.
|
||||
|
||||
def onSongListLoad(self):
|
||||
"""
|
||||
Handle the exit from the edit dialog and trigger remote updates
|
||||
of songs
|
||||
"""
|
||||
# Called to redisplay the song list screen edit from a search
|
||||
# or from the exit of the Song edit dialog. If remote editing is active
|
||||
# Trigger it and clean up so it will not update again.
|
||||
if self.remoteTriggered == u'L':
|
||||
self.onAddClick()
|
||||
if self.remoteTriggered == u'P':
|
||||
self.onPreviewClick()
|
||||
# Push edits to the service manager to update items
|
||||
if self.editItem and self.updateServiceOnEdit and \
|
||||
not self.remoteTriggered:
|
||||
item = self.buildServiceItem(self.editItem)
|
||||
self.parent.serviceManager.replaceServiceItem(item)
|
||||
self.onRemoteEditClear()
|
||||
self.onSearchTextButtonClick()
|
||||
|
||||
def displayResultsSong(self, searchresults):
|
||||
log.debug(u'display results Song')
|
||||
@ -273,8 +290,8 @@ class SongMediaItem(MediaManagerItem):
|
||||
if check_item_selected(self.listView,
|
||||
translate('SongsPlugin.MediaItem',
|
||||
'You must select an item to edit.')):
|
||||
item = self.listView.currentItem()
|
||||
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.editItem = self.listView.currentItem()
|
||||
item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.edit_song_form.loadSong(item_id, False)
|
||||
self.edit_song_form.exec_()
|
||||
|
||||
@ -324,6 +341,8 @@ class SongMediaItem(MediaManagerItem):
|
||||
service_item.add_capability(ItemCapabilities.AllowsEdit)
|
||||
service_item.add_capability(ItemCapabilities.AllowsPreview)
|
||||
service_item.add_capability(ItemCapabilities.AllowsLoop)
|
||||
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
|
||||
service_item.add_capability(ItemCapabilities.AddIfNewItem)
|
||||
song = self.parent.manager.get_object(Song, item_id)
|
||||
service_item.theme = song.theme_name
|
||||
service_item.editId = item_id
|
||||
@ -370,4 +389,31 @@ class SongMediaItem(MediaManagerItem):
|
||||
service_item.audit = [
|
||||
song.title, author_audit, song.copyright, unicode(song.ccli_number)
|
||||
]
|
||||
service_item.data_string = {u'title':song.search_title, u'authors':author_list}
|
||||
return True
|
||||
|
||||
def serviceLoad(self, item):
|
||||
"""
|
||||
Triggered by a song being loaded by the service item
|
||||
"""
|
||||
if item.data_string:
|
||||
search_results = self.parent.manager.get_all_objects(Song,
|
||||
Song.search_title.like(u'%' +
|
||||
item.data_string[u'title'].split(u'@')[0] + u'%'),
|
||||
Song.search_title.asc())
|
||||
author_list = item.data_string[u'authors'].split(u',')
|
||||
editId = 0
|
||||
uuid = 0
|
||||
if search_results:
|
||||
for song in search_results:
|
||||
count = 0
|
||||
for author in song.authors:
|
||||
if author.display_name in author_list:
|
||||
count += 1
|
||||
if count == len(author_list):
|
||||
editId = song.id
|
||||
uuid = item._uuid
|
||||
if editId != 0:
|
||||
Receiver.send_message(u'service_item_update',
|
||||
u'%s:%s' %(editId, uuid))
|
||||
|
||||
|
236
openlp/plugins/songs/lib/songbeamerimport.py
Normal file
236
openlp/plugins/songs/lib/songbeamerimport.py
Normal file
@ -0,0 +1,236 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
|
||||
|
||||
###############################################################################
|
||||
# OpenLP - Open Source Lyrics Projection #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Copyright (c) 2008-2010 Raoul Snyman #
|
||||
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
|
||||
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
|
||||
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
|
||||
# Carsten Tinggaard, Frode Woldsund #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# This program is free software; you can redistribute it and/or modify it #
|
||||
# under the terms of the GNU General Public License as published by the Free #
|
||||
# Software Foundation; version 2 of the License. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT #
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
||||
# more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License along #
|
||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||
###############################################################################
|
||||
"""
|
||||
The :mod:`songbeamerimport` module provides the functionality for importing
|
||||
SongBeamer songs into the OpenLP database.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import chardet
|
||||
import codecs
|
||||
|
||||
from openlp.plugins.songs.lib.songimport import SongImport
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class SongBeamerTypes(object):
|
||||
MarkTypes = {
|
||||
u'Refrain': u'C',
|
||||
u'Chorus': u'C',
|
||||
u'Vers': u'V',
|
||||
u'Verse': u'V',
|
||||
u'Strophe': u'V',
|
||||
u'Intro': u'I',
|
||||
u'Coda': u'E',
|
||||
u'Ending': u'E',
|
||||
u'Bridge': u'B',
|
||||
u'Interlude': u'B',
|
||||
u'Zwischenspiel': u'B',
|
||||
u'Pre-Chorus': u'P',
|
||||
u'Pre-Refrain': u'P',
|
||||
u'Pre-Bridge': u'O',
|
||||
u'Pre-Coda': u'O',
|
||||
u'Unbekannt': u'O',
|
||||
u'Unknown': u'O'
|
||||
}
|
||||
|
||||
class SongBeamerImport(SongImport):
|
||||
"""
|
||||
Import Song Beamer files(s)
|
||||
Song Beamer file format is text based
|
||||
in the beginning are one or more control tags written
|
||||
"""
|
||||
def __init__(self, master_manager, **kwargs):
|
||||
"""
|
||||
Initialise the import.
|
||||
``master_manager``
|
||||
The song manager for the running OpenLP installation.
|
||||
"""
|
||||
SongImport.__init__(self, master_manager)
|
||||
self.master_manager = master_manager
|
||||
if kwargs.has_key(u'filename'):
|
||||
self.import_source = kwargs[u'filename']
|
||||
if kwargs.has_key(u'filenames'):
|
||||
self.import_source = kwargs[u'filenames']
|
||||
log.debug(self.import_source)
|
||||
|
||||
def do_import(self):
|
||||
"""
|
||||
Recieve a single file, or a list of files to import.
|
||||
"""
|
||||
if isinstance(self.import_source, list):
|
||||
self.import_wizard.importProgressBar.setMaximum(
|
||||
len(self.import_source))
|
||||
for file in self.import_source:
|
||||
# TODO: check that it is a valid SongBeamer file
|
||||
self.current_verse = u''
|
||||
self.current_verse_type = u'V'
|
||||
self.file_name = os.path.split(file)[1]
|
||||
self.import_wizard.incrementProgressBar(
|
||||
"Importing %s" % (self.file_name), 0)
|
||||
if os.path.isfile(file):
|
||||
detect_file = open(file, u'r')
|
||||
details = chardet.detect(detect_file.read(2048))
|
||||
detect_file.close()
|
||||
infile = codecs.open(file, u'r', details['encoding'])
|
||||
self.songData = infile.readlines()
|
||||
else:
|
||||
return False
|
||||
for line in self.songData:
|
||||
line = line.strip()
|
||||
if line.startswith('#'):
|
||||
log.debug(u'find tag: %s' % line)
|
||||
if not self.parse_tags(line):
|
||||
return False
|
||||
elif line.startswith('---'):
|
||||
log.debug(u'find ---')
|
||||
if len(self.current_verse) > 0:
|
||||
self.add_verse(self.current_verse,
|
||||
self.current_verse_type)
|
||||
self.current_verse = u''
|
||||
self.current_verse_type = u'V'
|
||||
self.read_verse = True
|
||||
self.verse_start = True
|
||||
elif self.read_verse:
|
||||
if self.verse_start:
|
||||
self.check_verse_marks(line)
|
||||
self.verse_start = False
|
||||
else:
|
||||
self.current_verse += u'%s\n' % line
|
||||
if len(self.current_verse) > 0:
|
||||
self.add_verse(self.current_verse, self.current_verse_type)
|
||||
self.finish()
|
||||
self.import_wizard.incrementProgressBar(
|
||||
"Importing %s" % (self.file_name))
|
||||
return True
|
||||
|
||||
def parse_tags(self, line):
|
||||
tag_val = line.split('=')
|
||||
if len(tag_val[0]) == 0 or \
|
||||
len(tag_val[1]) == 0:
|
||||
return True
|
||||
if tag_val[0] == '#(c)':
|
||||
self.add_copyright(tag_val[1])
|
||||
elif tag_val[0] == '#AddCopyrightInfo':
|
||||
pass
|
||||
elif tag_val[0] == '#Author':
|
||||
#TODO split Authors
|
||||
self.add_author(tag_val[1])
|
||||
elif tag_val[0] == '#BackgroundImage':
|
||||
pass
|
||||
elif tag_val[0] == '#Bible':
|
||||
pass
|
||||
elif tag_val[0] == '#Categories':
|
||||
self.topics = line.split(',')
|
||||
elif tag_val[0] == '#CCLI':
|
||||
self.ccli_number = tag_val[1]
|
||||
elif tag_val[0] == '#Chords':
|
||||
pass
|
||||
elif tag_val[0] == '#ChurchSongID':
|
||||
pass
|
||||
elif tag_val[0] == '#ColorChords':
|
||||
pass
|
||||
elif tag_val[0] == '#Comments':
|
||||
self.comments = tag_val[1]
|
||||
elif tag_val[0] == '#Editor':
|
||||
pass
|
||||
elif tag_val[0] == '#Font':
|
||||
pass
|
||||
elif tag_val[0] == '#FontLang2':
|
||||
pass
|
||||
elif tag_val[0] == '#FontSize':
|
||||
pass
|
||||
elif tag_val[0] == '#Format':
|
||||
pass
|
||||
elif tag_val[0] == '#Format_PreLine':
|
||||
pass
|
||||
elif tag_val[0] == '#Format_PrePage':
|
||||
pass
|
||||
elif tag_val[0] == '#ID':
|
||||
pass
|
||||
elif tag_val[0] == '#Key':
|
||||
pass
|
||||
elif tag_val[0] == '#Keywords':
|
||||
pass
|
||||
elif tag_val[0] == '#LangCount':
|
||||
pass
|
||||
elif tag_val[0] == '#Melody':
|
||||
#TODO split Authors
|
||||
self.add_author(tag_val[1])
|
||||
elif tag_val[0] == '#NatCopyright':
|
||||
pass
|
||||
elif tag_val[0] == '#OTitle':
|
||||
pass
|
||||
elif tag_val[0] == '#OutlineColor':
|
||||
pass
|
||||
elif tag_val[0] == '#OutlinedFont':
|
||||
pass
|
||||
elif tag_val[0] == '#QuickFind':
|
||||
pass
|
||||
elif tag_val[0] == '#Rights':
|
||||
song_book_pub = tag_val[1]
|
||||
elif tag_val[0] == '#Songbook':
|
||||
book_num = tag_val[1].split(' / ')
|
||||
self.song_book_name = book_num[0]
|
||||
if len(book_num) == book_num[1]:
|
||||
self.song_number = u''
|
||||
elif tag_val[0] == '#Speed':
|
||||
pass
|
||||
elif tag_val[0] == '#TextAlign':
|
||||
pass
|
||||
elif tag_val[0] == '#Title':
|
||||
self.title = u'%s' % tag_val[1]
|
||||
elif tag_val[0] == '#TitleAlign':
|
||||
pass
|
||||
elif tag_val[0] == '#TitleFontSize':
|
||||
pass
|
||||
elif tag_val[0] == '#TitleLang2':
|
||||
pass
|
||||
elif tag_val[0] == '#TitleLang3':
|
||||
pass
|
||||
elif tag_val[0] == '#TitleLang4':
|
||||
pass
|
||||
elif tag_val[0] == '#Translation':
|
||||
pass
|
||||
elif tag_val[0] == '#Transpose':
|
||||
pass
|
||||
elif tag_val[0] == '#TransposeAccidental':
|
||||
pass
|
||||
elif tag_val[0] == '#Version':
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
return True
|
||||
|
||||
def check_verse_marks(self, line):
|
||||
marks = line.split(' ')
|
||||
if len(marks) <= 2 and \
|
||||
marks[0] in SongBeamerTypes.MarkTypes:
|
||||
self.current_verse_type = SongBeamerTypes.MarkTypes[marks[0]]
|
||||
if len(marks) == 2:
|
||||
#TODO: may check, because of only digits are allowed
|
||||
self.current_verse_type += marks[1]
|
@ -32,12 +32,11 @@ class SongsTab(SettingsTab):
|
||||
"""
|
||||
SongsTab is the Songs 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'SongsTab')
|
||||
self.tabTitleVisible = translate('SongsPlugin.SongsTab', 'Songs')
|
||||
self.SongsLayout = QtGui.QFormLayout(self)
|
||||
self.SongsLayout.setSpacing(8)
|
||||
self.SongsLayout.setMargin(8)
|
||||
@ -52,8 +51,14 @@ class SongsTab(SettingsTab):
|
||||
self.SearchAsTypeCheckBox.setObjectName(u'SearchAsTypeCheckBox')
|
||||
self.SongsModeLayout.addWidget(self.SearchAsTypeCheckBox)
|
||||
self.SongBarActiveCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
|
||||
self.SongBarActiveCheckBox.setObjectName(u'SearchAsTypeCheckBox')
|
||||
self.SongBarActiveCheckBox.setObjectName(u'SongBarActiveCheckBox')
|
||||
self.SongsModeLayout.addWidget(self.SongBarActiveCheckBox)
|
||||
self.SongUpdateOnEditCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
|
||||
self.SongUpdateOnEditCheckBox.setObjectName(u'SongUpdateOnEditCheckBox')
|
||||
self.SongsModeLayout.addWidget(self.SongUpdateOnEditCheckBox)
|
||||
self.SongAddFromServiceCheckBox = QtGui.QCheckBox(self.SongsModeGroupBox)
|
||||
self.SongAddFromServiceCheckBox.setObjectName(u'SongAddFromServiceCheckBox')
|
||||
self.SongsModeLayout.addWidget(self.SongAddFromServiceCheckBox)
|
||||
self.SongsLayout.setWidget(
|
||||
0, QtGui.QFormLayout.LabelRole, self.SongsModeGroupBox)
|
||||
QtCore.QObject.connect(self.SearchAsTypeCheckBox,
|
||||
@ -61,7 +66,13 @@ class SongsTab(SettingsTab):
|
||||
self.onSearchAsTypeCheckBoxChanged)
|
||||
QtCore.QObject.connect(self.SongBarActiveCheckBox,
|
||||
QtCore.SIGNAL(u'stateChanged(int)'),
|
||||
self.SongBarActiveCheckBoxChanged)
|
||||
self.onSongBarActiveCheckBoxChanged)
|
||||
QtCore.QObject.connect(self.SongUpdateOnEditCheckBox,
|
||||
QtCore.SIGNAL(u'stateChanged(int)'),
|
||||
self.onSongUpdateOnEditCheckBoxChanged)
|
||||
QtCore.QObject.connect(self.SongBarActiveCheckBox,
|
||||
QtCore.SIGNAL(u'stateChanged(int)'),
|
||||
self.onSongAddFromServiceCheckBoxChanged)
|
||||
|
||||
def retranslateUi(self):
|
||||
self.SongsModeGroupBox.setTitle(
|
||||
@ -70,6 +81,10 @@ class SongsTab(SettingsTab):
|
||||
translate('SongsPlugin.SongsTab', 'Enable search as you type'))
|
||||
self.SongBarActiveCheckBox.setText(translate('SongsPlugin.SongsTab',
|
||||
'Display verses on live tool bar'))
|
||||
self.SongUpdateOnEditCheckBox.setText(
|
||||
translate('SongsPlugin.SongsTab', 'Update service from song edit'))
|
||||
self.SongAddFromServiceCheckBox.setText(translate('SongsPlugin.SongsTab',
|
||||
'Add missing songs when opening service'))
|
||||
|
||||
def onSearchAsTypeCheckBoxChanged(self, check_state):
|
||||
self.song_search = False
|
||||
@ -77,12 +92,24 @@ class SongsTab(SettingsTab):
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
self.song_search = True
|
||||
|
||||
def SongBarActiveCheckBoxChanged(self, check_state):
|
||||
def onSongBarActiveCheckBoxChanged(self, check_state):
|
||||
self.song_bar = False
|
||||
# we have a set value convert to True/False
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
self.song_bar = True
|
||||
|
||||
def onSongUpdateOnEditCheckBoxChanged(self, check_state):
|
||||
self.update_edit = False
|
||||
# we have a set value convert to True/False
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
self.update_edit = True
|
||||
|
||||
def onSongAddFromServiceCheckBoxChanged(self, check_state):
|
||||
self.update_load = False
|
||||
# we have a set value convert to True/False
|
||||
if check_state == QtCore.Qt.Checked:
|
||||
self.update_load = True
|
||||
|
||||
def load(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
@ -90,8 +117,14 @@ class SongsTab(SettingsTab):
|
||||
u'search as type', QtCore.QVariant(False)).toBool()
|
||||
self.song_bar = settings.value(
|
||||
u'display songbar', QtCore.QVariant(True)).toBool()
|
||||
self.update_edit = settings.value(
|
||||
u'update service on edit', QtCore.QVariant(False)).toBool()
|
||||
self.update_load = settings.value(
|
||||
u'add song from service', QtCore.QVariant(True)).toBool()
|
||||
self.SearchAsTypeCheckBox.setChecked(self.song_search)
|
||||
self.SongBarActiveCheckBox.setChecked(self.song_bar)
|
||||
self.SongUpdateOnEditCheckBox.setChecked(self.update_edit)
|
||||
self.SongAddFromServiceCheckBox.setChecked(self.update_load)
|
||||
settings.endGroup()
|
||||
|
||||
def save(self):
|
||||
@ -99,4 +132,6 @@ class SongsTab(SettingsTab):
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'search as type', QtCore.QVariant(self.song_search))
|
||||
settings.setValue(u'display songbar', QtCore.QVariant(self.song_bar))
|
||||
settings.setValue(u'update service on edit', QtCore.QVariant(self.update_edit))
|
||||
settings.setValue(u'add song from service', QtCore.QVariant(self.update_load))
|
||||
settings.endGroup()
|
||||
|
@ -282,11 +282,9 @@ class Song(object):
|
||||
def get_author_list(self, asOneString = True):
|
||||
"""Return the list of authors as a string
|
||||
|
||||
asOneString
|
||||
True -- string:
|
||||
'John Newton, A Parker'
|
||||
False -- list of strings
|
||||
['John Newton', u'A Parker']
|
||||
``asOneString``
|
||||
If ``True``, returns 'John Newton, A Parker'. If ``False``, returns
|
||||
[u'John Newton', u'A Parker']
|
||||
"""
|
||||
if asOneString:
|
||||
res = self._assure_string(self.author_list)
|
||||
@ -297,7 +295,8 @@ class Song(object):
|
||||
def set_author_list(self, author_list):
|
||||
"""Set the author_list
|
||||
|
||||
author_list -- a string or list of strings
|
||||
``author_list``
|
||||
a string or list of strings
|
||||
"""
|
||||
if author_list is None:
|
||||
self.author_list = None
|
||||
@ -307,11 +306,9 @@ class Song(object):
|
||||
def get_category_array(self, asOneString = True):
|
||||
"""Return the list of categories as a string
|
||||
|
||||
asOneString
|
||||
True -- string:
|
||||
'Hymn, Gospel'
|
||||
False -- list of strings
|
||||
['Hymn', u'Gospel']
|
||||
``asOneString``
|
||||
If ``True``, returns 'Hymn, Gospel'. If ``False``, returns
|
||||
[u'Hymn', u'Gospel']
|
||||
"""
|
||||
if asOneString:
|
||||
res = self._assure_string(self.category_array)
|
||||
@ -381,6 +378,7 @@ class Song(object):
|
||||
properties
|
||||
|
||||
slideNumber -- 1 .. numberOfSlides
|
||||
|
||||
Returns a list as:
|
||||
[theme_name (string),
|
||||
title (string),
|
||||
|
@ -41,14 +41,13 @@ class WowImport(SongImport):
|
||||
The :class:`WowImport` class provides the ability to import song files from
|
||||
Words of Worship.
|
||||
|
||||
Words Of Worship Song File Format
|
||||
`````````````````````````````````
|
||||
**Words Of Worship Song File Format:**
|
||||
|
||||
The Words Of Worship song file format is as follows:
|
||||
|
||||
* The song title is the file name minus the extension.
|
||||
* The song has a header, a number of blocks, followed by footer containing
|
||||
the author and the copyright.
|
||||
the author and the copyright.
|
||||
* A block can be a verse, chorus or bridge.
|
||||
|
||||
File Header:
|
||||
@ -65,12 +64,12 @@ class WowImport(SongImport):
|
||||
Each block ends with 4 bytes, the first of which defines what type of
|
||||
block it is, and the rest which are null bytes:
|
||||
|
||||
* ``NUL`` (\x00) - Verse
|
||||
* ``SOH`` (\x01) - Chorus
|
||||
* ``STX`` (\x02) - Bridge
|
||||
* ``NUL`` (0x00) - Verse
|
||||
* ``SOH`` (0x01) - Chorus
|
||||
* ``STX`` (0x02) - Bridge
|
||||
|
||||
Blocks are seperated by two bytes. The first byte is ``SOH`` (\x01),
|
||||
and the second byte is ``€`` (\x80).
|
||||
Blocks are seperated by two bytes. The first byte is 0x01, and the
|
||||
second byte is 0x80.
|
||||
|
||||
Lines:
|
||||
Each line starts with a byte which specifies how long that line is,
|
||||
@ -116,16 +115,16 @@ class WowImport(SongImport):
|
||||
self.import_wizard.importProgressBar.setMaximum(
|
||||
len(self.import_source))
|
||||
for file in self.import_source:
|
||||
# TODO: check that it is a valid words of worship file (could
|
||||
# check header for WoW File Song Word)
|
||||
self.author = u''
|
||||
self.copyright = u''
|
||||
# Get the song title
|
||||
self.file_name = os.path.split(file)[1]
|
||||
self.import_wizard.incrementProgressBar(
|
||||
"Importing %s" % (self.file_name), 0)
|
||||
# Get the song title
|
||||
self.title = self.file_name.rpartition(u'.')[0]
|
||||
self.songData = open(file, 'rb')
|
||||
if self.songData.read(19) != u'WoW File\nSong Words':
|
||||
continue
|
||||
# Seek to byte which stores number of blocks in the song
|
||||
self.songData.seek(56)
|
||||
self.no_of_blocks = ord(self.songData.read(1))
|
||||
|
@ -28,7 +28,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.songs.lib import SongMediaItem, SongsTab
|
||||
from openlp.plugins.songs.lib.db import init_schema, Song
|
||||
@ -57,7 +57,8 @@ class SongsPlugin(Plugin):
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
||||
def getSettingsTab(self):
|
||||
return SongsTab(self.name)
|
||||
visible_name = self.getString(StringContent.VisibleName)
|
||||
return SongsTab(self.name, visible_name[u'title'])
|
||||
|
||||
def initialise(self):
|
||||
log.info(u'Songs Initialising')
|
||||
@ -70,7 +71,7 @@ class SongsPlugin(Plugin):
|
||||
Create the MediaManagerItem object, which is displaed in the
|
||||
Media Manager.
|
||||
"""
|
||||
return SongMediaItem(self, self.icon, self.name)
|
||||
return SongMediaItem(self, self, self.icon)
|
||||
|
||||
def addImportMenuItem(self, import_menu):
|
||||
"""
|
||||
@ -147,3 +148,54 @@ class SongsPlugin(Plugin):
|
||||
importer = class_(self.manager, **kwargs)
|
||||
importer.register(self.mediaItem.import_wizard)
|
||||
return importer
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('SongsPlugin', 'Song'),
|
||||
u'plural': translate('SongsPlugin', 'Songs')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('SongsPlugin', 'Songs')
|
||||
}
|
||||
# Middle Header Bar
|
||||
## New Button ##
|
||||
self.textStrings[StringContent.New] = {
|
||||
u'title': translate('SongsPlugin', 'Add'),
|
||||
u'tooltip': translate('SongsPlugin',
|
||||
'Add a new Song')
|
||||
}
|
||||
## Edit Button ##
|
||||
self.textStrings[StringContent.Edit] = {
|
||||
u'title': translate('SongsPlugin', 'Edit'),
|
||||
u'tooltip': translate('SongsPlugin',
|
||||
'Edit the selected Song')
|
||||
}
|
||||
## Delete Button ##
|
||||
self.textStrings[StringContent.Delete] = {
|
||||
u'title': translate('SongsPlugin', 'Delete'),
|
||||
u'tooltip': translate('SongsPlugin',
|
||||
'Delete the selected Song')
|
||||
}
|
||||
## Preview ##
|
||||
self.textStrings[StringContent.Preview] = {
|
||||
u'title': translate('SongsPlugin', 'Preview'),
|
||||
u'tooltip': translate('SongsPlugin',
|
||||
'Preview the selected Song')
|
||||
}
|
||||
## Live Button ##
|
||||
self.textStrings[StringContent.Live] = {
|
||||
u'title': translate('SongsPlugin', 'Live'),
|
||||
u'tooltip': translate('SongsPlugin',
|
||||
'Send the selected Song live')
|
||||
}
|
||||
## Add to service Button ##
|
||||
self.textStrings[StringContent.Service] = {
|
||||
u'title': translate('SongsPlugin', 'Service'),
|
||||
u'tooltip': translate('SongsPlugin',
|
||||
'Add the selected Song to the service')
|
||||
}
|
@ -29,7 +29,7 @@ from datetime import datetime
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import Plugin, Receiver, build_icon, translate
|
||||
from openlp.core.lib import Plugin, StringContent, Receiver, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.songusage.forms import SongUsageDetailForm, \
|
||||
SongUsageDeleteForm
|
||||
@ -162,3 +162,17 @@ class SongUsagePlugin(Plugin):
|
||||
'</strong><br />This plugin tracks the usage of songs in '
|
||||
'services.')
|
||||
return about_text
|
||||
|
||||
def setPluginTextStrings(self):
|
||||
"""
|
||||
Called to define all translatable texts of the plugin
|
||||
"""
|
||||
## Name PluginList ##
|
||||
self.textStrings[StringContent.Name] = {
|
||||
u'singular': translate('SongUsagePlugin', 'SongUsage'),
|
||||
u'plural': translate('SongUsagePlugin', 'SongUsage')
|
||||
}
|
||||
## Name for MediaDockManager, SettingsManager ##
|
||||
self.textStrings[StringContent.VisibleName] = {
|
||||
u'title': translate('SongUsagePlugin', 'SongUsage')
|
||||
}
|
@ -18,20 +18,48 @@
|
||||
<normaloff>:/icon/openlp.org-icon-32.bmp</normaloff>:/icon/openlp.org-icon-32.bmp</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item row="2" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="TitleLabel">
|
||||
<widget class="QLabel" name="ThemeLabel">
|
||||
<property name="text">
|
||||
<string>Title:</string>
|
||||
<string>Theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="TitleEdit"/>
|
||||
<widget class="QComboBox" name="ThemeComboBox">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Select custom theme for slide"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="CreditLabel">
|
||||
<property name="text">
|
||||
<string>Credits:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="CreditEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Edit dialog"/>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
@ -44,16 +72,42 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="UpButton">
|
||||
<widget class="QPushButton" name="AddButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Move slide up 1"/>
|
||||
<string extracomment="Adds a new slide at bottom"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
<string>Add New</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images/openlp-2.qrc">
|
||||
<normaloff>:/services/service_up.png</normaloff>:/services/service_up.png</iconset>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="EditButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Edit selected slide"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="EditAllButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Edit all slides"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="DeleteButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Delete selected slide"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -70,6 +124,20 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="UpButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Move slide up 1"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../images/openlp-2.qrc">
|
||||
<normaloff>:/services/service_up.png</normaloff>:/services/service_up.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="DownButton">
|
||||
<property name="toolTip">
|
||||
@ -88,166 +156,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QWidget" name="EditWidget" native="true">
|
||||
<layout class="QHBoxLayout" name="EditLayout_3">
|
||||
<property name="spacing">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="VerseTextEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="ButtonWidge" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="AddButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Adds a new slide at bottom"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add New</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="EditButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Edit selected slide"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="EditAllButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Edit all slides"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="SaveButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Replace edited slide"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="DeleteButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Delete selected slide"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="ClearButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Clear selection"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="SplitButton">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Add new slide split"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Split Slide</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="ButtonSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="ThemeLabel">
|
||||
<widget class="QLabel" name="TitleLabel">
|
||||
<property name="text">
|
||||
<string>Theme:</string>
|
||||
<string>Title:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="ThemeComboBox">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Select custom theme for slide"/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="TitleEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="CreditLabel">
|
||||
<property name="text">
|
||||
<string>Credits:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="CreditEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="toolTip">
|
||||
<string extracomment="Edit dialog"/>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>TitleEdit</tabstop>
|
||||
<tabstop>VerseTextEdit</tabstop>
|
||||
<tabstop>AddButton</tabstop>
|
||||
<tabstop>VerseListView</tabstop>
|
||||
<tabstop>EditButton</tabstop>
|
||||
<tabstop>EditAllButton</tabstop>
|
||||
<tabstop>SaveButton</tabstop>
|
||||
<tabstop>DeleteButton</tabstop>
|
||||
<tabstop>CreditEdit</tabstop>
|
||||
<tabstop>UpButton</tabstop>
|
||||
<tabstop>DownButton</tabstop>
|
||||
<tabstop>ThemeComboBox</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
|
96
resources/forms/editcustomslidedialog.ui
Normal file
96
resources/forms/editcustomslidedialog.ui
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>customSlideEditDialog</class>
|
||||
<widget class="QDialog" name="customSlideEditDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>474</width>
|
||||
<height>442</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>407</y>
|
||||
<width>458</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="VerseTextEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>8</y>
|
||||
<width>458</width>
|
||||
<height>349</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="SplitButton">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>380</x>
|
||||
<y>370</y>
|
||||
<width>85</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string extracomment="Add new slide split"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Split Slide</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../images/openlp-2.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>customSlideEditDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>customSlideEditDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -27,6 +27,7 @@ DefaultDirName={pf}\{#AppName}
|
||||
DefaultGroupName={#AppVerName}
|
||||
AllowNoIcons=true
|
||||
LicenseFile=LICENSE.txt
|
||||
OutputDir=..\..\dist
|
||||
OutputBaseFilename=OpenLP-{#RealVersion}-setup
|
||||
Compression=lzma
|
||||
SolidCompression=true
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
14
resources/windows/OpenLP.spec
Normal file
14
resources/windows/OpenLP.spec
Normal file
@ -0,0 +1,14 @@
|
||||
# -*- mode: python -*-
|
||||
a = Analysis([
|
||||
os.path.join(HOMEPATH, 'support\\_mountzlib.py'),
|
||||
os.path.join(HOMEPATH, 'support\\useUnicode.py'),
|
||||
os.path.abspath('openlp.pyw')],
|
||||
pathex=[os.path.abspath('.')])
|
||||
pyz = PYZ(a.pure)
|
||||
exe = EXE(pyz, a.scripts, exclude_binaries=1,
|
||||
name=os.path.abspath(os.path.join('build', 'pyi.win32', 'OpenLP',
|
||||
'OpenLP.exe')),
|
||||
debug=False, strip=False, upx=True, console=False,
|
||||
icon=os.path.abspath(os.path.join('resources', 'images', 'OpenLP.ico')))
|
||||
coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True,
|
||||
name=os.path.abspath(os.path.join('dist', 'OpenLP')))
|
611
resources/windows/warnOpenLP.txt
Normal file
611
resources/windows/warnOpenLP.txt
Normal file
@ -0,0 +1,611 @@
|
||||
W: no module named openlp.core.lib.build_html (top-level import by openlp.core.ui.maindisplay)
|
||||
W: no module named mx (top-level import by sqlite.main)
|
||||
W: no module named ctypes.create_string_buffer (delayed import by urllib)
|
||||
W: no module named openlp.core.ui.ServiceNoteForm (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named email.Iterators (delayed import by email.message)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named sqlalchemy.sql.join (top-level import by sqlalchemy)
|
||||
W: no module named java (conditional import by xml.sax._exceptions)
|
||||
W: no module named openlp.plugins.images.lib.ImageMediaItem (top-level import by openlp.plugins.images.imageplugin)
|
||||
W: no module named sqlalchemy.SMALLINT (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named sqlalchemy.engine.create_engine (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.sql.asc (top-level import by sqlalchemy)
|
||||
W: no module named openlp.plugins.bibles.lib.BiblesTab (top-level import by openlp.plugins.bibles.bibleplugin)
|
||||
W: no module named PyQt4._qt (top-level import by PyQt4.QtCore)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.lib.alertstab)
|
||||
W: no module named sqlalchemy.Column (top-level import by openlp.plugins.custom.lib.db)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songusage.songusageplugin)
|
||||
W: no module named openlp.plugins.alerts.lib.AlertsManager (top-level import by openlp.plugins.alerts.alertsplugin)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.generaltab)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.forms.alertdialog)
|
||||
W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named sqlalchemy.orm.MapperExtension (top-level import by sqlalchemy.orm.scoping)
|
||||
W: no module named pyodbc (delayed import by sqlalchemy.databases.access)
|
||||
W: no module named openlp.core.lib.expand_tags (top-level import by openlp.core.lib.renderer)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.dynamic)
|
||||
W: no module named ctypes._SimpleCData (top-level import by ctypes.wintypes)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.core.ui.generaltab)
|
||||
W: no module named simplejson (conditional import by openlp.plugins.remotes.lib.httpserver)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.alerts.forms.alertdialog)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.collections)
|
||||
W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.lib.serviceitem)
|
||||
W: no module named openlp.plugins.songs.lib.SongXMLParser (top-level import by openlp.plugins.songs.forms.editsongform)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.bibleplugin)
|
||||
W: no module named xml.dom.XMLNS_NAMESPACE (top-level import by xml.dom.minidom)
|
||||
W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.lib.songimport)
|
||||
W: no module named openlp.plugins.songs.lib.SongXMLBuilder (top-level import by openlp.plugins.songs.forms.editsongform)
|
||||
W: no module named openlp.core.ui.GeneralTab (top-level import by openlp.core.ui.settingsform)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named informixdb (delayed import by sqlalchemy.databases.informix)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.custom.customplugin)
|
||||
W: no module named cjkcodecs (top-level import by BeautifulSoup)
|
||||
W: no module named readline (delayed, conditional import by cmd)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.lib.songimport)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.media.mediaplugin)
|
||||
W: no module named openlp.core.lib.ThemeXML (top-level import by openlp.core.ui.amendthemeform)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.manager)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.ui.maindisplay)
|
||||
W: no module named openlp.plugins.songs.forms.EditVerseForm (top-level import by openlp.plugins.songs.forms.editsongform)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.ewimport)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.songs.lib.songstab)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.ui.HideMode (top-level import by openlp.core.ui.maindisplay)
|
||||
W: no module named sqlalchemy.Column (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.forms.songimportform)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.aboutdialog)
|
||||
W: no module named sqlalchemy.sql.insert (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.str_to_bool (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named sqlalchemy.MetaData (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.biblestab)
|
||||
W: no module named openlp.plugins.bibles.lib.BibleManager (top-level import by openlp.plugins.bibles.bibleplugin)
|
||||
W: no module named openlp.core.ui.SlideController (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named MacOS (delayed import by platform)
|
||||
W: no module named openlp.core.lib.ThemeXML (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named cx_Oracle (delayed import by sqlalchemy.databases.oracle)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.servicenotedialog)
|
||||
W: no module named sqlalchemy.sql.except_ (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.ui.AboutForm (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named EasyDialogs (conditional import by getpass)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named sqlalchemy.orm.SessionExtension (top-level import by sqlalchemy.orm.session)
|
||||
W: no module named sqlalchemy.orm.relation (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.forms.editsongform)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.lib.http)
|
||||
W: no module named sqlalchemy.sql.func (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.utils.languagemanager)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named uno (conditional import by openlp.plugins.songs.lib.oooimport)
|
||||
W: no module named kinterbasdb (delayed import by sqlalchemy.databases.firebird)
|
||||
W: no module named multiprocessing.RLock (top-level import by multiprocessing.sharedctypes)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.filerenameform)
|
||||
W: no module named sqlalchemy.ForeignKey (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.lib.Renderer (top-level import by openlp.core.lib.rendermanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songmaintenancedialog)
|
||||
W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named openlp.core.ui.FileRenameForm (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.songsplugin)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.bibles.bibleplugin)
|
||||
W: no module named vms_lib (delayed, conditional import by platform)
|
||||
W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.alerts.lib.alertsmanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedetaildialog)
|
||||
W: no module named openlp.plugins.remotes.lib.RemoteTab (top-level import by openlp.plugins.remotes.remoteplugin)
|
||||
W: no module named openlp.core.ui.ServiceManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.songusage.forms.songusagedetailform)
|
||||
W: no module named openlp.core.ui.SettingsForm (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.plugins.alerts.lib.AlertsTab (top-level import by openlp.plugins.alerts.alertsplugin)
|
||||
W: no module named xdg (delayed, conditional import by openlp.core.utils)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.custom.customplugin)
|
||||
W: no module named openlp.core.ui.AmendThemeForm (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named posix (delayed, conditional import by iu)
|
||||
W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.forms.editversedialog)
|
||||
W: no module named multiprocessing.dummy.Process (delayed import by __main__)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named sqlalchemy.String (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named xml.dom.EMPTY_PREFIX (top-level import by xml.dom.expatbuilder)
|
||||
W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named openlp.core.lib.PluginManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named multiprocessing.current_process (top-level import by multiprocessing.reduction)
|
||||
W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songbookform)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named xmltok (top-level import by pyexpat)
|
||||
W: no module named openlp.plugins.bibles.lib.SearchResults (top-level import by openlp.plugins.bibles.lib.http)
|
||||
W: no module named sqlalchemy.sql.delete (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.lib.oooimport)
|
||||
W: no module named _emx_link (conditional import by os)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.aboutdialog)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.bibles.forms.bibleimportwizard)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.core.lib.pluginmanager)
|
||||
W: no module named openlp.plugins.songs.lib.SongsTab (top-level import by openlp.plugins.songs.songsplugin)
|
||||
W: no module named sqlalchemy.CHAR (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named sqlalchemy.sql.collate (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.sql.outparam (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.lib.db)
|
||||
W: no module named openlp.core.ui.PluginForm (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named gobject (top-level import by enchant.checker.GtkSpellCheckerDialog)
|
||||
W: no module named openlp.core.utils.VersionThread (top-level import by __main__)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.topicsform)
|
||||
W: no module named sqlalchemy.Integer (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.exceptiondialog)
|
||||
W: no module named pwd (delayed, conditional import by distutils.util)
|
||||
W: no module named uno (conditional import by openlp.plugins.presentations.lib.impresscontroller)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.utils)
|
||||
W: no module named sqlalchemy.orm.class_mapper (top-level import by openlp.plugins.songs.lib.olpimport)
|
||||
W: no module named sqlalchemy.orm.relation (top-level import by openlp.plugins.songs.lib.olpimport)
|
||||
W: no module named readline (delayed import by pdb)
|
||||
W: no module named openlp.core.ui.MainDisplay (top-level import by openlp.core.lib.rendermanager)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named sqlalchemy.Table (top-level import by openlp.plugins.songusage.lib.db)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.alertsplugin)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.forms.importwizardform)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.remotes.remoteplugin)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.images.imageplugin)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.alerts.lib.alertstab)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.editversedialog)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songusage.songusageplugin)
|
||||
W: no module named openlp.core.ui.HideMode (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named sqlalchemy.sql.between (top-level import by sqlalchemy)
|
||||
W: no module named xml.dom.EMPTY_PREFIX (top-level import by xml.dom.minidom)
|
||||
W: no module named pysqlite2 (delayed import by sqlalchemy.databases.sqlite)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.lib.customtab)
|
||||
W: no module named gtk (top-level import by enchant.checker.GtkSpellCheckerDialog)
|
||||
W: no module named xml.dom.EMPTY_NAMESPACE (top-level import by xml.dom.expatbuilder)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.remotes.lib.httpserver)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedeleteform)
|
||||
W: no module named sqlalchemy.orm.scoped_session (top-level import by openlp.core.lib.db)
|
||||
W: no module named openlp.core.lib.clean_tags (top-level import by openlp.core.lib.serviceitem)
|
||||
W: no module named openlp.core.utils.get_filesystem_encoding (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named xml.dom.EMPTY_NAMESPACE (top-level import by xml.dom.minidom)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.lib.toolbar)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.remotes.remoteplugin)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.attributes)
|
||||
W: no module named sqlalchemy.ForeignKey (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named sqlalchemy.Column (top-level import by openlp.plugins.alerts.lib.db)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.core.ui.advancedtab)
|
||||
W: no module named AES (delayed, conditional import by archive)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.forms.songmaintenanceform)
|
||||
W: no module named openlp.core.lib.context_menu_separator (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named fcntl (top-level import by tempfile)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named mx (top-level import by sqlalchemy.databases.mxODBC)
|
||||
W: no module named sqlalchemy.sql.union (top-level import by sqlalchemy)
|
||||
W: no module named openlp.plugins.songs.forms.TopicsForm (top-level import by openlp.plugins.songs.forms.songmaintenanceform)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named MacOS (delayed import by distutils.sysconfig)
|
||||
W: no module named openlp.core.lib.SpellTextEdit (top-level import by openlp.plugins.custom.forms.editcustomdialog)
|
||||
W: no module named ic (top-level import by webbrowser)
|
||||
W: no module named com (conditional import by openlp.plugins.presentations.lib.impresscontroller)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.media.mediaplugin)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.forms.editcustomform)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.lib.spelltextedit)
|
||||
W: no module named openlp.core.lib.html_expands (top-level import by openlp.core.lib.spelltextedit)
|
||||
W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named sqlalchemy.Column (top-level import by openlp.plugins.songs.lib.db)
|
||||
W: no module named py2exe (delayed import by enchant.tests)
|
||||
W: no module named openlp.plugins.songs.forms.AuthorsForm (top-level import by openlp.plugins.songs.forms.songmaintenanceform)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.authorsform)
|
||||
W: no module named openlp.plugins.remotes.lib.HttpServer (top-level import by openlp.plugins.remotes.remoteplugin)
|
||||
W: no module named sqlalchemy.Table (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.remotes.remoteplugin)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.filerenamedialog)
|
||||
W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named sapdb (delayed import by sqlalchemy.databases.maxdb)
|
||||
W: no module named ctypes.cdll (delayed import by ctypes.util)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.presentations.lib.presentationtab)
|
||||
W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named sqlalchemy.sql.text (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.image_to_byte (top-level import by openlp.core.lib.renderer)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.forms.importwizardform)
|
||||
W: no module named openlp.core.lib.image_to_byte (top-level import by openlp.core.ui.maindisplay)
|
||||
W: no module named iconv_codec (top-level import by BeautifulSoup)
|
||||
W: no module named openlp.plugins.songs.forms.SongBookForm (top-level import by openlp.plugins.songs.forms.songmaintenanceform)
|
||||
W: no module named sqlalchemy.sql.not_ (top-level import by sqlalchemy)
|
||||
W: no module named multiprocessing.Pipe (top-level import by multiprocessing.queues)
|
||||
W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedetailform)
|
||||
W: no module named sqlalchemy.sql.subquery (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.songsplugin)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.editsongdialog)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.bibles.bibleplugin)
|
||||
W: no module named openlp.plugins.songs.forms.SongMaintenanceForm (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named xmlparse (top-level import by pyexpat)
|
||||
W: no module named sqlalchemy.sql.exists (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.sql.and_ (top-level import by openlp.plugins.songs.forms.songmaintenanceform)
|
||||
W: no module named multiprocessing.Process (top-level import by multiprocessing.pool)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.settingsdialog)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by openlp.core.lib.db)
|
||||
W: no module named sqlalchemy.sql.outerjoin (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.editsongdialog)
|
||||
W: no module named openlp.plugins.custom.lib.CustomXMLParser (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.custom.forms.editcustomdialog)
|
||||
W: no module named sqlalchemy.Integer (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.properties)
|
||||
W: no module named multiprocessing.current_process (top-level import by multiprocessing.managers)
|
||||
W: no module named openlp.core.ui.SplashScreen (top-level import by __main__)
|
||||
W: no module named multiprocessing.TimeoutError (top-level import by multiprocessing.dummy)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.songs.forms.songimportform)
|
||||
W: no module named xml.dom.XMLNS_NAMESPACE (top-level import by xml.dom.expatbuilder)
|
||||
W: no module named ctypes.c_int32 (delayed import by urllib)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.amendthemedialog)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.lib.serviceitem)
|
||||
W: no module named openlp.core.utils.LanguageManager (top-level import by __main__)
|
||||
W: no module named sqlalchemy.orm.object_mapper (top-level import by sqlalchemy.orm.properties)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.utils.languagemanager)
|
||||
W: no module named sqlalchemy.sql.literal_column (top-level import by sqlalchemy)
|
||||
W: no module named openlp.plugins.songs.lib.SongXMLParser (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named ctypes.c_char_p (delayed import by urllib)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.images.imageplugin)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.remotes.lib.remotetab)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.opensong)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songimportform)
|
||||
W: no module named sqlalchemy.sql.select (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songbookdialog)
|
||||
W: no module named openlp.plugins.bibles.lib.BibleMediaItem (top-level import by openlp.plugins.bibles.bibleplugin)
|
||||
W: no module named PyQt4._qt (top-level import by PyQt4.QtNetwork)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.songs.songsplugin)
|
||||
W: no module named sqlalchemy.sql.case (top-level import by sqlalchemy)
|
||||
W: no module named wx (top-level import by enchant.checker.wxSpellCheckerDialog)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.alerts.alertsplugin)
|
||||
W: no module named com (conditional import by openlp.plugins.songs.lib.sofimport)
|
||||
W: no module named PyQt4._qt (top-level import by PyQt4)
|
||||
W: no module named SOCKS (top-level import by ftplib)
|
||||
W: no module named openlp.plugins.songusage.forms.SongUsageDetailForm (top-level import by openlp.plugins.songusage.songusageplugin)
|
||||
W: no module named sqlalchemy.sql.null (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.MetaData (top-level import by openlp.core.lib.db)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.plugins.custom.forms.EditCustomForm (top-level import by openlp.plugins.custom.customplugin)
|
||||
W: no module named org (delayed import by xml.sax)
|
||||
W: no module named openlp.core.lib.SpellTextEdit (top-level import by openlp.plugins.songs.forms.editversedialog)
|
||||
W: no module named sqlalchemy.orm.EXT_CONTINUE (top-level import by sqlalchemy.orm.scoping)
|
||||
W: no module named openlp.core.lib.build_lyrics_outline_css (top-level import by openlp.core.lib.renderer)
|
||||
W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.forms.editverseform)
|
||||
W: no module named com (conditional import by openlp.plugins.songs.lib.oooimport)
|
||||
W: no module named openlp.core.lib.str_to_bool (top-level import by openlp.core.lib.theme)
|
||||
W: no module named sqlalchemy.sql.literal (top-level import by sqlalchemy)
|
||||
W: no module named termios (top-level import by getpass)
|
||||
W: no module named openlp.core.lib.build_lyrics_format_css (top-level import by openlp.core.lib.renderer)
|
||||
W: no module named ctypes.byref (delayed import by urllib)
|
||||
W: no module named openlp.plugins.custom.lib.CustomTab (top-level import by openlp.plugins.custom.customplugin)
|
||||
W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named openlp.plugins.bibles.lib.parse_reference (top-level import by openlp.plugins.bibles.lib.manager)
|
||||
W: no module named java (delayed import by platform)
|
||||
W: no module named openlp.core.ui.ServiceItemEditForm (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.customplugin)
|
||||
W: no module named openlp.core.lib.ThemeLevel (top-level import by openlp.core.lib.rendermanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named _xmlrpclib (top-level import by xmlrpclib)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named openlp.plugins.media.lib.MediaMediaItem (top-level import by openlp.plugins.media.mediaplugin)
|
||||
W: no module named openlp.plugins.custom.lib.CustomXMLBuilder (top-level import by openlp.plugins.custom.forms.editcustomform)
|
||||
W: no module named rourl2path (conditional import by urllib)
|
||||
W: no module named pwd (delayed import by webbrowser)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.themestab)
|
||||
W: no module named PyQt4._qt (top-level import by PyQt4.QtWebKit)
|
||||
W: no module named sqlalchemy.orm.class_mapper (delayed, conditional import by sqlalchemy.orm.interfaces)
|
||||
W: no module named PyQt4._qt (top-level import by PyQt4.phonon)
|
||||
W: no module named openlp.core.ui.HideMode (top-level import by openlp.plugins.presentations.lib.messagelistener)
|
||||
W: no module named openlp.plugins.songusage.forms.SongUsageDeleteForm (top-level import by openlp.plugins.songusage.songusageplugin)
|
||||
W: no module named openlp.core.lib.context_menu_separator (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.plugindialog)
|
||||
W: no module named fcntl (conditional import by subprocess)
|
||||
W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.bibles.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.PluginStatus (top-level import by openlp.core.lib.pluginmanager)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.forms.editsongform)
|
||||
W: no module named openlp.core.ui.ScreenList (top-level import by __main__)
|
||||
W: no module named sqlalchemy.or_ (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.editsongform)
|
||||
W: no module named openlp.plugins.songs.forms.ImportWizardForm (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.ui.ThemeManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named pyodbc (delayed, conditional import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.biblestab)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.songusageplugin)
|
||||
W: no module named multiprocessing.active_children (top-level import by multiprocessing.managers)
|
||||
W: no module named openlp.plugins.songs.forms.EditSongForm (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named email.Generator (delayed import by email.message)
|
||||
W: no module named mx (delayed import by sqlalchemy.databases.mxODBC)
|
||||
W: no module named sqlalchemy.sql.or_ (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.Table (top-level import by openlp.plugins.custom.lib.db)
|
||||
W: no module named sqlalchemy.Table (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named openlp.core.lib.get_text_file_string (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named sqlalchemy.orm.object_session (top-level import by sqlalchemy.orm.scoping)
|
||||
W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.bibles.lib.mediaitem)
|
||||
W: no module named sqlalchemy.Table (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.forms.bibleimportwizard)
|
||||
W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.lib.renderer)
|
||||
W: no module named pymssql (delayed import by sqlalchemy.databases.mssql)
|
||||
W: no module named sqlalchemy.orm.sessionmaker (top-level import by openlp.plugins.songs.lib.olpimport)
|
||||
W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.expand_tags (top-level import by openlp.core.lib.serviceitem)
|
||||
W: no module named gestalt (delayed import by platform)
|
||||
W: no module named enchant.checker.SpellChecker (top-level import by enchant.checker.CmdLineChecker)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.themestab)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.olp1import)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.messagelistener)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.interfaces)
|
||||
W: no module named sqlalchemy.orm.object_mapper (top-level import by sqlalchemy.orm.query)
|
||||
W: no module named sqlalchemy.sql.distinct (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named sqlalchemy.sql.extract (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.Column (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named psycopg2 (delayed import by sqlalchemy.databases.postgres)
|
||||
W: no module named enchant.checker.SpellChecker (delayed import by enchant.checker.GtkSpellCheckerDialog)
|
||||
W: no module named clr (conditional import by adodbapi.adodbapi)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named openlp.plugins.custom.lib.CustomXMLParser (top-level import by openlp.plugins.custom.forms.editcustomform)
|
||||
W: no module named openlp.core.theme.Theme (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.custom.forms.editcustomform)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.lib.settingsmanager)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by __main__)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.bibles.lib.manager)
|
||||
W: no module named org (top-level import by pickle)
|
||||
W: no module named enchant.DictNotFoundError (top-level import by openlp.core.lib.spelltextedit)
|
||||
W: no module named sqlalchemy.sql.except_all (top-level import by sqlalchemy)
|
||||
W: no module named openlp.plugins.presentations.lib.PresentationTab (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named sqlalchemy.sql.cast (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.orm.relation (top-level import by openlp.plugins.songs.lib.db)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.settingsdialog)
|
||||
W: no module named openlp.core.utils.LanguageManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named sqlalchemy.sql.intersect (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.songimport)
|
||||
W: no module named sqlalchemy.orm.class_mapper (top-level import by sqlalchemy.orm.scoping)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.util)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.opensongimport)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.bibles.lib.biblestab)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.aboutform)
|
||||
W: no module named openlp.plugins.custom.lib.CustomMediaItem (top-level import by openlp.plugins.custom.customplugin)
|
||||
W: no module named sqlalchemy.orm.scoped_session (top-level import by openlp.plugins.songs.lib.olpimport)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.amendthemeform)
|
||||
W: no module named sqlalchemy.engine.engine_from_config (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.core.ui.themestab)
|
||||
W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.maindisplay)
|
||||
W: no module named openlp.core.lib.PluginStatus (top-level import by openlp.core.ui.pluginform)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.http)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.remotes.lib.httpserver)
|
||||
W: no module named sqlalchemy.Table (top-level import by openlp.plugins.songs.lib.db)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.utils)
|
||||
W: no module named openlp.core.lib.RenderManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.alerts.alertsplugin)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.lib.plugin)
|
||||
W: no module named sqlalchemy.ForeignKey (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named openlp.plugins.songs.lib.SongMediaItem (top-level import by openlp.plugins.songs.songsplugin)
|
||||
W: no module named sqlalchemy.Index (top-level import by openlp.plugins.songs.lib.db)
|
||||
W: no module named multiprocessing.TimeoutError (top-level import by multiprocessing.pool)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songusage.forms.songusagedetaildialog)
|
||||
W: no module named enchant.DictWithPWL (delayed import by enchant.checker.tests)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.songstab)
|
||||
W: no module named openlp.core.ui.AdvancedTab (top-level import by openlp.core.ui.settingsform)
|
||||
W: no module named MySQLdb (delayed import by sqlalchemy.databases.mysql)
|
||||
W: no module named openlp.plugins.presentations.lib.PresentationMediaItem (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named openlp.plugins.alerts.forms.AlertForm (top-level import by openlp.plugins.alerts.alertsplugin)
|
||||
W: no module named ctypes.c_int (delayed import by urllib)
|
||||
W: no module named xml.dom.XML_NAMESPACE (delayed import by xml.dom.pulldom)
|
||||
W: no module named ctypes.c_void_p (delayed import by urllib)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.lib.osis)
|
||||
W: no module named sqlalchemy.create_engine (top-level import by openlp.core.lib.db)
|
||||
W: no module named win32com.client._get_good_object_ (top-level import by win32com.client.util)
|
||||
W: no module named openlp.core.ui.MainDisplay (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named openlp.core.lib.resize_image (top-level import by openlp.plugins.presentations.lib.presentationcontroller)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.remotes.lib.remotetab)
|
||||
W: no module named openlp.core.ui.MediaDockManager (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.session)
|
||||
W: no module named sqlalchemy.Column (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.editversedialog)
|
||||
W: no module named multiprocessing.Process (top-level import by multiprocessing.managers)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.presentationcontroller)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.forms.editcustomdialog)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.lib.alertsmanager)
|
||||
W: no module named sgmlop (top-level import by xmlrpclib)
|
||||
W: no module named MacOS (conditional import by py_compile)
|
||||
W: no module named multiprocessing.cpu_count (top-level import by multiprocessing.dummy)
|
||||
W: no module named _dummy_threading (top-level import by dummy_threading)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songmaintenanceform)
|
||||
W: no module named openlp.plugins.presentations.lib.PresentationController (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named sqlalchemy.sql.union_all (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.opensong)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.bibles.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.osis)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.settingsform)
|
||||
W: no module named enchant.tokenize.get_tokenizer (top-level import by enchant.checker)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.lib.manager)
|
||||
W: no module named org (top-level import by copy)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named sqlalchemy.MetaData (top-level import by openlp.plugins.songs.lib.olpimport)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.songmaintenancedialog)
|
||||
W: no module named sqlalchemy.sql.select (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.bibles.forms.importwizardform)
|
||||
W: no module named multiprocessing.current_process (top-level import by multiprocessing.connection)
|
||||
W: no module named sqlalchemy.orm.sessionmaker (top-level import by openlp.core.lib.db)
|
||||
W: no module named sqlalchemy.sql.desc (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedeletedialog)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.mediaitem)
|
||||
W: no module named ctypes.cdll (delayed import by urllib)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.media.mediaplugin)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.presentations.lib.presentationtab)
|
||||
W: no module named MySQLdb (delayed, conditional import by sqlalchemy.databases.mysql)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named sqlalchemy.orm.object_session (top-level import by sqlalchemy.orm.dynamic)
|
||||
W: no module named sqlalchemy.sql.modifier (top-level import by sqlalchemy)
|
||||
W: no module named _xmlplus (top-level import by xml)
|
||||
W: no module named sqlalchemy.Column (top-level import by openlp.plugins.songusage.lib.db)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.advancedtab)
|
||||
W: no module named sqlalchemy.sql.and_ (top-level import by sqlalchemy)
|
||||
W: no module named sqlalchemy.MetaData (top-level import by sqlalchemy.databases.mssql)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.dependency)
|
||||
W: no module named openlp.core.lib.ThemeLevel (top-level import by openlp.core.ui.themestab)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.presentationtab)
|
||||
W: no module named openlp.core.utils.get_images_filter (top-level import by openlp.core.ui.amendthemeform)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.presentations.presentationplugin)
|
||||
W: no module named openlp.plugins.presentations.lib.MessageListener (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named openlp.plugins.bibles.forms.ImportWizardForm (top-level import by openlp.plugins.bibles.lib.mediaitem)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by __main__)
|
||||
W: no module named sqlalchemy.ForeignKey (top-level import by openlp.plugins.songs.lib.db)
|
||||
W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named ctypes.cdll (conditional import by openlp.plugins.presentations.lib.pptviewcontroller)
|
||||
W: no module named pwd (delayed import by getpass)
|
||||
W: no module named sqlalchemy.sql.and_ (top-level import by openlp.plugins.songusage.forms.songusagedetailform)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.amendthemedialog)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.songimportwizard)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.serviceitemeditdialog)
|
||||
W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.ui.maindisplay)
|
||||
W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.custom.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.topicsdialog)
|
||||
W: no module named PyQt4._qt (top-level import by PyQt4.QtGui)
|
||||
W: no module named sqlalchemy.sql.update (top-level import by sqlalchemy)
|
||||
W: no module named multiprocessing.current_process (delayed, conditional import by logging)
|
||||
W: no module named multiprocessing.Pool (top-level import by multiprocessing.managers)
|
||||
W: no module named sqlalchemy.create_engine (delayed, conditional import by sqlalchemy.schema)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.forms.importwizardform)
|
||||
W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.lib.mediamanageritem)
|
||||
W: no module named posix (conditional import by os)
|
||||
W: no module named sqlalchemy.sql.bindparam (top-level import by sqlalchemy)
|
||||
W: no module named xml.dom.DOMImplementation (top-level import by xml.dom.domreg)
|
||||
W: no module named openlp.core.utils.add_actions (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named sqlalchemy.create_engine (top-level import by openlp.plugins.songs.lib.olpimport)
|
||||
W: no module named multiprocessing.cpu_count (top-level import by multiprocessing.pool)
|
||||
W: no module named multiprocessing.AuthenticationError (top-level import by multiprocessing.connection)
|
||||
W: no module named openlp.core.ui.ThemesTab (top-level import by openlp.core.ui.settingsform)
|
||||
W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.media.lib.mediaitem)
|
||||
W: no module named sqlalchemy.orm.class_mapper (top-level import by openlp.plugins.bibles.lib.db)
|
||||
W: no module named sqlalchemy.String (top-level import by sqlalchemy.databases.sybase)
|
||||
W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named pwd (delayed, conditional import by posixpath)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.strategies)
|
||||
W: no module named mx (top-level import by adodbapi.adodbapi)
|
||||
W: no module named sqlalchemy.sql.alias (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.authorsdialog)
|
||||
W: no module named sqlalchemy.Table (top-level import by openlp.plugins.alerts.lib.db)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.images.imageplugin)
|
||||
W: no module named sqlalchemy.orm.mapperlib (delayed import by sqlalchemy.orm.util)
|
||||
W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.lib.rendermanager)
|
||||
W: no module named openlp.core.lib.OpenLPDockWidget (top-level import by openlp.core.ui.mainwindow)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songimportwizard)
|
||||
W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.songusage.songusageplugin)
|
||||
W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.presentations.lib.presentationcontroller)
|
||||
W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.lib.spelltextedit)
|
||||
W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.thememanager)
|
||||
W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.pluginform)
|
||||
W: no module named enchant.checker.SpellChecker (delayed import by enchant.checker.wxSpellCheckerDialog)
|
||||
W: no module named sqlalchemy.DefaultClause (top-level import by sqlalchemy.databases.sqlite)
|
||||
W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named openlp.core.utils.get_images_filter (top-level import by openlp.plugins.images.lib.mediaitem)
|
||||
W: no module named pyodbc (delayed import by sqlalchemy.databases.mssql)
|
||||
W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.ui.slidecontroller)
|
||||
W: no module named System (conditional import by adodbapi.adodbapi)
|
||||
W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.custom.lib.customtab)
|
||||
W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.csvbible)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.generaltab)
|
||||
W: no module named openlp.core.lib.ThemeLevel (top-level import by openlp.core.ui.servicemanager)
|
||||
W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.scoping)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.forms.alertform)
|
||||
W: no module named mypyodbc (delayed import by sqlalchemy.databases.sybase)
|
||||
W: no module named sqlalchemy.sql.intersect_all (top-level import by sqlalchemy)
|
||||
W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.presentations.lib.mediaitem)
|
||||
W: __all__ is built strangely at line 0 - dummy_threading (C:\Python26\lib\dummy_threading.pyc)
|
||||
W: delayed exec statement detected at line 0 - bdb (C:\Python26\lib\bdb.pyc)
|
||||
W: delayed eval hack detected at line 0 - bdb (C:\Python26\lib\bdb.pyc)
|
||||
W: delayed eval hack detected at line 0 - bdb (C:\Python26\lib\bdb.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - optparse (C:\Python26\lib\optparse.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc)
|
||||
W: delayed conditional exec statement detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - doctest (C:\Python26\lib\doctest.pyc)
|
||||
W: delayed exec statement detected at line 0 - doctest (C:\Python26\lib\doctest.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - doctest (C:\Python26\lib\doctest.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.orm.interfaces (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\interfaces.pyc)
|
||||
W: __all__ is built strangely at line 0 - tokenize (C:\Python26\lib\tokenize.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.engine (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\engine\__init__.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - pickle (C:\Python26\lib\pickle.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - pickle (C:\Python26\lib\pickle.pyc)
|
||||
W: top-level conditional exec statement detected at line 0 - sqlalchemy.sql.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\sql\util.pyc)
|
||||
W: top-level conditional exec statement detected at line 0 - sqlalchemy.sql.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\sql\util.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - openlp.core.lib.pluginmanager (c:\Documents and Settings\raoul\My Documents\My Projects\openlp\movements\openlp\core\lib\pluginmanager.pyc)
|
||||
W: delayed conditional exec statement detected at line 0 - multiprocessing.sharedctypes (C:\Python26\lib\multiprocessing\sharedctypes.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - encodings (C:\Python26\lib\encodings\__init__.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.databases.mysql (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\databases\mysql.pyc)
|
||||
W: delayed exec statement detected at line 0 - sqlalchemy.orm.attributes (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\attributes.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - openlp.plugins.presentations.presentationplugin (c:\Documents and Settings\raoul\My Documents\My Projects\openlp\movements\openlp\plugins\presentations\presentationplugin.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - enchant.tokenize (C:\Python26\lib\site-packages\enchant\tokenize\__init__.pyc)
|
||||
W: __all__ is built strangely at line 0 - multiprocessing (C:\Python26\lib\multiprocessing\__init__.pyc)
|
||||
W: __all__ is built strangely at line 0 - dis (C:\Python26\lib\dis.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.databases (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\databases\__init__.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - win32com.server.policy (C:\Python26\lib\site-packages\win32com\server\policy.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.orm.mapper (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\mapper.pyc)
|
||||
W: top-level exec statement detected at line 0 - hashlib (C:\Python26\lib\hashlib.pyc)
|
||||
W: top-level conditional exec statement detected at line 0 - hashlib (C:\Python26\lib\hashlib.pyc)
|
||||
W: delayed conditional eval hack detected at line 0 - warnings (C:\Python26\lib\warnings.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - warnings (C:\Python26\lib\warnings.pyc)
|
||||
W: delayed exec statement detected at line 0 - cgi (C:\Python26\lib\cgi.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - email (C:\Python26\lib\email\__init__.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.orm (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\__init__.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - ctypes (C:\Python26\lib\ctypes\__init__.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - ctypes (C:\Python26\lib\ctypes\__init__.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - xml.dom.domreg (C:\Python26\lib\xml\dom\domreg.pyc)
|
||||
W: delayed exec statement detected at line 0 - pdb (C:\Python26\lib\pdb.pyc)
|
||||
W: delayed conditional eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc)
|
||||
W: delayed eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc)
|
||||
W: delayed conditional eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc)
|
||||
W: delayed eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - unittest (C:\Python26\lib\unittest.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - unittest (C:\Python26\lib\unittest.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - pkgutil (C:\Python26\lib\pkgutil.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - pkgutil (C:\Python26\lib\pkgutil.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.orm.properties (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\properties.pyc)
|
||||
W: delayed conditional exec statement detected at line 0 - iu (c:\Documents and Settings\raoul\My Documents\My Projects\pyinstaller\iu.pyc)
|
||||
W: delayed conditional exec statement detected at line 0 - iu (c:\Documents and Settings\raoul\My Documents\My Projects\pyinstaller\iu.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy.sql (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\sql\__init__.pyc)
|
||||
W: __all__ is built strangely at line 0 - collections (C:\Python26\lib\collections.pyc)
|
||||
W: delayed exec statement detected at line 0 - collections (C:\Python26\lib\collections.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - sqlalchemy.engine.url (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\engine\url.pyc)
|
||||
W: delayed exec statement detected at line 0 - multiprocessing.managers (C:\Python26\lib\multiprocessing\managers.pyc)
|
||||
W: delayed exec statement detected at line 0 - socket (C:\Python26\lib\socket.pyc)
|
||||
W: delayed conditional __import__ hack detected at line 0 - win32com.client.gencache (C:\Python26\lib\site-packages\win32com\client\gencache.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - win32com.client.gencache (C:\Python26\lib\site-packages\win32com\client\gencache.pyc)
|
||||
W: delayed eval hack detected at line 0 - os (C:\Python26\lib\os.pyc)
|
||||
W: __all__ is built strangely at line 0 - __future__ (C:\Python26\lib\__future__.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - win32com.client.makepy (C:\Python26\lib\site-packages\win32com\client\makepy.pyc)
|
||||
W: delayed exec statement detected at line 0 - win32com.client.dynamic (C:\Python26\lib\site-packages\win32com\client\dynamic.pyc)
|
||||
W: __all__ is built strangely at line 0 - sqlalchemy (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\__init__.pyc)
|
||||
W: delayed __import__ hack detected at line 0 - xml.sax (C:\Python26\lib\xml\sax\__init__.pyc)
|
||||
W: delayed eval hack detected at line 0 - gettext (C:\Python26\lib\gettext.pyc)
|
||||
W: delayed eval hack detected at line 0 - sqlalchemy.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\util.pyc)
|
||||
W: delayed exec statement detected at line 0 - sqlalchemy.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\util.pyc)
|
@ -63,6 +63,7 @@ IGNORED_PATHS = [u'scripts']
|
||||
IGNORED_FILES = [u'setup.py']
|
||||
|
||||
verbose_mode = False
|
||||
quiet_mode = False
|
||||
|
||||
class Command(object):
|
||||
"""
|
||||
@ -128,6 +129,20 @@ class CommandStack(object):
|
||||
results.append(str((item[u'command'], )))
|
||||
return u'[%s]' % u', '.join(results)
|
||||
|
||||
def print_quiet(text, linefeed=True):
|
||||
"""
|
||||
This method checks to see if we are in quiet mode, and if not prints
|
||||
``text`` out.
|
||||
|
||||
``text``
|
||||
The text to print.
|
||||
"""
|
||||
global quiet_mode
|
||||
if not quiet_mode:
|
||||
if linefeed:
|
||||
print text
|
||||
else:
|
||||
print text,
|
||||
|
||||
def print_verbose(text):
|
||||
"""
|
||||
@ -137,8 +152,8 @@ def print_verbose(text):
|
||||
``text``
|
||||
The text to print.
|
||||
"""
|
||||
global verbose_mode
|
||||
if verbose_mode:
|
||||
global verbose_mode, quiet_mode
|
||||
if not quiet_mode and verbose_mode:
|
||||
print u' %s' % text
|
||||
|
||||
def run(command):
|
||||
@ -155,7 +170,6 @@ def run(command):
|
||||
print_verbose(u'ReadyRead: %s' % QtCore.QString(process.readAll()))
|
||||
print_verbose(u'Error(s):\n%s' % process.readAllStandardError())
|
||||
print_verbose(u'Output:\n%s' % process.readAllStandardOutput())
|
||||
print u' Done.'
|
||||
|
||||
def update_export_at_pootle(source_filename):
|
||||
"""
|
||||
@ -194,7 +208,7 @@ def download_translations():
|
||||
"""
|
||||
This method downloads the translation files from the Pootle server.
|
||||
"""
|
||||
print 'Download translation files from Pootle'
|
||||
print_quiet(u'Download translation files from Pootle')
|
||||
page = urllib.urlopen(SERVER_URL)
|
||||
soup = BeautifulSoup(page)
|
||||
languages = soup.findAll(text=re.compile(r'.*\.ts'))
|
||||
@ -205,14 +219,14 @@ def download_translations():
|
||||
language_file)
|
||||
print_verbose(u'Get Translation File: %s' % filename)
|
||||
download_file(language_file, filename)
|
||||
print u' Done.'
|
||||
print_quiet(u' Done.')
|
||||
|
||||
def prepare_project():
|
||||
"""
|
||||
This method creates the project file needed to update the translation files
|
||||
and compile them into .qm files.
|
||||
"""
|
||||
print u'Generating the openlp.pro file'
|
||||
print_quiet(u'Generating the openlp.pro file')
|
||||
lines = []
|
||||
start_dir = os.path.abspath(u'..')
|
||||
start_dir = start_dir + os.sep
|
||||
@ -251,10 +265,10 @@ def prepare_project():
|
||||
file = open(os.path.join(start_dir, u'openlp.pro'), u'w')
|
||||
file.write(u'\n'.join(lines).encode('utf8'))
|
||||
file.close()
|
||||
print u' Done.'
|
||||
print_quiet(u' Done.')
|
||||
|
||||
def update_translations():
|
||||
print u'Update the translation files'
|
||||
print_quiet(u'Update the translation files')
|
||||
if not os.path.exists(os.path.join(os.path.abspath(u'..'), u'openlp.pro')):
|
||||
print u'You have no generated a project file yet, please run this ' + \
|
||||
u'script with the -p option.'
|
||||
@ -265,7 +279,7 @@ def update_translations():
|
||||
os.chdir(os.path.abspath(u'scripts'))
|
||||
|
||||
def generate_binaries():
|
||||
print u'Generate the related *.qm files'
|
||||
print_quiet(u'Generate the related *.qm files')
|
||||
if not os.path.exists(os.path.join(os.path.abspath(u'..'), u'openlp.pro')):
|
||||
print u'You have not generated a project file yet, please run this ' + \
|
||||
u'script with the -p option. It is also recommended that you ' + \
|
||||
@ -285,6 +299,7 @@ def generate_binaries():
|
||||
if re.search('.qm$', file):
|
||||
copy(os.path.join(src_path, u'%s' % file),
|
||||
os.path.join(dest_path, u'%s' % file))
|
||||
print_quiet(u' Done.')
|
||||
|
||||
|
||||
def create_translation(language):
|
||||
@ -294,17 +309,17 @@ def create_translation(language):
|
||||
``language``
|
||||
The language file to create.
|
||||
"""
|
||||
print "Create new Translation File"
|
||||
print_quiet(u'Create new Translation File')
|
||||
if not language.endswith(u'.ts'):
|
||||
language += u'.ts'
|
||||
filename = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n', language)
|
||||
download_file(u'en.ts', filename)
|
||||
print u' ** Please Note **'
|
||||
print u' In order to get this file into OpenLP and onto the Pootle ' + \
|
||||
u'translation server you will need to subscribe to the OpenLP' + \
|
||||
u'Translators mailing list, and request that your language file ' + \
|
||||
u'be added to the project.'
|
||||
print u' Done'
|
||||
print_quiet(u' ** Please Note **')
|
||||
print_quiet(u' In order to get this file into OpenLP and onto the '
|
||||
u'Pootle translation server you will need to subscribe to the '
|
||||
u'OpenLP Translators mailing list, and request that your language '
|
||||
u'file be added to the project.')
|
||||
print_quiet(u' Done.')
|
||||
|
||||
def process_stack(command_stack):
|
||||
"""
|
||||
@ -315,9 +330,9 @@ def process_stack(command_stack):
|
||||
The command stack to process.
|
||||
"""
|
||||
if command_stack:
|
||||
print u'Processing %d commands...' % len(command_stack)
|
||||
print_quiet(u'Processing %d commands...' % len(command_stack))
|
||||
for command in command_stack:
|
||||
print u'%d.' % (command_stack.current_index),
|
||||
print_quiet(u'%d.' % (command_stack.current_index), False)
|
||||
if command == Command.Download:
|
||||
download_translations()
|
||||
elif command == Command.Prepare:
|
||||
@ -329,12 +344,12 @@ def process_stack(command_stack):
|
||||
elif command == Command.Create:
|
||||
arguments = command_stack.arguments()
|
||||
create_translation(*arguments)
|
||||
print u'Finished processing commands.'
|
||||
print_quiet(u'Finished processing commands.')
|
||||
else:
|
||||
print u'No commands to process.'
|
||||
print_quiet(u'No commands to process.')
|
||||
|
||||
def main():
|
||||
global verbose_mode
|
||||
global verbose_mode, quiet_mode
|
||||
# Set up command line options.
|
||||
usage = u'%prog [options]\nOptions are parsed in the order they are ' + \
|
||||
u'listed below. If no options are given, "-dpug" will be used.\n\n' + \
|
||||
@ -352,6 +367,8 @@ def main():
|
||||
help='compile .ts files into .qm files')
|
||||
parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
|
||||
help='show extra information while processing translations')
|
||||
parser.add_option('-q', '--quiet', dest='quiet', action='store_true',
|
||||
help='suppress all output other than errors')
|
||||
(options, args) = parser.parse_args()
|
||||
# Create and populate the command stack
|
||||
command_stack = CommandStack()
|
||||
@ -366,6 +383,7 @@ def main():
|
||||
if options.generate:
|
||||
command_stack.append(Command.Generate)
|
||||
verbose_mode = options.verbose
|
||||
quiet_mode = options.quiet
|
||||
if not command_stack:
|
||||
command_stack.append(Command.Download)
|
||||
command_stack.append(Command.Prepare)
|
||||
|
@ -87,20 +87,33 @@ windows-builder.py
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from shutil import copy
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
python_exe = sys.executable
|
||||
innosetup_exe = os.path.join(os.getenv(u'PROGRAMFILES'), 'Inno Setup 5',
|
||||
u'ISCC.exe')
|
||||
|
||||
# Base paths
|
||||
script_path = os.path.split(os.path.abspath(__file__))[0]
|
||||
branch_path = os.path.abspath(os.path.join(script_path, u'..'))
|
||||
site_packages = os.path.join(os.path.split(python_exe)[0], u'Lib',
|
||||
u'site-packages')
|
||||
|
||||
# Files and executables
|
||||
pyi_build = os.path.abspath(os.path.join(branch_path, u'..', u'..',
|
||||
u'pyinstaller', u'Build.py'))
|
||||
lrelease_exe = os.path.join(site_packages, u'PyQt4', u'bin', u'lrelease.exe')
|
||||
i18n_utils = os.path.join(script_path, u'translation_utils.py')
|
||||
|
||||
# Paths
|
||||
source_path = os.path.join(branch_path, u'openlp')
|
||||
i18n_path = os.path.join(branch_path, u'resources', u'i18n')
|
||||
winres_path = os.path.join(branch_path, u'resources', u'windows')
|
||||
build_path = os.path.join(branch_path, u'build', u'pyi.win32', u'OpenLP')
|
||||
dist_path = os.path.join(branch_path, u'dist', u'OpenLP')
|
||||
pyinstaller_path = os.path.abspath(os.path.join(branch_path, u'..', u'..', u'pyinstaller'))
|
||||
innosetup_path = os.path.join(os.getenv(u'PROGRAMFILES'), 'Inno Setup 5')
|
||||
iss_path = os.path.join(branch_path, u'resources', u'innosetup')
|
||||
lrelease_path = u'C:\\Python26\\Lib\\site-packages\\PyQt4\\bin\\lrelease.exe'
|
||||
enchant_path = u'C:\\Python26\\Lib\\site-packages\\enchant'
|
||||
enchant_path = os.path.join(site_packages, u'enchant')
|
||||
|
||||
def clean_build_directories():
|
||||
#if not os.path.exists(build_path)
|
||||
@ -117,11 +130,13 @@ def clean_build_directories():
|
||||
def run_pyinstaller():
|
||||
print u'Running PyInstaller...'
|
||||
os.chdir(branch_path)
|
||||
pyinstaller = Popen((u'python', os.path.join(pyinstaller_path, u'Build.py'),
|
||||
u'-y', u'OpenLP.spec'))
|
||||
pyinstaller = Popen((python_exe, pyi_build, u'-y', u'-o', build_path,
|
||||
os.path.join(winres_path, u'OpenLP.spec')), stdout=PIPE)
|
||||
output, error = pyinstaller.communicate()
|
||||
code = pyinstaller.wait()
|
||||
if code != 0:
|
||||
raise Exception(u'Error running PyInstaller Build.py')
|
||||
print output
|
||||
raise Exception(u'Error running PyInstaller')
|
||||
|
||||
def write_version_file():
|
||||
print u'Writing version file...'
|
||||
@ -155,7 +170,7 @@ def copy_enchant():
|
||||
for root, dirs, files in os.walk(source):
|
||||
for filename in files:
|
||||
if not filename.endswith(u'.pyc') and not filename.endswith(u'.pyo'):
|
||||
dest_path = os.path.join(dest, root[len(source)+1:])
|
||||
dest_path = os.path.join(dest, root[len(source) + 1:])
|
||||
if not os.path.exists(dest_path):
|
||||
os.makedirs(dest_path)
|
||||
copy(os.path.join(root, filename),
|
||||
@ -176,16 +191,18 @@ def copy_plugins():
|
||||
|
||||
def copy_windows_files():
|
||||
print u'Copying extra files for Windows...'
|
||||
copy(os.path.join(iss_path, u'OpenLP.ico'), os.path.join(dist_path, u'OpenLP.ico'))
|
||||
copy(os.path.join(iss_path, u'LICENSE.txt'), os.path.join(dist_path, u'LICENSE.txt'))
|
||||
copy(os.path.join(winres_path, u'OpenLP.ico'),
|
||||
os.path.join(dist_path, u'OpenLP.ico'))
|
||||
copy(os.path.join(winres_path, u'LICENSE.txt'),
|
||||
os.path.join(dist_path, u'LICENSE.txt'))
|
||||
|
||||
def update_translations():
|
||||
print u'Updating translations...'
|
||||
os.chdir(script_path)
|
||||
translation_utils = Popen(u'python translation_utils.py -dpu')
|
||||
translation_utils = Popen((python_exe, i18n_utils, u'-qdpu'))
|
||||
code = translation_utils.wait()
|
||||
if code != 0:
|
||||
print u'Error running translation_utils.py'
|
||||
raise Exception(u'Error running translation_utils.py')
|
||||
|
||||
def compile_translations():
|
||||
print u'Compiling translations...'
|
||||
@ -197,19 +214,17 @@ def compile_translations():
|
||||
source_path = os.path.join(i18n_path, file)
|
||||
dest_path = os.path.join(dist_path, u'i18n',
|
||||
file.replace(u'.ts', u'.qm'))
|
||||
lconvert = Popen(u'"%s" "%s" -qm "%s"' % (lrelease_path, \
|
||||
source_path, dest_path))
|
||||
lconvert = Popen((lrelease_exe, u'-compress', u'-silent',
|
||||
source_path, u'-qm', dest_path))
|
||||
code = lconvert.wait()
|
||||
if code != 0:
|
||||
print 'Error running lconvert on %s' % source_path
|
||||
raise Exception('Error running lconvert on %s' % source_path)
|
||||
|
||||
def run_innosetup():
|
||||
print u'Running Inno Setup...'
|
||||
os.chdir(iss_path)
|
||||
run_command = u'"%s" "%s"' % (os.path.join(innosetup_path, u'ISCC.exe'),
|
||||
os.path.join(iss_path, u'OpenLP-2.0.iss'))
|
||||
print run_command
|
||||
innosetup = Popen(run_command)
|
||||
os.chdir(winres_path)
|
||||
innosetup = Popen((innosetup_exe,
|
||||
os.path.join(winres_path, u'OpenLP-2.0.iss'), u'/q'))
|
||||
code = innosetup.wait()
|
||||
if code != 0:
|
||||
raise Exception(u'Error running Inno Setup')
|
||||
@ -221,9 +236,9 @@ def main():
|
||||
print "Branch path:", branch_path
|
||||
print "Source path:", source_path
|
||||
print "\"dist\" path:", dist_path
|
||||
print "PyInstaller path:", pyinstaller_path
|
||||
print "PyInstaller:", pyi_build
|
||||
print "Inno Setup path:", innosetup_path
|
||||
print "ISS file path:", iss_path
|
||||
print "Windows resources:", winres_path
|
||||
#clean_build_directories()
|
||||
run_pyinstaller()
|
||||
write_version_file()
|
||||
|
Loading…
Reference in New Issue
Block a user