This commit is contained in:
Andreas Preikschat 2010-10-28 15:28:13 +02:00
commit ab2379ecc0
116 changed files with 2746 additions and 1167 deletions

View File

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

View File

@ -17,7 +17,7 @@ import sys
# If extensions (or modules to document with autodoc) are in another directory, # 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 # 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. # 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 ----------------------------------------------------- # -- General configuration -----------------------------------------------------
@ -39,7 +39,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = u'OpenLP' project = u'OpenLP'
copyright = u'2009, Raoul Snyman' copyright = u'2004-2010, Raoul Snyman'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -48,7 +48,7 @@ copyright = u'2009, Raoul Snyman'
# The short X.Y version. # The short X.Y version.
version = '2.0' version = '2.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '2.0.pre' release = '1.9.3'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -111,7 +111,7 @@ html_theme_options = {
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
#html_title = None html_title = 'OpenLP 2.0 Developer API'
# A shorter title for the navigation bar. Default is the same as html_title. # A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None #html_short_title = None
@ -166,7 +166,7 @@ html_static_path = ['_static']
#html_file_suffix = '' #html_file_suffix = ''
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'OpenLPdoc' htmlhelp_basename = 'OpenLP-2.0-api'
# -- Options for LaTeX output -------------------------------------------------- # -- Options for LaTeX output --------------------------------------------------
@ -180,7 +180,7 @@ htmlhelp_basename = 'OpenLPdoc'
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'OpenLP.tex', u'OpenLP Documentation', ('index', 'OpenLP.tex', u'OpenLP 2.0 Developer API',
u'Raoul Snyman', 'manual'), u'Raoul Snyman', 'manual'),
] ]

View File

@ -3,9 +3,13 @@
:mod:`core` Module :mod:`core` Module
================== ==================
.. automodule:: openlp.core
:members:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
lib lib
theme theme
ui
utils

View File

@ -1,7 +1,7 @@
.. _core-lib: .. _core-lib:
:mod:`lib` Module Object Library
================= ==============
.. automodule:: openlp.core.lib .. automodule:: openlp.core.lib
:members: :members:
@ -60,12 +60,6 @@
.. autoclass:: openlp.core.lib.settingstab.SettingsTab .. autoclass:: openlp.core.lib.settingstab.SettingsTab
:members: :members:
:mod:`ThemeXML`
---------------
.. autoclass:: openlp.core.lib.themexmlhandler.ThemeXML
:members:
:mod:`OpenLPToolbar` :mod:`OpenLPToolbar`
-------------------- --------------------

View File

@ -0,0 +1,27 @@
.. _core-ui:
User Interface
==============
.. automodule:: openlp.core.ui
Main Windows
------------
.. autoclass:: openlp.core.ui.mainwindow.MainWindow
:members:
.. autoclass:: openlp.core.ui.maindisplay.MainDisplay
:members:
Managers
--------
.. autoclass:: openlp.core.ui.servicemanager.ServiceManager
:members:
.. autoclass:: openlp.core.ui.mediadockmanager.MediaDockManager
:members:
.. autoclass:: openlp.core.ui.thememanager.ThemeManager
:members:

View File

@ -0,0 +1,7 @@
.. _core-utils:
Utilities
=========
.. automodule:: openlp.core.utils
:members:

View File

@ -15,7 +15,6 @@ Contents:
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
openlp
core/index core/index
plugins/index plugins/index

View File

@ -0,0 +1,31 @@
.. _plugins-alerts:
Alerts Plugin
=============
.. automodule:: openlp.plugins.alerts
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.alerts.alertsplugin.AlertsPlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.alerts.forms
:members:
.. autoclass:: openlp.plugins.alerts.forms.alertform.AlertForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.alerts.lib
:members:
.. automodule:: openlp.plugins.alerts.lib.db
:members:

View File

@ -0,0 +1,55 @@
.. _plugins-bibles:
Bibles Plugin
=============
.. automodule:: openlp.plugins.bibles
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.bibles.bibleplugin.BiblePlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.bibles.forms
:members:
.. autoclass:: openlp.plugins.bibles.forms.importwizardform.ImportWizardForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.bibles.lib
:members:
.. automodule:: openlp.plugins.bibles.lib.db
:members:
.. automodule:: openlp.plugins.bibles.lib.biblestab
:members:
.. automodule:: openlp.plugins.bibles.lib.manager
:members:
.. automodule:: openlp.plugins.bibles.lib.mediaitem
:members:
Bible Importers
---------------
.. automodule:: openlp.plugins.bibles.lib.csvbible
:members:
.. automodule:: openlp.plugins.bibles.lib.http
:members:
.. automodule:: openlp.plugins.bibles.lib.osis
:members:
.. automodule:: openlp.plugins.bibles.lib.opensong
:members:

View File

@ -0,0 +1,34 @@
.. _plugins-custom:
Custom Slides Plugin
====================
.. automodule:: openlp.plugins.custom
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.custom.customplugin.CustomPlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.custom.forms
:members:
.. autoclass:: openlp.plugins.custom.forms.editcustomform.EditCustomForm
:members:
.. autoclass:: openlp.plugins.custom.forms.editcustomslideform.EditCustomSlideForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.custom.lib
:members:
.. automodule:: openlp.plugins.custom.lib.mediaitem
:members:

View File

@ -0,0 +1,22 @@
.. _plugins-images:
Images Plugin
=============
.. automodule:: openlp.plugins.images
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.images.imageplugin.ImagePlugin
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.images.lib
:members:
.. automodule:: openlp.plugins.images.lib.mediaitem
:members:

View File

@ -0,0 +1,20 @@
.. _plugins-index:
Plugins
=======
.. automodule:: openlp.plugins
:members:
.. toctree::
:maxdepth: 2
songs
bibles
presentations
media
images
custom
remotes
songusage
alerts

View File

@ -0,0 +1,22 @@
.. _plugins-media:
Media Plugin
============
.. automodule:: openlp.plugins.media
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.media.mediaplugin.MediaPlugin
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.media.lib
:members:
.. automodule:: openlp.plugins.media.lib.mediaitem
:members:

View 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:

View File

@ -0,0 +1,19 @@
.. _plugins-remotes:
Remotes Plugin
==============
.. automodule:: openlp.plugins.remotes
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.remotes.remoteplugin.RemotesPlugin
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.remotes.lib
:members:

View File

@ -0,0 +1,103 @@
.. _plugins-songs:
Songs Plugin
============
.. automodule:: openlp.plugins.songs
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.songs.songsplugin.SongsPlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.songs.forms
:members:
.. autoclass:: openlp.plugins.songs.forms.authorsform.AuthorsForm
:members:
.. autoclass:: openlp.plugins.songs.forms.editsongform.EditSongForm
:members:
.. autoclass:: openlp.plugins.songs.forms.editverseform.EditVerseForm
:members:
.. autoclass:: openlp.plugins.songs.forms.songbookform.SongBookForm
:members:
.. autoclass:: openlp.plugins.songs.forms.songimportform.SongImportForm
:members:
.. autoclass:: openlp.plugins.songs.forms.songmaintenanceform.SongMaintenanceForm
:members:
.. autoclass:: openlp.plugins.songs.forms.topicsform.TopicsForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.songs.lib
:members:
.. automodule:: openlp.plugins.songs.lib.db
:members:
.. automodule:: openlp.plugins.songs.lib.importer
:members:
.. automodule:: openlp.plugins.songs.lib.mediaitem
:members:
.. autoclass:: openlp.plugins.songs.lib.mediaitem.SongListView
:members:
.. automodule:: openlp.plugins.songs.lib.songimport
:members:
.. automodule:: openlp.plugins.songs.lib.songstab
:members:
.. automodule:: openlp.plugins.songs.lib.xml
:members:
Song Importers
--------------
.. automodule:: openlp.plugins.songs.lib.cclifileimport
:members:
.. autoclass:: openlp.plugins.songs.lib.cclifileimport.CCLIFileImportError
:members:
.. automodule:: openlp.plugins.songs.lib.ewimport
:members:
.. autoclass:: openlp.plugins.songs.lib.ewimport.FieldDescEntry
:members:
.. automodule:: openlp.plugins.songs.lib.olp1import
:members:
.. automodule:: openlp.plugins.songs.lib.olpimport
:members:
.. automodule:: openlp.plugins.songs.lib.oooimport
:members:
.. automodule:: openlp.plugins.songs.lib.opensongimport
:members:
.. automodule:: openlp.plugins.songs.lib.sofimport
:members:
.. automodule:: openlp.plugins.songs.lib.songbeamerimport
:members:
.. automodule:: openlp.plugins.songs.lib.wowimport
:members:

View File

@ -0,0 +1,34 @@
.. _plugins-songusage:
Song Usage Plugin
=================
.. automodule:: openlp.plugins.songusage
:members:
Plugin Class
------------
.. autoclass:: openlp.plugins.songusage.songusageplugin.SongUsagePlugin
:members:
Forms
-----
.. automodule:: openlp.plugins.songusage.forms
:members:
.. autoclass:: openlp.plugins.songusage.forms.songusagedeleteform.SongUsageDeleteForm
:members:
.. autoclass:: openlp.plugins.songusage.forms.songusagedetailform.SongUsageDetailForm
:members:
Helper Classes & Functions
--------------------------
.. automodule:: openlp.plugins.songusage.lib
:members:
.. automodule:: openlp.plugins.songusage.lib.db
:members:

View File

@ -0,0 +1,88 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf build/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) build/html
@echo
@echo "Build finished. The HTML pages are in build/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) build/dirhtml
@echo
@echo "Build finished. The HTML pages are in build/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) build/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) build/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) build/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in build/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) build/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in build/qthelp, like this:"
@echo "# qcollectiongenerator build/qthelp/OpenLP.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile build/qthelp/OpenLP.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex
@echo
@echo "Build finished; the LaTeX files are in build/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) build/changes
@echo
@echo "The overview file is in build/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) build/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in build/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) build/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in build/doctest/output.txt."

View File

@ -0,0 +1,112 @@
@ECHO OFF
REM Command file for Sphinx documentation
set SPHINXBUILD=sphinx-build
set ALLSPHINXOPTS=-d build/doctrees %SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (build\*) do rmdir /q /s %%i
del /q /s build\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% build/html
echo.
echo.Build finished. The HTML pages are in build/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% build/dirhtml
echo.
echo.Build finished. The HTML pages are in build/dirhtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% build/pickle
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% build/json
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% build/htmlhelp
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in build/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% build/qthelp
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in build/qthelp, like this:
echo.^> qcollectiongenerator build\qthelp\OpenLP.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile build\qthelp\OpenLP.ghc
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% build/latex
echo.
echo.Build finished; the LaTeX files are in build/latex.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% build/changes
echo.
echo.The overview file is in build/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% build/linkcheck
echo.
echo.Link check complete; look for any errors in the above output ^
or in build/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% build/doctest
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in build/doctest/output.txt.
goto end
)
:end

View File

@ -0,0 +1,208 @@
# -*- coding: utf-8 -*-
#
# OpenLP documentation build configuration file, created by
# sphinx-quickstart on Fri Jul 10 17:20:40 2009.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
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.insert(0, os.path.abspath(os.path.join('..', '..')))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
#extensions = ['sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'OpenLP'
copyright = u'2004-2010 Raoul Snyman'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.0'
# The full version, including alpha/beta/rc tags.
release = '1.9.3'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
'sidebarbgcolor': '#3a60a9',
'relbarbgcolor': '#203b6f',
'footerbgcolor': '#26437c',
'headtextcolor': '#203b6f',
'linkcolor': '#26437c',
'sidebarlinkcolor': '#ceceff'
}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = u'OpenLP 2.0 User Manual'
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'OpenLP-2.0-manual'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'OpenLP.tex', u'OpenLP 2.0 User Manual',
u'Raoul Snyman', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
# A dictionary that contains LaTeX snippets that override those Sphinx usually
# puts into the generated .tex files.
latex_elements = {
'fontpkg': '\\usepackage{helvet}'
}

View File

@ -0,0 +1,180 @@
==================
Dual Monitor Setup
==================
The first step in getting OpenLP working on your system is to setup your
computer properly for dual monitors. This is not very difficult, but the steps
do vary depending on operating system.
Most modern computers do have the ability for dual monitors. To be certain
check your computer's documentation. A typical desktop computer capable of dual
monitors will have two of, or a combination of the two connectors below.
**VGA**
.. image:: pics/vga.png
**DVI**
.. image:: pics/dvi.png
A laptop computer setup only varies slightly, generally you will need only one
of outputs pictured above since your laptops screen serves as one of the
monitors. Sometimes with older laptops a key stroke generally involving the
:kbd:`Fn` key and another key is required to enable the second monitor on
laptops.
Some computers also incorporate the use of :abbr:`S-Video (Separate Video)` or
:abbr:`HDMI (High-Definition Multimedia Interface)` connections.
A typical OpenLP set up consist of your normal single monitor setup, with your
projector setup as the second monitor. With the option of extending your
desktop across the second monitor, or your operating system's equivalent.
Microsoft Windows
-----------------
Dual monitor setup is similar among all the currently supported Windows
releases (XP, Vista, Windows 7), but does vary slightly from one release to the
next.
Windows 7
^^^^^^^^^
Windows 7 has using a projector in mind. Simply connect your projector and
press :kbd:`Windows+P`.
The more traditional way is also fairly straight forward. Go to
:guilabel:`Control Panel` and click on :guilabel:`Display`. This will open up
the :guilabel:`Display` dialog. You can also bypass this step by right click on
a blank area on your desktop and selecting :guilabel:`Resolution`.
.. image:: pics/winsevendisplay.png
Then click on the :guilabel:`Adjust resolution` link in the left pane. Enable
your projector and make sure that the selected value for :guilabel:`Multiple
displays` is :guilabel:`Extend these displays`.
.. image:: pics/winsevenresolution.png
Windows Vista
^^^^^^^^^^^^^
From :guilabel:`Control Panel` click on :guilabel:`Personalize`, or right click
a blank place on the desktop and click :guilabel:`Personalization`.
.. image:: pics/vistapersonalize.png
From the :guilabel:`Personalization` window click on :guilabel:`Display
Settings`. Then enable the montior that represents your projector and make sure
you have checked :guilabel:`Extend the desktop onto this monitor`.
.. image:: pics/vistadisplaysettings.png
Windows XP
^^^^^^^^^^
From :guilabel:`Control Panel` select :guilabel:`Display`, or right click on a
blank area of the desktop and select :guilabel:`Properties`. From the
:guilabel:`Display Properties` window click on the :guilabel:`Settings` tab.
Then click on the monitor that represents your projector and make sure you have
checked :guilabel:`Extend my Windows desktop onto this monitor`.
.. image:: pics/xpdisplaysettings.png
Linux
-----
Due to the vast varieties of hardware, distributions, desktops, and drivers
this is not an exhaustive guide to dual monitor setup on Linux. This guide
assumes that you have properly set up any proprietary drivers if needed. You
should seek out your distributions documentation if this general guide does not
work.
GNOME
^^^^^
This guide is for users of the GNOME desktop who do not use proprietary drivers.
From most distros go to :menuselection:`System --> Preferences --> Display
Settings (Monitors)`. Set up your projector with the correct resolution and make
sure that :guilabel:`Same image on all monitors` is **unchecked**.
.. image:: pics/gnome.png
KDE
^^^
This guide is for users of the KDE desktop who do not use proprietary drivers.
From most distros click the Kick Off menu and navigate to
:guilabel:`System Settings`
.. image:: pics/kdesystemsettings.png
Click on the display and monitor icon.
.. image:: pics/kdedisplay.png
From here you will need to set up your projector with the appropriate
resolution, and position. OpenLP works best projecting to the monitor on the
right.
Linux Systems Using nVidia Drivers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This guide is for users of the proprietary nVidia driver on Linux Distributions.
It is assumed that you have properly setup your drivers according to your
distribution's documentation, and you have a working ``xorg.conf`` file in place.
If you wish to make the changes permanent in setting up your system for dual
monitors it will be necessary to modify your ``xorg.conf`` file. It is always a
good idea to make a backup of any critical file before making changes::
user@linux:~ $ sudo cp /etc/X11/xorg.conf /etc/X11/xorg.conf.old
Or for those using systems that use the root user instead of sudo, change to
root and enter::
root@linux: # cp /etc/X11/xorg.conf /etc/X11/xorg.conf.old
The exact location of the ``xorg.conf`` file can vary so check your
distribution's documentation.
If you want to make your changes permanent run nVidia settings from the
terminal::
user@linux:~ $ sudo nvidia-settings
Or, as root::
root@linux: # nividia-settings
If you do not want to write the changes to your ``xorg.conf`` file simply run
the nVidia Settings program (``nvidia-settings``) from your desktop's menu,
usually in an administration or system menu, or from the terminal as a normal
user run::
user@linux:~ $ nvidia-settings
Once you have opened nVidia Settings, click on
:guilabel:`X Server Display Configuration`. Then select the monitor you are
wanting to use as your second monitor and click :guilabel:`Configure`.
.. image:: pics/nvlinux1.png
After clicking :guilabel:`Configure`, select :guilabel:`TwinView`. Then click
:guilabel:`OK`.
.. image:: pics/twinview.png
Then click :guilabel:`Apply` and if you are happy with the way things look click
:guilabel:`Keep` to keep your new settings. Don't worry if all goes wrong the
settings will return back to the previous settings in 15 seconds without any
action. nVidia Settings should take care of selecting your optimum resolution
etc, but that can be changed as needed. When you are happy with everything click
on :guilabel:`Save to X Configuration File`.
.. image:: pics/xorgwrite.png
Then click :guilabel:`Save` and you should be set. You may want to restart X or
your machine just to make sure all the settings carry over the next time you log
in.

View File

@ -0,0 +1,70 @@
========
Glossary
========
The developers of OpenLP have strived to make it a straightforward and easy to
use application. However, it is good to be familiar with a few terms that will
be used throughout this documentation, and when seeking support.
Main Window
-----------
The Main Window is what you will see when you first open OpenLP
.. image:: pics/mainwindow.png
The Main Window contains all the tools and plugins that make OpenLP function
Media Manager
-------------
The Media Manager contains a number of tabs that plugins supply to OpenLP.
Each tab in the Media Manager is called a **Media Item**
.. image:: pics/mediamanager.png
From the Media Manager you can send Media Items to the Preview or Live screens.
Preview
-------
The preview pane is a section to preview your media items before you go live
with them.
.. image:: pics/preview.png
Service File
------------
A service file, is the file that is created when you save your work on OpenLP.
The service file consist of **Service Items**
Service Item
------------
A service item are the **media items** that are in the **service manager**
Service Manger
--------------
The service manager contains the media items in your service file. This is the
area from wich your media items go live, and you can also save, open, and edit
services files.
.. image:: pics/servicemanager.png
Slide Controller
----------------
The Slide Controller controls which slide from a **Service Item** is currently
being displayed, and moving between the various slides.
.. image:: pics/slidecontroller.png
Theme Manager
-------------
The theme manager is where themes are created and edited. Themes are the text
styles backgrounds that you use to personalize your services.
.. image:: pics/thememanager.png

View File

@ -0,0 +1,24 @@
.. 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 the OpenLP 2.0 User Manual
=====================================
Contents:
.. toctree::
:maxdepth: 2
introduction
glossary
dualmonitors
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -1,95 +0,0 @@
.. _plugins-bibles:
:mod:`bibles` Plugin
====================
.. automodule:: openlp.plugins.bibles
:members:
:mod:`BiblePlugin` Class
-------------------------
.. autoclass:: openlp.plugins.bibles.bibleplugin.BiblePlugin
:members:
:mod:`forms` Submodule
----------------------
.. automodule:: openlp.plugins.bibles.forms
:members:
:mod:`BibleImportWizard`
^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: openlp.plugins.bibles.forms.bibleimportwizard.Ui_BibleImportWizard
:members:
.. autoclass:: openlp.plugins.bibles.forms.importwizardform.ImportWizardForm
:members:
:mod:`lib` Submodule
--------------------
.. automodule:: openlp.plugins.bibles.lib
:members:
:mod:`db`
^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.db
:members:
.. autoclass:: openlp.plugins.bibles.lib.db.BibleDB
:members:
:mod:`csv`
^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.csvbible
:members:
.. autoclass:: openlp.plugins.bibles.lib.csvbible.CSVBible
:members:
:mod:`http`
^^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.http
:members:
.. autoclass:: openlp.plugins.bibles.lib.http.HTTPBible
:members:
:mod:`bibleOSISimpl`
^^^^^^^^^^^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.osis
:members:
.. autoclass:: openlp.plugins.bibles.lib.osis.OSISBible
:members:
:mod:`biblestab`
^^^^^^^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.biblestab
:members:
:mod:`common`
^^^^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.common
:members:
:mod:`manager`
^^^^^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.manager
:members:
:mod:`mediaitem`
^^^^^^^^^^^^^^^^
.. automodule:: openlp.plugins.bibles.lib.mediaitem
:members:

View File

@ -1,43 +0,0 @@
.. _plugins-index:
:mod:`plugins` Module
=====================
.. automodule:: openlp.plugins
:members:
.. toctree::
:maxdepth: 2
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:
:mod:`custom` Plugin
--------------------
.. automodule:: openlp.plugins.custom
:members:
:mod:`songusage` Plugin
-----------------------
.. automodule:: openlp.plugins.songusage
:members:

View File

@ -1,46 +0,0 @@
.. _plugins-songs:
:mod:`songs` Plugin
===================
.. automodule:: openlp.plugins.songs
:members:
:mod:`SongsPlugin` Class
------------------------
.. autoclass:: openlp.plugins.songs.songsplugin.SongsPlugin
:members:
:mod:`forms` Submodule
----------------------
.. automodule:: openlp.plugins.songs.forms
:members:
:mod:`AuthorsForm`
^^^^^^^^^^^^^^^^^^
.. autoclass:: openlp.plugins.songs.forms.authorsdialog.Ui_AuthorsDialog
:members:
.. autoclass:: openlp.plugins.songs.forms.authorsform.AuthorsForm
:members:
:mod:`EditSongForm`
^^^^^^^^^^^^^^^^^^^
.. autoclass:: openlp.plugins.songs.forms.editsongdialog.Ui_EditSongDialog
:members:
.. autoclass:: openlp.plugins.songs.forms.editsongform.EditSongForm
:members:
:mod:`EditVerseForm`
^^^^^^^^^^^^^^^^^^^^
.. autoclass:: openlp.plugins.songs.forms.editversedialog.Ui_EditVerseDialog
:members:
.. autoclass:: openlp.plugins.songs.forms.editverseform.EditVerseForm
:members:

View File

@ -30,6 +30,7 @@ import sys
import logging import logging
from optparse import OptionParser from optparse import OptionParser
from traceback import format_exception from traceback import format_exception
from subprocess import Popen, PIPE
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
@ -71,23 +72,68 @@ class OpenLP(QtGui.QApplication):
""" """
log.info(u'OpenLP Application Loaded') log.info(u'OpenLP Application Loaded')
def notify(self, obj, evt): def _get_version(self):
#TODO needed for presentation exceptions
return QtGui.QApplication.notify(self, obj, evt)
def run(self):
""" """
Run the OpenLP application. Load and store current Application Version
""" """
#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 = AppLocation.get_directory(AppLocation.VersionDir)
filepath = os.path.join(filepath, u'.version') filepath = os.path.join(filepath, u'.version')
fversion = None fversion = None
try: try:
fversion = open(filepath, u'r') fversion = open(filepath, u'r')
for line in fversion: full_version = unicode(fversion.read()).rstrip()
full_version = unicode(line).rstrip() #\ except IOError:
#.replace(u'\r', u'').replace(u'\n', u'') log.exception('Error in version file.')
full_version = u'0.0.0-bzr000'
finally:
if fversion:
fversion.close()
bits = full_version.split(u'-') bits = full_version.split(u'-')
app_version = { app_version = {
u'full': full_version, u'full': full_version,
@ -102,16 +148,17 @@ class OpenLP(QtGui.QApplication):
) )
else: else:
log.info(u'Openlp version %s' % app_version[u'version']) log.info(u'Openlp version %s' % app_version[u'version'])
except IOError: return app_version
log.exception('Error in version file.')
app_version = { def notify(self, obj, evt):
u'full': u'1.9.0-bzr000', #TODO needed for presentation exceptions
u'version': u'1.9.0', return QtGui.QApplication.notify(self, obj, evt)
u'build': u'bzr000'
} def run(self):
finally: """
if fversion: Run the OpenLP application.
fversion.close() """
app_version = self._get_version()
#provide a listener for widgets to reqest a screen update. #provide a listener for widgets to reqest a screen update.
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents) QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
@ -172,6 +219,9 @@ def main():
parser.add_option('-p', '--portable', dest='portable', parser.add_option('-p', '--portable', dest='portable',
action='store_true', help='Specify if this should be run as a ' action='store_true', help='Specify if this should be run as a '
'portable app, off a USB flash drive (not implemented).') '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', parser.add_option('-s', '--style', dest='style',
help='Set the Qt4 style (passed directly to Qt4).') help='Set the Qt4 style (passed directly to Qt4).')
# Set up logging # Set up logging

View File

@ -81,9 +81,6 @@ html_expands.append({u'desc':u'Italics', u'start tag':u'{it}',
u'start html':u'<em>', u'end tag':u'{/it}', u'end html':u'</em>', u'start html':u'<em>', u'end tag':u'{/it}', u'end html':u'</em>',
u'protected':True}) u'protected':True})
# Image image_cache to stop regualar image resizing
image_cache = {}
def translate(context, text, comment=None): def translate(context, text, comment=None):
""" """
A special shortcut method to wrap around the Qt4 translation functions. A special shortcut method to wrap around the Qt4 translation functions.
@ -223,16 +220,13 @@ def image_to_byte(image):
``image`` ``image``
The image to converted. The image to converted.
""" """
log.debug(u'image_to_byte') log.debug(u'image_to_byte - start')
byte_array = QtCore.QByteArray() byte_array = QtCore.QByteArray()
# use buffer to store pixmap into byteArray # use buffer to store pixmap into byteArray
buffie = QtCore.QBuffer(byte_array) buffie = QtCore.QBuffer(byte_array)
buffie.open(QtCore.QIODevice.WriteOnly) buffie.open(QtCore.QIODevice.WriteOnly)
if isinstance(image, QtGui.QImage): image.save(buffie, "PNG")
pixmap = QtGui.QPixmap.fromImage(image) log.debug(u'image_to_byte - end')
else:
pixmap = QtGui.QPixmap(image)
pixmap.save(buffie, "PNG")
# convert to base64 encoding so does not get missed! # convert to base64 encoding so does not get missed!
return byte_array.toBase64() return byte_array.toBase64()
@ -253,7 +247,10 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
The background colour defaults to black. The background colour defaults to black.
""" """
log.debug(u'resize_image') log.debug(u'resize_image - start')
if isinstance(image, QtGui.QImage):
preview = image
else:
preview = QtGui.QImage(image) preview = QtGui.QImage(image)
if not preview.isNull(): if not preview.isNull():
# Only resize if different size # Only resize if different size
@ -261,18 +258,14 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
return preview return preview
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio, preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation) QtCore.Qt.SmoothTransformation)
image_cache_key = u'%s%s%s' % (image, unicode(width), unicode(height))
if image_cache_key in image_cache:
return image_cache[image_cache_key]
realw = preview.width() realw = preview.width()
realh = preview.height() realh = preview.height()
# and move it to the centre of the preview space # and move it to the centre of the preview space
new_image = QtGui.QImage(width, height, new_image = QtGui.QImage(width, height,
QtGui.QImage.Format_ARGB32_Premultiplied) QtGui.QImage.Format_ARGB32_Premultiplied)
new_image.fill(background)
painter = QtGui.QPainter(new_image) painter = QtGui.QPainter(new_image)
painter.fillRect(new_image.rect(), background)
painter.drawImage((width - realw) / 2, (height - realh) / 2, preview) painter.drawImage((width - realw) / 2, (height - realh) / 2, preview)
image_cache[image_cache_key] = new_image
return new_image return new_image
def check_item_selected(list_widget, message): def check_item_selected(list_widget, message):
@ -312,6 +305,7 @@ def expand_tags(text):
from spelltextedit import SpellTextEdit from spelltextedit import SpellTextEdit
from eventreceiver import Receiver from eventreceiver import Receiver
from imagemanager import ImageManager
from settingsmanager import SettingsManager from settingsmanager import SettingsManager
from plugin import PluginStatus, StringContent, Plugin from plugin import PluginStatus, StringContent, Plugin
from pluginmanager import PluginManager from pluginmanager import PluginManager

View File

@ -246,3 +246,10 @@ class Manager(object):
self.session.rollback() self.session.rollback()
log.exception(u'Failed to delete %s records', object_class.__name__) log.exception(u'Failed to delete %s records', object_class.__name__)
return False return False
def finalise(self):
"""
VACUUM the database on exit.
"""
engine = create_engine(self.db_url)
engine.execute("vacuum")

View File

@ -328,6 +328,7 @@ def build_html(item, screen, alert, islive):
height = screen[u'size'].height() height = screen[u'size'].height()
theme = item.themedata theme = item.themedata
webkitvers = webkit_version() webkitvers = webkit_version()
# Image generated and poked in
if item.bg_image_bytes: if item.bg_image_bytes:
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
else: else:

View File

@ -0,0 +1,158 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Provides the store and management for Images automatically caching them and
resizing them when needed. Only one copy of each image is needed in the system.
A Thread is used to convert the image to a byte array so the user does not need
to wait for the conversion to happen.
"""
import logging
import os
import time
from PyQt4 import QtCore
from openlp.core.lib import resize_image, image_to_byte
log = logging.getLogger(__name__)
class ImageThread(QtCore.QThread):
"""
A special Qt thread class to speed up the display of text based frames.
This is threaded so it loads the frames in background
"""
def __init__(self, manager):
QtCore.QThread.__init__(self, None)
self.image_mamager = manager
def run(self):
"""
Run the thread.
"""
self.image_mamager.process()
class Image(object):
name = ''
path = ''
dirty = True
image = None
image_bytes = None
class ImageManager(QtCore.QObject):
"""
Image Manager handles the conversion and sizing of images.
"""
log.info(u'Image Manager loaded')
def __init__(self):
self._cache = {}
self._thread_running = False
self._cache_dirty = False
self.image_thread = ImageThread(self)
def update_display(self, width, height):
"""
Screen has changed size so rebuild the cache to new size
"""
log.debug(u'update_display')
self.width = width
self.height = height
# mark the images as dirty for a rebuild
for key in self._cache.keys():
image = self._cache[key]
image.dirty = True
fullpath = os.path.join(image.path, image.name)
image.image = resize_image(fullpath,
self.width, self.height)
self._cache_dirty = True
# only one thread please
if not self._thread_running:
self.image_thread.start()
def get_image(self, name):
"""
Return the Qimage from the cache
"""
log.debug(u'get_image %s' % name)
return self._cache[name].image
def get_image_bytes(self, name):
"""
Returns the byte string for an image
If not present wait for the background thread to process it.
"""
log.debug(u'get_image_bytes %s' % name)
if not self._cache[name].image_bytes:
while self._cache[name].dirty:
log.debug(u'get_image_bytes - waiting')
time.sleep(0.1)
return self._cache[name].image_bytes
def add_image(self, name, path):
"""
Add image to cache if it is not already there
"""
log.debug(u'add_image %s:%s' % (name, path))
if not name in self._cache:
image = Image()
image.name = name
image.path = path
image.image = resize_image(path,
self.width, self.height)
self._cache[name] = image
self._cache_dirty = True
# only one thread please
if not self._thread_running:
self.image_thread.start()
def process(self):
"""
Controls the processing called from a QThread
"""
log.debug(u'process - started')
self._thread_running = True
self.clean_cache()
# data loaded since we started ?
while self._cache_dirty:
log.debug(u'process - recycle')
self.clean_cache()
self._thread_running = False
log.debug(u'process - ended')
def clean_cache(self):
"""
Actually does the work.
"""
log.debug(u'clean_cache')
# we will clean the cache now
self._cache_dirty = False
for key in self._cache.keys():
image = self._cache[key]
if image.dirty:
image.image_bytes = image_to_byte(image.image)
image.dirty = False

View File

@ -51,11 +51,6 @@ class Renderer(object):
self._rect = None self._rect = None
self.theme_name = None self.theme_name = None
self._theme = None self._theme = None
self._bg_image_filename = None
self.frame = None
self.bg_frame = None
self.bg_image = None
self.bg_image_bytes = None
def set_theme(self, theme): def set_theme(self, theme):
""" """
@ -66,14 +61,7 @@ class Renderer(object):
""" """
log.debug(u'set theme') log.debug(u'set theme')
self._theme = theme self._theme = theme
self.bg_frame = None
self.bg_image = None
self.bg_image_bytes = None
self._bg_image_filename = None
self.theme_name = theme.theme_name self.theme_name = theme.theme_name
if theme.background_type == u'image':
if theme.background_filename:
self._bg_image_filename = unicode(theme.background_filename)
def set_text_rectangle(self, rect_main, rect_footer): def set_text_rectangle(self, rect_main, rect_footer):
""" """
@ -105,39 +93,6 @@ class Renderer(object):
(build_lyrics_format_css(self._theme, self.page_width, (build_lyrics_format_css(self._theme, self.page_width,
self.page_height), build_lyrics_outline_css(self._theme)) self.page_height), build_lyrics_outline_css(self._theme))
def set_frame_dest(self, frame_width, frame_height):
"""
Set the size of the slide.
``frame_width``
The width of the slide.
``frame_height``
The height of the slide.
"""
log.debug(u'set frame dest (frame) w %d h %d', frame_width,
frame_height)
self.frame = QtGui.QImage(frame_width, frame_height,
QtGui.QImage.Format_ARGB32_Premultiplied)
if self._bg_image_filename and not self.bg_image:
self.bg_image = resize_image(self._bg_image_filename,
self.frame.width(), self.frame.height())
if self._theme.background_type == u'image':
self.bg_frame = QtGui.QImage(self.frame.width(),
self.frame.height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
painter = QtGui.QPainter()
painter.begin(self.bg_frame)
painter.fillRect(self.frame.rect(), QtCore.Qt.black)
if self.bg_image:
painter.drawImage(0, 0, self.bg_image)
painter.end()
self.bg_image_bytes = image_to_byte(self.bg_frame)
else:
self.bg_frame = None
self.bg_image_bytes = None
def format_slide(self, words, line_break): def format_slide(self, words, line_break):
""" """
Figure out how much text can appear on a slide, using the current Figure out how much text can appear on a slide, using the current

View File

@ -28,7 +28,7 @@ import logging
from PyQt4 import QtCore from PyQt4 import QtCore
from openlp.core.lib import Renderer, ThemeLevel, ServiceItem from openlp.core.lib import Renderer, ThemeLevel, ServiceItem, ImageManager
from openlp.core.ui import MainDisplay from openlp.core.ui import MainDisplay
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -56,7 +56,9 @@ class RenderManager(object):
""" """
log.debug(u'Initilisation started') log.debug(u'Initilisation started')
self.screens = screens self.screens = screens
self.image_manager = ImageManager()
self.display = MainDisplay(self, screens, False) self.display = MainDisplay(self, screens, False)
self.display.imageManager = self.image_manager
self.display.setup() self.display.setup()
self.theme_manager = theme_manager self.theme_manager = theme_manager
self.renderer = Renderer() self.renderer = Renderer()
@ -75,9 +77,11 @@ class RenderManager(object):
log.debug(u'Update Display') log.debug(u'Update Display')
self.calculate_default(self.screens.current[u'size']) self.calculate_default(self.screens.current[u'size'])
self.display = MainDisplay(self, self.screens, False) self.display = MainDisplay(self, self.screens, False)
self.display.imageManager = self.image_manager
self.display.setup() self.display.setup()
self.renderer.bg_frame = None self.renderer.bg_frame = None
self.themedata = None self.themedata = None
self.image_manager.update_display(self.width, self.height)
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global): def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
""" """
@ -153,7 +157,8 @@ class RenderManager(object):
self.calculate_default(self.screens.current[u'size']) self.calculate_default(self.screens.current[u'size'])
self.renderer.set_theme(self.themedata) self.renderer.set_theme(self.themedata)
self.build_text_rectangle(self.themedata) self.build_text_rectangle(self.themedata)
self.renderer.set_frame_dest(self.width, self.height) self.image_manager.add_image(self.themedata.theme_name,
self.themedata.background_filename)
return self.renderer._rect, self.renderer._rect_footer return self.renderer._rect, self.renderer._rect_footer
def build_text_rectangle(self, theme): def build_text_rectangle(self, theme):
@ -211,7 +216,7 @@ class RenderManager(object):
serviceItem.raw_footer = footer serviceItem.raw_footer = footer
serviceItem.render(True) serviceItem.render(True)
self.display.buildHtml(serviceItem) self.display.buildHtml(serviceItem)
raw_html = serviceItem.get_rendered_frame(0)[1] raw_html = serviceItem.get_rendered_frame(0)
preview = self.display.text(raw_html) preview = self.display.text(raw_html)
# Reset the real screen size for subsequent render requests # Reset the real screen size for subsequent render requests
self.calculate_default(self.screens.current[u'size']) self.calculate_default(self.screens.current[u'size'])

View File

@ -30,7 +30,6 @@ type and capability of an item.
import logging import logging
import os import os
import time
import uuid import uuid
from PyQt4 import QtGui from PyQt4 import QtGui
@ -160,12 +159,10 @@ class ServiceItem(object):
theme = self.theme theme = self.theme
self.main, self.footer = \ self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride) 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 self.themedata = self.render_manager.renderer._theme
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides') log.debug(u'Formatting slides')
for slide in self._raw_frames: for slide in self._raw_frames:
before = time.time()
formatted = self.render_manager \ formatted = self.render_manager \
.format_slide(slide[u'raw_slide'], line_break) .format_slide(slide[u'raw_slide'], line_break)
for page in formatted: for page in formatted:
@ -174,12 +171,8 @@ class ServiceItem(object):
u'text': clean_tags(page.rstrip()), u'text': clean_tags(page.rstrip()),
u'html': expand_tags(page.rstrip()), u'html': expand_tags(page.rstrip()),
u'verseTag': slide[u'verseTag'] }) u'verseTag': slide[u'verseTag'] })
log.log(15, u'Formatting took %4s' % (time.time() - before)) elif self.service_item_type == ServiceItemType.Image or \
elif self.service_item_type == ServiceItemType.Image: self.service_item_type == ServiceItemType.Command:
for slide in self._raw_frames:
slide[u'image'] = resize_image(slide[u'image'],
self.render_manager.width, self.render_manager.height)
elif self.service_item_type == ServiceItemType.Command:
pass pass
else: else:
log.error(u'Invalid value renderer :%s' % self.service_item_type) log.error(u'Invalid value renderer :%s' % self.service_item_type)
@ -192,7 +185,7 @@ class ServiceItem(object):
else: else:
self.foot_text = u'%s<br>%s' % (self.foot_text, foot) self.foot_text = u'%s<br>%s' % (self.foot_text, foot)
def add_from_image(self, path, title, image): def add_from_image(self, path, title):
""" """
Add an image slide to the service item. Add an image slide to the service item.
@ -201,13 +194,11 @@ class ServiceItem(object):
``title`` ``title``
A title for the slide in the service item. A title for the slide in the service item.
``image``
The actual image file name.
""" """
self.service_item_type = ServiceItemType.Image self.service_item_type = ServiceItemType.Image
self._raw_frames.append( self._raw_frames.append(
{u'title': title, u'image': image, u'path': path}) {u'title': title, u'path': path})
self.render_manager.image_manager.add_image(title, path)
self._new_item() self._new_item()
def add_from_text(self, title, raw_slide, verse_tag=None): def add_from_text(self, title, raw_slide, verse_tag=None):
@ -310,8 +301,7 @@ class ServiceItem(object):
elif self.service_item_type == ServiceItemType.Image: elif self.service_item_type == ServiceItemType.Image:
for text_image in serviceitem[u'serviceitem'][u'data']: for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image) filename = os.path.join(path, text_image)
real_image = QtGui.QImage(unicode(filename)) self.add_from_image(filename, text_image)
self.add_from_image(path, text_image, real_image)
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for text_image in serviceitem[u'serviceitem'][u'data']: for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image[u'title']) filename = os.path.join(path, text_image[u'title'])
@ -387,9 +377,11 @@ class ServiceItem(object):
renders it if required. renders it if required.
""" """
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
return None, self._display_frames[row][u'html'].split(u'\n')[0] return self._display_frames[row][u'html'].split(u'\n')[0]
elif self.service_item_type == ServiceItemType.Image:
return self._raw_frames[row][u'title']
else: else:
return self._raw_frames[row][u'image'], u'' return self._raw_frames[row][u'image']
def get_frame_title(self, row=0): def get_frame_title(self, row=0):
""" """
@ -399,6 +391,6 @@ class ServiceItem(object):
def get_frame_path(self, row=0): def get_frame_path(self, row=0):
""" """
Returns the title of the raw frame Returns the path of the raw frame
""" """
return self._raw_frames[row][u'path'] return self._raw_frames[row][u'path']

View File

@ -25,7 +25,6 @@
############################################################################### ###############################################################################
import re import re
import sys
try: try:
import enchant import enchant
from enchant import DictNotFoundError from enchant import DictNotFoundError
@ -37,7 +36,7 @@ except ImportError:
# http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/ # http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import html_expands, translate, context_menu_action from openlp.core.lib import html_expands, translate
class SpellTextEdit(QtGui.QPlainTextEdit): class SpellTextEdit(QtGui.QPlainTextEdit):
def __init__(self, *args): def __init__(self, *args):

View File

@ -87,11 +87,11 @@ class ThemeLevel(object):
Service = 2 Service = 2
Song = 3 Song = 3
boolean_list = [u'italics', u'override', u'outline', u'shadow', \ boolean_list = [u'italics', u'override', u'outline', u'shadow',
u'slide_transition'] u'slide_transition']
integer_list =[u'proportion', u'line_adjustment', u'x', u'height', u'y', \ integer_list = [u'proportion', u'line_adjustment', u'x', u'height', u'y',
u'width', u'shadow_size', u'outline_size', u'horizontal_align', \ u'width', u'shadow_size', u'outline_size', u'horizontal_align',
u'vertical_align', u'wrap_style'] u'vertical_align', u'wrap_style']
class ThemeXML(object): class ThemeXML(object):

View File

@ -39,7 +39,6 @@ class HideMode(object):
from filerenameform import FileRenameForm from filerenameform import FileRenameForm
from maindisplay import MainDisplay from maindisplay import MainDisplay
from slidecontroller import HideMode
from servicenoteform import ServiceNoteForm from servicenoteform import ServiceNoteForm
from serviceitemeditform import ServiceItemEditForm from serviceitemeditform import ServiceItemEditForm
from screen import ScreenList from screen import ScreenList

View File

@ -24,7 +24,7 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtGui
from exceptiondialog import Ui_ExceptionDialog from exceptiondialog import Ui_ExceptionDialog

View File

@ -27,7 +27,6 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from filerenamedialog import Ui_FileRenameDialog from filerenamedialog import Ui_FileRenameDialog
from openlp.core.lib import translate
class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog): class FileRenameForm(QtGui.QDialog, Ui_FileRenameDialog):
""" """

View File

@ -90,6 +90,9 @@ class DisplayWidget(QtGui.QGraphicsView):
event.ignore() event.ignore()
class MainDisplay(DisplayWidget): class MainDisplay(DisplayWidget):
"""
This is the display screen.
"""
def __init__(self, parent, screens, live): def __init__(self, parent, screens, live):
DisplayWidget.__init__(self, live, parent=None) DisplayWidget.__init__(self, live, parent=None)
@ -184,7 +187,7 @@ class MainDisplay(DisplayWidget):
`slide` `slide`
The slide text to be displayed The slide text to be displayed
""" """
log.debug(u'text') log.debug(u'text to display')
# Wait for the webview to update before displayiong text. # Wait for the webview to update before displayiong text.
while not self.loaded: while not self.loaded:
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
@ -199,7 +202,7 @@ class MainDisplay(DisplayWidget):
`slide` `slide`
The slide text to be displayed The slide text to be displayed
""" """
log.debug(u'alert') log.debug(u'alert to display')
if self.height() != self.screen[u'size'].height() \ if self.height() != self.screen[u'size'].height() \
or not self.isVisible() or self.videoWidget.isVisible(): or not self.isVisible() or self.videoWidget.isVisible():
shrink = True shrink = True
@ -222,7 +225,14 @@ class MainDisplay(DisplayWidget):
shrinkItem.resize(self.screen[u'size'].width(), shrinkItem.resize(self.screen[u'size'].width(),
self.screen[u'size'].height()) self.screen[u'size'].height())
def image(self, image): def directImage(self, name, path):
"""
API for replacement backgrounds so Images are added directly to cache
"""
image = self.imageManager.add_image(name, path)
self.image(name)
def image(self, name):
""" """
Add an image as the background. The image is converted to a Add an image as the background. The image is converted to a
bytestream on route. bytestream on route.
@ -230,24 +240,20 @@ class MainDisplay(DisplayWidget):
`Image` `Image`
The Image to be displayed can be QImage or QPixmap The Image to be displayed can be QImage or QPixmap
""" """
log.debug(u'image') log.debug(u'image to display')
image = resize_image(image, self.screen[u'size'].width(), image = self.imageManager.get_image_bytes(name)
self.screen[u'size'].height())
self.resetVideo() self.resetVideo()
self.displayImage(image) self.displayImage(image)
# show screen # show screen
if self.isLive: if self.isLive:
self.setVisible(True) self.setVisible(True)
return self.preview()
def displayImage(self, image): def displayImage(self, image):
""" """
Display an image, as is. Display an image, as is.
""" """
if image: if image:
if isinstance(image, QtGui.QImage):
js = u'show_image("data:image/png;base64,%s");' % \
image_to_byte(image)
else:
js = u'show_image("data:image/png;base64,%s");' % image js = u'show_image("data:image/png;base64,%s");' % image
else: else:
js = u'show_image("");' js = u'show_image("");'
@ -395,6 +401,9 @@ class MainDisplay(DisplayWidget):
self.loaded = False self.loaded = False
self.initialFrame = False self.initialFrame = False
self.serviceItem = serviceItem self.serviceItem = serviceItem
if self.serviceItem.themedata.background_filename:
self.serviceItem.bg_image_bytes = self.imageManager. \
get_image_bytes(self.serviceItem.themedata.theme_name)
html = build_html(self.serviceItem, self.screen, self.parent.alertTab, html = build_html(self.serviceItem, self.screen, self.parent.alertTab,
self.isLive) self.isLive)
log.debug(u'buildHtml - pre setHtml') log.debug(u'buildHtml - pre setHtml')

View File

@ -781,7 +781,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtGui.QMessageBox.Save), QtGui.QMessageBox.Save),
QtGui.QMessageBox.Save) QtGui.QMessageBox.Save)
if ret == QtGui.QMessageBox.Save: if ret == QtGui.QMessageBox.Save:
self.ServiceManagerContents.onSaveService() self.ServiceManagerContents.onSaveService(True)
self.cleanUp() self.cleanUp()
event.accept() event.accept()
elif ret == QtGui.QMessageBox.Discard: elif ret == QtGui.QMessageBox.Discard:

View File

@ -25,6 +25,7 @@
############################################################################### ###############################################################################
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate from openlp.core.lib import translate
class Ui_ServiceItemEditDialog(object): class Ui_ServiceItemEditDialog(object):
@ -44,16 +45,26 @@ class Ui_ServiceItemEditDialog(object):
self.topLayout.addWidget(self.listWidget) self.topLayout.addWidget(self.listWidget)
self.buttonLayout = QtGui.QVBoxLayout() self.buttonLayout = QtGui.QVBoxLayout()
self.buttonLayout.setObjectName(u'buttonLayout') self.buttonLayout.setObjectName(u'buttonLayout')
self.upButton = QtGui.QPushButton(self.layoutWidget)
self.upButton.setObjectName(u'upButton')
self.buttonLayout.addWidget(self.upButton)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.buttonLayout.addItem(spacerItem)
self.deleteButton = QtGui.QPushButton(self.layoutWidget) self.deleteButton = QtGui.QPushButton(self.layoutWidget)
self.deleteButton.setObjectName(u'deleteButton') self.deleteButton.setObjectName(u'deleteButton')
self.buttonLayout.addWidget(self.deleteButton) self.buttonLayout.addWidget(self.deleteButton)
spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.buttonLayout.addItem(spacerItem)
self.upButton = QtGui.QPushButton(self.layoutWidget)
self.upButton.setText(u'')
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(u':/services/service_up.png'),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.upButton.setIcon(icon)
self.upButton.setObjectName(u'upButton')
self.buttonLayout.addWidget(self.upButton)
self.downButton = QtGui.QPushButton(self.layoutWidget) self.downButton = QtGui.QPushButton(self.layoutWidget)
self.downButton.setText(u'')
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap(u':/services/service_down.png'),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.downButton.setIcon(icon)
self.downButton.setObjectName(u'downButton') self.downButton.setObjectName(u'downButton')
self.buttonLayout.addWidget(self.downButton) self.buttonLayout.addWidget(self.downButton)
self.topLayout.addLayout(self.buttonLayout) self.topLayout.addLayout(self.buttonLayout)
@ -70,7 +81,5 @@ class Ui_ServiceItemEditDialog(object):
def retranslateUi(self, serviceItemEditDialog): def retranslateUi(self, serviceItemEditDialog):
serviceItemEditDialog.setWindowTitle( serviceItemEditDialog.setWindowTitle(
translate('OpenLP.ServiceItemEditForm', 'Reorder Service Item')) translate('OpenLP.ServiceItemEditForm', 'Reorder Service Item'))
self.upButton.setText(translate('OpenLP.ServiceItemEditForm', 'Up'))
self.deleteButton.setText(translate('OpenLP.ServiceItemEditForm', self.deleteButton.setText(translate('OpenLP.ServiceItemEditForm',
'Delete')) 'Delete'))
self.downButton.setText(translate('OpenLP.ServiceItemEditForm', 'Down'))

View File

@ -346,7 +346,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems[item][u'service_item']) self.serviceItems[item][u'service_item'])
if self.serviceItemEditForm.exec_(): if self.serviceItemEditForm.exec_():
self.addServiceItem(self.serviceItemEditForm.getServiceItem(), self.addServiceItem(self.serviceItemEditForm.getServiceItem(),
replace=True, expand=self.serviceItems[item][u'expand']) replace=True, expand=self.serviceItems[item][u'expanded'])
def nextItem(self): def nextItem(self):
""" """
@ -650,6 +650,9 @@ class ServiceManager(QtGui.QWidget):
.get_service_repr()}) .get_service_repr()})
if item[u'service_item'].uses_file(): if item[u'service_item'].uses_file():
for frame in item[u'service_item'].get_frames(): for frame in item[u'service_item'].get_frames():
if item[u'service_item'].is_image():
path_from = frame[u'path']
else:
path_from = unicode(os.path.join( path_from = unicode(os.path.join(
frame[u'path'], frame[u'path'],
frame[u'title'])) frame[u'title']))

View File

@ -26,6 +26,7 @@
import logging import logging
import os import os
import time
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from PyQt4.phonon import Phonon from PyQt4.phonon import Phonon
@ -400,6 +401,7 @@ class SlideController(QtGui.QWidget):
log.debug(u'screenSizeChanged live = %s' % self.isLive) log.debug(u'screenSizeChanged live = %s' % self.isLive)
# rebuild display as screen size changed # rebuild display as screen size changed
self.display = MainDisplay(self, self.screens, self.isLive) self.display = MainDisplay(self, self.screens, self.isLive)
self.display.imageManager = self.parent.RenderManager.image_manager
self.display.alertTab = self.alertTab self.display.alertTab = self.alertTab
self.ratio = float(self.screens.current[u'size'].width()) / \ self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height()) float(self.screens.current[u'size'].height())
@ -584,11 +586,15 @@ class SlideController(QtGui.QWidget):
else: else:
label = QtGui.QLabel() label = QtGui.QLabel()
label.setMargin(4) label.setMargin(4)
pixmap = resize_image(frame[u'image'], label.setScaledContents(True)
if self.serviceItem.is_command():
image = resize_image(frame[u'image'],
self.parent.RenderManager.width, self.parent.RenderManager.width,
self.parent.RenderManager.height) self.parent.RenderManager.height)
label.setScaledContents(True) else:
label.setPixmap(QtGui.QPixmap.fromImage(pixmap)) image = self.parent.RenderManager.image_manager. \
get_image(frame[u'title'])
label.setPixmap(QtGui.QPixmap.fromImage(image))
self.PreviewListWidget.setCellWidget(framenumber, 0, label) self.PreviewListWidget.setCellWidget(framenumber, 0, label)
slideHeight = width * self.parent.RenderManager.screen_ratio slideHeight = width * self.parent.RenderManager.screen_ratio
row += 1 row += 1
@ -779,15 +785,12 @@ class SlideController(QtGui.QWidget):
[self.serviceItem, self.isLive, row]) [self.serviceItem, self.isLive, row])
self.updatePreview() self.updatePreview()
else: else:
frame, raw_html = self.serviceItem.get_rendered_frame(row) toDisplay = self.serviceItem.get_rendered_frame(row)
if self.serviceItem.is_text(): if self.serviceItem.is_text():
frame = self.display.text(raw_html) frame = self.display.text(toDisplay)
else: else:
self.display.image(frame) frame = self.display.image(toDisplay)
if isinstance(frame, QtGui.QImage):
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
else:
self.SlidePreview.setPixmap(QtGui.QPixmap(frame))
self.selectedRow = row self.selectedRow = row
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
row) row)
@ -999,4 +1002,3 @@ class SlideController(QtGui.QWidget):
self.video.hide() self.video.hide()
self.SlidePreview.clear() self.SlidePreview.clear()
self.SlidePreview.show() self.SlidePreview.show()

View File

@ -34,9 +34,8 @@ from PyQt4 import QtCore, QtGui
from openlp.core.ui import AmendThemeForm, FileRenameForm from openlp.core.ui import AmendThemeForm, FileRenameForm
from openlp.core.theme import Theme from openlp.core.theme import Theme
from openlp.core.lib import OpenLPToolbar, context_menu_action, \ from openlp.core.lib import OpenLPToolbar, ThemeXML, get_text_file_string, \
ThemeXML, str_to_bool, get_text_file_string, build_icon, Receiver, \ build_icon, Receiver, SettingsManager, translate, check_item_selected
context_menu_separator, SettingsManager, translate, check_item_selected
from openlp.core.utils import AppLocation, get_filesystem_encoding from openlp.core.utils import AppLocation, get_filesystem_encoding
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -267,7 +266,7 @@ class ThemeManager(QtGui.QWidget):
filename = \ filename = \
os.path.split(unicode(oldThemeData.background_filename))[1] os.path.split(unicode(oldThemeData.background_filename))[1]
new_theme.add_background_image(filename) new_theme.add_background_image(filename)
save_to = os.path.join(self.path, theme_name, filename) save_to = os.path.join(self.path, newThemeName, filename)
save_from = oldThemeData.background_filename save_from = oldThemeData.background_filename
new_theme.add_font(unicode(oldThemeData.font_main_name), new_theme.add_font(unicode(oldThemeData.font_main_name),
unicode(oldThemeData.font_main_color), unicode(oldThemeData.font_main_color),

View File

@ -28,7 +28,6 @@ The :mod:`languagemanager` module provides all the translation settings and
language file loading for OpenLP. language file loading for OpenLP.
""" """
import logging import logging
import os
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui

View File

@ -45,13 +45,15 @@ class AlertsPlugin(Plugin):
self.icon = build_icon(u':/plugins/plugin_alerts.png') self.icon = build_icon(u':/plugins/plugin_alerts.png')
self.alertsmanager = AlertsManager(self) self.alertsmanager = AlertsManager(self)
self.manager = Manager(u'alerts', init_schema) self.manager = Manager(u'alerts', init_schema)
self.alertForm = AlertForm(self) visible_name = self.getString(StringContent.VisibleName)
self.alertForm = AlertForm(self, visible_name[u'title'])
def getSettingsTab(self): def getSettingsTab(self):
""" """
Return the settings tab for the Alerts plugin Return the settings tab for the Alerts plugin
""" """
self.alertsTab = AlertsTab(self) visible_name = self.getString(StringContent.VisibleName)
self.alertsTab = AlertsTab(self, visible_name[u'title'])
return self.alertsTab return self.alertsTab
def addToolsMenuItem(self, tools_menu): def addToolsMenuItem(self, tools_menu):
@ -116,3 +118,10 @@ class AlertsPlugin(Plugin):
u'title': translate('AlertsPlugin', 'Alerts') u'title': translate('AlertsPlugin', 'Alerts')
} }
def finalise(self):
"""
Time to tidy up on exit
"""
log.info(u'Alerts Finalising')
self.manager.finalise()
Plugin.finalise(self)

View File

@ -35,7 +35,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
""" """
Provide UI for the alert system Provide UI for the alert system
""" """
def __init__(self, title, visible_title): def __init__(self, plugin, visible_title):
""" """
Initialise the alert form Initialise the alert form
""" """

View File

@ -24,6 +24,6 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # 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. scripture.
""" """

View File

@ -172,3 +172,11 @@ class BiblePlugin(Plugin):
u'tooltip': translate('BiblesPlugin', u'tooltip': translate('BiblesPlugin',
'Add the selected Bible to the service') 'Add the selected Bible to the service')
} }
def finalise(self):
"""
Time to tidy up on exit
"""
log.info(u'Bible Finalising')
self.manager.finalise()
Plugin.finalise(self)

View File

@ -24,6 +24,33 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
from importwizardform import ImportWizardForm """
Forms in OpenLP are made up of two classes. One class holds all the graphical
elements, like buttons and lists, and the other class holds all the functional
code, like slots and loading and saving.
__all__ = ['ImportWizardForm'] The first class, commonly known as the **Dialog** class, is typically named
``Ui_<name>Dialog``. It is a slightly modified version of the class that the
``pyuic4`` command produces from Qt4's .ui file. Typical modifications will be
converting most strings from "" to u'' and using OpenLP's ``translate()``
function for translating strings.
The second class, commonly known as the **Form** class, is typically named
``<name>Form``. This class is the one which is instantiated and used. It uses
dual inheritance to inherit from (usually) QtGui.QDialog and the Ui class
mentioned above, like so::
class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
def __init__(self, parent, manager, bibleplugin):
QtGui.QWizard.__init__(self, parent)
self.setupUi(self)
This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
them separate from the functionality, so that it is easier to recreate the GUI
from the .ui files later if necessary.
"""
from bibleimportform import BibleImportForm
__all__ = ['BibleImportForm']

View File

@ -54,7 +54,7 @@ class WebDownload(object):
return cls.Names[name] return cls.Names[name]
class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): class BibleImportForm(QtGui.QWizard, Ui_BibleImportWizard):
""" """
This is the Bible Import Wizard, which allows easy importing of Bibles This is the Bible Import Wizard, which allows easy importing of Bibles
into OpenLP from other formats like OSIS, CSV and OpenSong. into OpenLP from other formats like OSIS, CSV and OpenSong.
@ -282,7 +282,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
self.LicenseDetailsPage.registerField( self.LicenseDetailsPage.registerField(
u'license_copyright', self.CopyrightEdit) u'license_copyright', self.CopyrightEdit)
self.LicenseDetailsPage.registerField( self.LicenseDetailsPage.registerField(
u'license_permission', self.PermissionEdit) u'license_permissions', self.PermissionsEdit)
def setDefaults(self): def setDefaults(self):
settings = QtCore.QSettings() settings = QtCore.QSettings()
@ -308,8 +308,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
QtCore.QVariant(self.VersionNameEdit.text())) QtCore.QVariant(self.VersionNameEdit.text()))
self.setField(u'license_copyright', self.setField(u'license_copyright',
QtCore.QVariant(self.CopyrightEdit.text())) QtCore.QVariant(self.CopyrightEdit.text()))
self.setField(u'license_permission', self.setField(u'license_permissions',
QtCore.QVariant(self.PermissionEdit.text())) QtCore.QVariant(self.PermissionsEdit.text()))
self.onLocationComboBoxChanged(WebDownload.Crosswalk) self.onLocationComboBoxChanged(WebDownload.Crosswalk)
settings.endGroup() settings.endGroup()
@ -391,8 +391,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
bible_type = self.field(u'source_format').toInt()[0] bible_type = self.field(u'source_format').toInt()[0]
license_version = unicode(self.field(u'license_version').toString()) license_version = unicode(self.field(u'license_version').toString())
license_copyright = unicode(self.field(u'license_copyright').toString()) license_copyright = unicode(self.field(u'license_copyright').toString())
license_permission = \ license_permissions = \
unicode(self.field(u'license_permission').toString()) unicode(self.field(u'license_permissions').toString())
importer = None importer = None
if bible_type == BibleFormat.OSIS: if bible_type == BibleFormat.OSIS:
# Import an OSIS bible # Import an OSIS bible
@ -436,7 +436,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard):
) )
if importer.do_import(): if importer.do_import():
self.manager.save_meta_data(license_version, license_version, self.manager.save_meta_data(license_version, license_version,
license_copyright, license_permission) license_copyright, license_permissions)
self.manager.reload_bibles() self.manager.reload_bibles()
self.ImportProgressLabel.setText( self.ImportProgressLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Finished import.')) translate('BiblesPlugin.ImportWizardForm', 'Finished import.'))

View File

@ -275,14 +275,14 @@ class Ui_BibleImportWizard(object):
self.CopyrightEdit.setObjectName(u'CopyrightEdit') self.CopyrightEdit.setObjectName(u'CopyrightEdit')
self.LicenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.LicenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.CopyrightEdit) self.CopyrightEdit)
self.PermissionLabel = QtGui.QLabel(self.LicenseDetailsPage) self.PermissionsLabel = QtGui.QLabel(self.LicenseDetailsPage)
self.PermissionLabel.setObjectName(u'PermissionLabel') self.PermissionsLabel.setObjectName(u'PermissionsLabel')
self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole, self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.PermissionLabel) self.PermissionsLabel)
self.PermissionEdit = QtGui.QLineEdit(self.LicenseDetailsPage) self.PermissionsEdit = QtGui.QLineEdit(self.LicenseDetailsPage)
self.PermissionEdit.setObjectName(u'PermissionEdit') self.PermissionsEdit.setObjectName(u'PermissionsEdit')
self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole, self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.PermissionEdit) self.PermissionsEdit)
BibleImportWizard.addPage(self.LicenseDetailsPage) BibleImportWizard.addPage(self.LicenseDetailsPage)
self.ImportPage = QtGui.QWizardPage() self.ImportPage = QtGui.QWizardPage()
self.ImportPage.setObjectName(u'ImportPage') self.ImportPage.setObjectName(u'ImportPage')
@ -372,8 +372,8 @@ class Ui_BibleImportWizard(object):
translate('BiblesPlugin.ImportWizardForm', 'Version name:')) translate('BiblesPlugin.ImportWizardForm', 'Version name:'))
self.CopyrightLabel.setText( self.CopyrightLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Copyright:')) translate('BiblesPlugin.ImportWizardForm', 'Copyright:'))
self.PermissionLabel.setText( self.PermissionsLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Permission:')) translate('BiblesPlugin.ImportWizardForm', 'Permissions:'))
self.ImportPage.setTitle( self.ImportPage.setTitle(
translate('BiblesPlugin.ImportWizardForm', 'Importing')) translate('BiblesPlugin.ImportWizardForm', 'Importing'))
self.ImportPage.setSubTitle( self.ImportPage.setSubTitle(

View File

@ -60,22 +60,32 @@ def parse_reference(reference):
and converts it to a reference list, a list of references to be queried and converts it to a reference list, a list of references to be queried
from the Bible database files. from the Bible database files.
BIBLE_REFERENCE regular expression produces the following match groups: The ``BIBLE_REFERENCE`` constant regular expression produces the following
0 This is a special group consisting of the whole string that matched. match groups:
1 [\w ]+ The book the reference is from.
2 [0-9]+ The first (or only) chapter in the reference. 0. (match string)
3 None|[0-9]+ None or the only verse or the first verse in a This is a special group consisting of the whole string that matched.
verse range or the start verse in a chapter range. 1. ``[\w ]+``
4 None|[0-9]+|end None or the end verse of the first verse range or The book the reference is from.
the end chapter of a chapter range. 2. ``[0-9]+``
5 None|[0-9]+ None or the second chapter in multiple The first (or only) chapter in the reference.
(non-ranged) chapters. 3. ``None`` or ``[0-9]+``
6 None|[0-9]+|end None, the start of the second verse range or the ``None``, or the only verse, or the first verse in a verse range or,
end of a chapter range. the start verse in a chapter range.
7 None|[0-9]+|end None or the end of the second verse 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 The reference list is a list of tuples, with each tuple structured like
this:: this::
(book, chapter, start_verse, end_verse) (book, chapter, start_verse, end_verse)
``reference`` ``reference``
@ -154,7 +164,7 @@ def parse_reference(reference):
class SearchResults(object): 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): def __init__(self, book, chapter, verselist):
""" """

View File

@ -64,10 +64,10 @@ class Verse(BaseModel):
def init_schema(url): 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`` ``url``
The database to setup The database to setup.
""" """
session, metadata = init_db(url) session, metadata = init_db(url)
@ -281,23 +281,23 @@ class BibleDB(QtCore.QObject, Manager):
def create_meta(self, key, value): 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`` ``key``
The key for this instance The key for this instance.
``value`` ``value``
The value for this instance The value for this instance.
""" """
log.debug(u'save_meta %s/%s', key, value) log.debug(u'save_meta %s/%s', key, value)
self.save_object(BibleMeta.populate(key=key, value=value)) self.save_object(BibleMeta.populate(key=key, value=value))
def get_book(self, book): def get_book(self, book):
""" """
Return a book object from the database Return a book object from the database.
``book`` ``book``
The name of the book to return The name of the book to return.
""" """
log.debug(u'BibleDb.get_book("%s")', book) log.debug(u'BibleDb.get_book("%s")', book)
db_book = self.get_object_filtered(Book, Book.name.like(book + u'%')) db_book = self.get_object_filtered(Book, Book.name.like(book + u'%'))
@ -353,8 +353,8 @@ class BibleDB(QtCore.QObject, Manager):
QtGui.QMessageBox.information(self.bible_plugin.mediaItem, QtGui.QMessageBox.information(self.bible_plugin.mediaItem,
translate('BiblesPlugin.BibleDB', 'Book not found'), translate('BiblesPlugin.BibleDB', 'Book not found'),
translate('BiblesPlugin.BibleDB', 'The book you requested ' translate('BiblesPlugin.BibleDB', 'The book you requested '
'could not be found in this bible. Please check your ' 'could not be found in this Bible. Please check your '
'spelling and that this is a complete bible not just ' 'spelling and that this is a complete Bible not just '
'one testament.')) 'one testament.'))
return verse_list return verse_list
@ -387,10 +387,10 @@ class BibleDB(QtCore.QObject, Manager):
def get_chapter_count(self, book): def get_chapter_count(self, book):
""" """
Return the number of chapters in a book Return the number of chapters in a book.
``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) log.debug(u'BibleDB.get_chapter_count("%s")', book)
count = self.session.query(Verse.chapter).join(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): def get_verse_count(self, book, chapter):
""" """
Return the number of verses in a chapter Return the number of verses in a chapter.
``book`` ``book``
The book containing the chapter The book containing the chapter.
``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) log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter)
count = self.session.query(Verse).join(Book)\ count = self.session.query(Verse).join(Book)\
@ -423,7 +423,7 @@ class BibleDB(QtCore.QObject, Manager):
def dump_bible(self): 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(u'.........Dumping Bible Database')
log.debug('...............................Books ') log.debug('...............................Books ')

View File

@ -187,16 +187,16 @@ class BGExtract(object):
def get_bible_chapter(self, version, bookname, chapter): 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`` ``version``
The version of the bible like 31 for New International version The version of the bible like 31 for New International version.
``bookname`` ``bookname``
Name of the Book Name of the Book.
``chapter`` ``chapter``
Chapter number Chapter number.
""" """
log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter) log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter)
url_params = urllib.urlencode( url_params = urllib.urlencode(
@ -428,7 +428,7 @@ class HTTPBible(BibleDB):
def get_chapter(self, book, chapter): 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'get_chapter %s, %s', book, chapter)
log.debug(u'source = %s', self.download_source) log.debug(u'source = %s', self.download_source)

View File

@ -137,7 +137,7 @@ class BibleManager(object):
name = bible.get_name() name = bible.get_name()
log.debug(u'Bible Name: "%s"', name) log.debug(u'Bible Name: "%s"', name)
self.db_cache[name] = bible 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, source = self.db_cache[name].get_object(BibleMeta,
u'download source') u'download source')
if source: if source:
@ -181,10 +181,10 @@ class BibleManager(object):
def get_bibles(self): 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') log.debug(u'get_bibles')
return self.db_cache.keys() return self.db_cache
def get_books(self, bible): def get_books(self, bible):
""" """
@ -204,7 +204,7 @@ class BibleManager(object):
def get_chapter_count(self, bible, book): 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) log.debug(u'get_book_chapter_count %s', book)
return self.db_cache[bible].get_chapter_count(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): def get_verse_count(self, bible, book, chapter):
""" """
Returns all the number of verses for a given 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)', log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)',
bible, book, chapter) bible, book, chapter)
@ -254,12 +254,35 @@ class BibleManager(object):
'Book Chapter:Verse-Verse\n' 'Book Chapter:Verse-Verse\n'
'Book Chapter:Verse-Verse,Verse-Verse\n' 'Book Chapter:Verse-Verse,Verse-Verse\n'
'Book Chapter:Verse-Verse,Chapter: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 return None
def save_meta_data(self, bible, version, copyright, permissions): 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', log.debug(u'save_meta data %s,%s, %s,%s',
bible, version, copyright, permissions) bible, version, copyright, permissions)
@ -269,14 +292,14 @@ class BibleManager(object):
def get_meta_data(self, bible, key): 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) log.debug(u'get_meta %s,%s', bible, key)
return self.db_cache[bible].get_object(BibleMeta, key) return self.db_cache[bible].get_object(BibleMeta, key)
def exists(self, name): def exists(self, name):
""" """
Check cache to see if new bible Check cache to see if new bible.
""" """
if not isinstance(name, unicode): if not isinstance(name, unicode):
name = unicode(name) name = unicode(name)
@ -287,3 +310,11 @@ class BibleManager(object):
if bible == name: if bible == name:
return True return True
return False return False
def finalise(self):
"""
Loop through the databases to VACUUM them.
"""
for bible in self.db_cache:
self.db_cache[bible].finalise()

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \
ItemCapabilities, translate ItemCapabilities, translate
from openlp.plugins.bibles.forms import ImportWizardForm from openlp.plugins.bibles.forms import BibleImportForm
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -361,7 +361,7 @@ class BibleMediaItem(MediaManagerItem):
def onImportClick(self): def onImportClick(self):
if not hasattr(self, u'import_wizard'): if not hasattr(self, u'import_wizard'):
self.import_wizard = ImportWizardForm(self, self.parent.manager, self.import_wizard = BibleImportForm(self, self.parent.manager,
self.parent) self.parent)
self.import_wizard.exec_() self.import_wizard.exec_()
self.reloadBibles() self.reloadBibles()
@ -374,7 +374,7 @@ class BibleMediaItem(MediaManagerItem):
self.AdvancedSecondBibleComboBox.clear() self.AdvancedSecondBibleComboBox.clear()
self.QuickSecondBibleComboBox.addItem(u'') self.QuickSecondBibleComboBox.addItem(u'')
self.AdvancedSecondBibleComboBox.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 # load bibles into the combo boxes
first = True first = True
for bible in bibles: for bible in bibles:
@ -497,6 +497,7 @@ class BibleMediaItem(MediaManagerItem):
def onAdvancedSearchButton(self): def onAdvancedSearchButton(self):
log.debug(u'Advanced Search Button pressed') log.debug(u'Advanced Search Button pressed')
self.AdvancedSearchButton.setEnabled(False)
bible = unicode(self.AdvancedVersionComboBox.currentText()) bible = unicode(self.AdvancedVersionComboBox.currentText())
dual_bible = unicode(self.AdvancedSecondBibleComboBox.currentText()) dual_bible = unicode(self.AdvancedSecondBibleComboBox.currentText())
book = unicode(self.AdvancedBookComboBox.currentText()) book = unicode(self.AdvancedBookComboBox.currentText())
@ -529,16 +530,30 @@ class BibleMediaItem(MediaManagerItem):
self.displayResults(bible, dual_bible) self.displayResults(bible, dual_bible)
else: else:
self.displayResults(bible, dual_bible) self.displayResults(bible, dual_bible)
self.AdvancedSearchButton.setEnabled(True)
def onQuickSearchButton(self): def onQuickSearchButton(self):
log.debug(u'Quick Search Button pressed') log.debug(u'Quick Search Button pressed')
self.QuickSearchButton.setEnabled(False)
bible = unicode(self.QuickVersionComboBox.currentText()) bible = unicode(self.QuickVersionComboBox.currentText())
dual_bible = unicode(self.QuickSecondBibleComboBox.currentText()) dual_bible = unicode(self.QuickSecondBibleComboBox.currentText())
text = unicode(self.QuickSearchEdit.text()) text = unicode(self.QuickSearchEdit.text())
if self.QuickSearchComboBox.currentIndex() == 0:
# We are doing a 'Verse Search'.
self.search_results = self.parent.manager.get_verses(bible, text) self.search_results = self.parent.manager.get_verses(bible, text)
if dual_bible: if dual_bible and self.search_results:
self.dual_search_results = self.parent.manager.get_verses( self.dual_search_results = self.parent.manager.get_verses(
dual_bible, text) 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: if self.ClearQuickSearchComboBox.currentIndex() == 0:
self.listView.clear() self.listView.clear()
if self.listView.count() != 0 and self.search_results: if self.listView.count() != 0 and self.search_results:
@ -558,6 +573,7 @@ class BibleMediaItem(MediaManagerItem):
self.displayResults(bible, dual_bible) self.displayResults(bible, dual_bible)
elif self.search_results: elif self.search_results:
self.displayResults(bible, dual_bible) self.displayResults(bible, dual_bible)
self.QuickSearchButton.setEnabled(True)
def displayResults(self, bible, dual_bible=u''): def displayResults(self, bible, dual_bible=u''):
""" """
@ -566,16 +582,16 @@ class BibleMediaItem(MediaManagerItem):
""" """
version = self.parent.manager.get_meta_data(bible, u'Version') version = self.parent.manager.get_meta_data(bible, u'Version')
copyright = self.parent.manager.get_meta_data(bible, u'Copyright') 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: if dual_bible:
dual_version = self.parent.manager.get_meta_data(dual_bible, dual_version = self.parent.manager.get_meta_data(dual_bible,
u'Version') u'Version')
dual_copyright = self.parent.manager.get_meta_data(dual_bible, dual_copyright = self.parent.manager.get_meta_data(dual_bible,
u'Copyright') u'Copyright')
dual_permission = self.parent.manager.get_meta_data(dual_bible, dual_permissions = self.parent.manager.get_meta_data(dual_bible,
u'Permissions') u'Permissions')
if not dual_permission: if not dual_permissions:
dual_permission = u'' dual_permissions = u''
# We count the number of rows which are maybe already present. # We count the number of rows which are maybe already present.
start_count = self.listView.count() start_count = self.listView.count()
for count, verse in enumerate(self.search_results): for count, verse in enumerate(self.search_results):
@ -587,12 +603,12 @@ class BibleMediaItem(MediaManagerItem):
'bible': QtCore.QVariant(bible), 'bible': QtCore.QVariant(bible),
'version': QtCore.QVariant(version.value), 'version': QtCore.QVariant(version.value),
'copyright': QtCore.QVariant(copyright.value), 'copyright': QtCore.QVariant(copyright.value),
'permission': QtCore.QVariant(permission.value), 'permissions': QtCore.QVariant(permissions.value),
'text': QtCore.QVariant(verse.text), 'text': QtCore.QVariant(verse.text),
'dual_bible': QtCore.QVariant(dual_bible), 'dual_bible': QtCore.QVariant(dual_bible),
'dual_version': QtCore.QVariant(dual_version.value), 'dual_version': QtCore.QVariant(dual_version.value),
'dual_copyright': QtCore.QVariant(dual_copyright.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( 'dual_text': QtCore.QVariant(
self.dual_search_results[count].text) self.dual_search_results[count].text)
} }
@ -607,12 +623,12 @@ class BibleMediaItem(MediaManagerItem):
'bible': QtCore.QVariant(bible), 'bible': QtCore.QVariant(bible),
'version': QtCore.QVariant(version.value), 'version': QtCore.QVariant(version.value),
'copyright': QtCore.QVariant(copyright.value), 'copyright': QtCore.QVariant(copyright.value),
'permission': QtCore.QVariant(permission.value), 'permissions': QtCore.QVariant(permissions.value),
'text': QtCore.QVariant(verse.text), 'text': QtCore.QVariant(verse.text),
'dual_bible': QtCore.QVariant(u''), 'dual_bible': QtCore.QVariant(u''),
'dual_version': QtCore.QVariant(u''), 'dual_version': QtCore.QVariant(u''),
'dual_copyright': QtCore.QVariant(u''), 'dual_copyright': QtCore.QVariant(u''),
'dual_permission': QtCore.QVariant(u''), 'dual_permissions': QtCore.QVariant(u''),
'dual_text': QtCore.QVariant(u'') 'dual_text': QtCore.QVariant(u'')
} }
bible_text = u' %s %d:%d (%s)' % (verse.book.name, bible_text = u' %s %d:%d (%s)' % (verse.book.name,
@ -658,20 +674,20 @@ class BibleMediaItem(MediaManagerItem):
bible = self._decodeQtObject(bitem, 'bible') bible = self._decodeQtObject(bitem, 'bible')
version = self._decodeQtObject(bitem, 'version') version = self._decodeQtObject(bitem, 'version')
copyright = self._decodeQtObject(bitem, 'copyright') copyright = self._decodeQtObject(bitem, 'copyright')
permission = self._decodeQtObject(bitem, 'permission') permissions = self._decodeQtObject(bitem, 'permissions')
text = self._decodeQtObject(bitem, 'text') text = self._decodeQtObject(bitem, 'text')
dual_bible = self._decodeQtObject(bitem, 'dual_bible') dual_bible = self._decodeQtObject(bitem, 'dual_bible')
dual_version = self._decodeQtObject(bitem, 'dual_version') dual_version = self._decodeQtObject(bitem, 'dual_version')
dual_copyright = self._decodeQtObject(bitem, 'dual_copyright') 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') dual_text = self._decodeQtObject(bitem, 'dual_text')
verse_text = self.formatVerse(old_chapter, chapter, verse) 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: if footer not in raw_footer:
raw_footer.append(footer) raw_footer.append(footer)
if dual_bible: if dual_bible:
footer = u'%s (%s %s %s)' % (book, dual_version, dual_copyright, footer = u'%s (%s %s %s)' % (book, dual_version, dual_copyright,
dual_permission) dual_permissions)
if footer not in raw_footer: if footer not in raw_footer:
raw_footer.append(footer) raw_footer.append(footer)
bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text, bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text,

View File

@ -6,8 +6,8 @@ Deut,Deuteronomy,Deut
Josh,Joshua,Josh Josh,Joshua,Josh
Judg,Judges,Judg Judg,Judges,Judg
Ruth,Ruth,Ruth Ruth,Ruth,Ruth
1Sam,1 Samual,1Sam 1Sam,1 Samuel,1Sam
2Sam,2 Samual,2Sam 2Sam,2 Samuel,2Sam
1Kgs,1 Kings,1Kgs 1Kgs,1 Kings,1Kgs
2Kgs,2 Kings,2Kgs 2Kgs,2 Kings,2Kgs
1Chr,1 Chronicles,1Chr 1Chr,1 Chronicles,1Chr

1 Gen Genesis Gen
6 Josh Joshua Josh
7 Judg Judges Judg
8 Ruth Ruth Ruth
9 1Sam 1 Samual 1 Samuel 1Sam
10 2Sam 2 Samual 2 Samuel 2Sam
11 1Kgs 1 Kings 1Kgs
12 2Kgs 2 Kings 2Kgs
13 1Chr 1 Chronicles 1Chr

View File

@ -49,8 +49,8 @@ class CustomPlugin(Plugin):
def __init__(self, plugin_helpers): def __init__(self, plugin_helpers):
Plugin.__init__(self, u'Custom', u'1.9.3', plugin_helpers) Plugin.__init__(self, u'Custom', u'1.9.3', plugin_helpers)
self.weight = -5 self.weight = -5
self.custommanager = Manager(u'custom', init_schema) self.manager = Manager(u'custom', init_schema)
self.edit_custom_form = EditCustomForm(self.custommanager) self.edit_custom_form = EditCustomForm(self.manager)
self.icon_path = u':/plugins/plugin_custom.png' self.icon_path = u':/plugins/plugin_custom.png'
self.icon = build_icon(self.icon_path) self.icon = build_icon(self.icon_path)
@ -160,3 +160,11 @@ class CustomPlugin(Plugin):
u'tooltip': translate('CustomsPlugin', u'tooltip': translate('CustomsPlugin',
'Add the selected Custom to the service') 'Add the selected Custom to the service')
} }
def finalise(self):
"""
Time to tidy up on exit
"""
log.info(u'Custom Finalising')
self.manager.finalise()
Plugin.finalise(self)

View File

@ -110,6 +110,7 @@ class Ui_CustomEditDialog(object):
self.titleEdit.setObjectName(u'titleEdit') self.titleEdit.setObjectName(u'titleEdit')
self.horizontalLayout.addWidget(self.titleEdit) self.horizontalLayout.addWidget(self.titleEdit)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
self.retranslateUi(customEditDialog) self.retranslateUi(customEditDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
customEditDialog.accept) customEditDialog.accept)

View File

@ -41,7 +41,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
Class documentation goes here. Class documentation goes here.
""" """
log.info(u'Custom Editor loaded') log.info(u'Custom Editor loaded')
def __init__(self, custommanager, parent=None): def __init__(self, manager, parent=None):
""" """
Constructor Constructor
""" """
@ -74,7 +74,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_list'), self.loadThemes) QtCore.SIGNAL(u'theme_update_list'), self.loadThemes)
# Create other objects and forms. # Create other objects and forms.
self.custommanager = custommanager self.manager = manager
self.editSlideForm = EditCustomSlideForm(self) self.editSlideForm = EditCustomSlideForm(self)
self.initialise() self.initialise()
@ -115,7 +115,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.customSlide = CustomSlide() self.customSlide = CustomSlide()
self.initialise() self.initialise()
if id != 0: if id != 0:
self.customSlide = self.custommanager.get_object(CustomSlide, id) self.customSlide = self.manager.get_object(CustomSlide, id)
self.titleEdit.setText(self.customSlide.title) self.titleEdit.setText(self.customSlide.title)
self.creditEdit.setText(self.customSlide.credits) self.creditEdit.setText(self.customSlide.credits)
customXML = CustomXMLParser(self.customSlide.text) customXML = CustomXMLParser(self.customSlide.text)
@ -168,7 +168,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
u'utf-8') u'utf-8')
self.customSlide.theme_name = unicode(self.themeComboBox.currentText(), self.customSlide.theme_name = unicode(self.themeComboBox.currentText(),
u'utf-8') u'utf-8')
return self.custommanager.save_object(self.customSlide) return self.manager.save_object(self.customSlide)
def onUpButtonPressed(self): def onUpButtonPressed(self):
selectedRow = self.slideListView.currentRow() selectedRow = self.slideListView.currentRow()

View File

@ -28,7 +28,6 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, translate
from editcustomslidedialog import Ui_CustomSlideEditDialog from editcustomslidedialog import Ui_CustomSlideEditDialog
log = logging.getLogger(__name__) log = logging.getLogger(__name__)

View File

@ -56,6 +56,7 @@ class CustomMediaItem(MediaManagerItem):
# Holds information about whether the edit is remotly triggered and # Holds information about whether the edit is remotly triggered and
# which Custom is required. # which Custom is required.
self.remoteCustom = -1 self.remoteCustom = -1
self.manager = parent.manager
def addEndHeaderBar(self): def addEndHeaderBar(self):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
@ -71,7 +72,7 @@ class CustomMediaItem(MediaManagerItem):
MediaManagerItem.requiredIcons(self) MediaManagerItem.requiredIcons(self)
def initialise(self): def initialise(self):
self.loadCustomListView(self.parent.custommanager.get_all_objects( self.loadCustomListView(self.manager.get_all_objects(
CustomSlide, order_by_ref=CustomSlide.title)) CustomSlide, order_by_ref=CustomSlide.title))
#Called to redisplay the song list screen edith from a search #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 #or from the exit of the Song edit dialog. If remote editing is active
@ -106,7 +107,7 @@ class CustomMediaItem(MediaManagerItem):
type of display is required. type of display is required.
""" """
fields = customid.split(u':') fields = customid.split(u':')
valid = self.parent.custommanager.get_object(CustomSlide, fields[1]) valid = self.manager.get_object(CustomSlide, fields[1])
if valid: if valid:
self.remoteCustom = fields[1] self.remoteCustom = fields[1]
self.remoteTriggered = fields[0] self.remoteTriggered = fields[0]

View File

@ -166,9 +166,8 @@ class ImageMediaItem(MediaManagerItem):
for item in items: for item in items:
bitem = self.listView.item(item.row()) bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
frame = QtGui.QImage(unicode(filename))
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
service_item.add_from_image(path, name, frame) service_item.add_from_image(filename, name)
return True return True
else: else:
return False return False
@ -185,7 +184,8 @@ class ImageMediaItem(MediaManagerItem):
for item in items: for item in items:
bitem = self.listView.item(item.row()) bitem = self.listView.item(item.row())
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString()) filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
self.parent.liveController.display.image(filename) (path, name) = os.path.split(filename)
self.parent.liveController.display.directImage(name, filename)
self.resetButton.setVisible(True) self.resetButton.setVisible(True)
def onPreviewClick(self): def onPreviewClick(self):

View File

@ -169,7 +169,8 @@ class ImpressController(PresentationController):
try: try:
return Dispatch(u'com.sun.star.ServiceManager') return Dispatch(u'com.sun.star.ServiceManager')
except pywintypes.com_error: except pywintypes.com_error:
log.exception(u'Failed to get COM service manager') log.warn(u'Failed to get COM service manager. '
u'Impress Controller has been disabled')
return None return None
def kill(self): def kill(self):

View File

@ -143,11 +143,14 @@ class PowerpointDocument(PresentationDocument):
def create_thumbnails(self): def create_thumbnails(self):
""" """
Create the thumbnail images for the current presentation. 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() self.presentation.Slides[n].Copy()
thumbnail = QApplication.clipboard.image() 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(): if self.check_thumbnails():
return return
@ -156,9 +159,8 @@ class PowerpointDocument(PresentationDocument):
def close_presentation(self): def close_presentation(self):
""" """
Close presentation and clean up objects Close presentation and clean up objects. This is triggered by a new
Triggerent by new object being added to SlideController orOpenLP object being added to SlideController or OpenLP being shut down.
being shut down
""" """
log.debug(u'ClosePresentation') log.debug(u'ClosePresentation')
if self.presentation: if self.presentation:
@ -171,7 +173,7 @@ class PowerpointDocument(PresentationDocument):
def is_loaded(self): def is_loaded(self):
""" """
Returns true if a presentation is loaded Returns ``True`` if a presentation is loaded.
""" """
try: try:
if not self.controller.process.Visible: if not self.controller.process.Visible:
@ -187,7 +189,7 @@ class PowerpointDocument(PresentationDocument):
def is_active(self): 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(): if not self.is_loaded():
return False return False
@ -202,7 +204,7 @@ class PowerpointDocument(PresentationDocument):
def unblank_screen(self): def unblank_screen(self):
""" """
Unblanks (restores) the presentationn Unblanks (restores) the presentation.
""" """
self.presentation.SlideShowSettings.Run() self.presentation.SlideShowSettings.Run()
self.presentation.SlideShowWindow.View.State = 1 self.presentation.SlideShowWindow.View.State = 1
@ -210,13 +212,13 @@ class PowerpointDocument(PresentationDocument):
def blank_screen(self): def blank_screen(self):
""" """
Blanks the screen Blanks the screen.
""" """
self.presentation.SlideShowWindow.View.State = 3 self.presentation.SlideShowWindow.View.State = 3
def is_blank(self): def is_blank(self):
""" """
Returns true if screen is blank Returns ``True`` if screen is blank.
""" """
if self.is_active(): if self.is_active():
return self.presentation.SlideShowWindow.View.State == 3 return self.presentation.SlideShowWindow.View.State == 3
@ -225,14 +227,14 @@ class PowerpointDocument(PresentationDocument):
def stop_presentation(self): 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() self.presentation.SlideShowWindow.View.Exit()
if os.name == u'nt': if os.name == u'nt':
def start_presentation(self): 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 #SlideShowWindow measures its size/position by points, not pixels
try: try:
@ -254,40 +256,40 @@ class PowerpointDocument(PresentationDocument):
def get_slide_number(self): def get_slide_number(self):
""" """
Returns the current slide number Returns the current slide number.
""" """
return self.presentation.SlideShowWindow.View.CurrentShowPosition return self.presentation.SlideShowWindow.View.CurrentShowPosition
def get_slide_count(self): def get_slide_count(self):
""" """
Returns total number of slides Returns total number of slides.
""" """
return self.presentation.Slides.Count return self.presentation.Slides.Count
def goto_slide(self, slideno): 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) self.presentation.SlideShowWindow.View.GotoSlide(slideno)
def next_step(self): 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() self.presentation.SlideShowWindow.View.Next()
def previous_step(self): 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() self.presentation.SlideShowWindow.View.Previous()
def get_slide_text(self, slide_no): def get_slide_text(self, slide_no):
""" """
Returns the text on the slide Returns the text on the slide.
``slide_no`` ``slide_no``
The slide the text is required for, starting at 1 The slide the text is required for, starting at 1.
""" """
text = '' text = ''
shapes = self.presentation.Slides(slide_no).Shapes shapes = self.presentation.Slides(slide_no).Shapes
@ -299,10 +301,10 @@ class PowerpointDocument(PresentationDocument):
def get_slide_notes(self, slide_no): def get_slide_notes(self, slide_no):
""" """
Returns the text on the slide Returns the text on the slide.
``slide_no`` ``slide_no``
The slide the notes are required for, starting at 1 The slide the notes are required for, starting at 1.
""" """
text = '' text = ''
shapes = self.presentation.Slides(slide_no).NotesPage.Shapes shapes = self.presentation.Slides(slide_no).NotesPage.Shapes

View File

@ -37,16 +37,21 @@ log = logging.getLogger(__name__)
class PresentationController(object): class PresentationController(object):
""" """
Base class for presentation controllers to inherit from This class is used to control interactions with presentation applications
Class to control interactions with presentations. by creating a runtime environment. This is a base class for presentation
It creates the runtime environment controllers to inherit from.
To create a new controller, take a copy of this file and name it
so it ends in controller.py, i.e. foobarcontroller.py To create a new controller, take a copy of this file and name it so it ends
Make sure it inherits PresentationController with ``controller.py``, i.e. ``foobarcontroller.py``. Make sure it inherits
Then fill in the blanks. If possible try and make sure it loads :class:`~openlp.plugins.presentations.lib.presentationcontroller.PresentationController`,
on all platforms, using for example os.name checks, although and then fill in the blanks. If possible try to make sure it loads on all
__init__, check_available and presentation_deleted should always work. platforms, usually by using :mod:``os.name`` checks, although
See impresscontroller, powerpointcontroller or pptviewcontroller ``__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. for examples.
**Basic Attributes** **Basic Attributes**

View File

@ -24,10 +24,37 @@
# Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Temple Place, Suite 330, Boston, MA 02111-1307 USA #
############################################################################### ###############################################################################
"""
Forms in OpenLP are made up of two classes. One class holds all the graphical
elements, like buttons and lists, and the other class holds all the functional
code, like slots and loading and saving.
The first class, commonly known as the **Dialog** class, is typically named
``Ui_<name>Dialog``. It is a slightly modified version of the class that the
``pyuic4`` command produces from Qt4's .ui file. Typical modifications will be
converting most strings from "" to u'' and using OpenLP's ``translate()``
function for translating strings.
The second class, commonly known as the **Form** class, is typically named
``<name>Form``. This class is the one which is instantiated and used. It uses
dual inheritance to inherit from (usually) QtGui.QDialog and the Ui class
mentioned above, like so::
class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
them separate from the functionality, so that it is easier to recreate the GUI
from the .ui files later if necessary.
"""
from authorsform import AuthorsForm from authorsform import AuthorsForm
from topicsform import TopicsForm from topicsform import TopicsForm
from songbookform import SongBookForm from songbookform import SongBookForm
from editverseform import EditVerseForm from editverseform import EditVerseForm
from editsongform import EditSongForm from editsongform import EditSongForm
from songmaintenanceform import SongMaintenanceForm from songmaintenanceform import SongMaintenanceForm
from songimportform import ImportWizardForm from songimportform import SongImportForm

View File

@ -483,6 +483,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.VerseListWidget.resizeRowsToContents() self.VerseListWidget.resizeRowsToContents()
self.VerseListWidget.repaint() self.VerseListWidget.repaint()
self.tagRows() self.tagRows()
self.VerseEditButton.setEnabled(False)
self.VerseDeleteButton.setEnabled(False)
def onVerseDeleteButtonClicked(self): def onVerseDeleteButtonClicked(self):
self.VerseListWidget.removeRow(self.VerseListWidget.currentRow()) self.VerseListWidget.removeRow(self.VerseListWidget.currentRow())

View File

@ -53,6 +53,9 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
QtCore.QObject.connect(self.verseTextEdit, QtCore.QObject.connect(self.verseTextEdit,
QtCore.SIGNAL(u'cursorPositionChanged()'), QtCore.SIGNAL(u'cursorPositionChanged()'),
self.onCursorPositionChanged) self.onCursorPositionChanged)
QtCore.QObject.connect(self.verseTypeComboBox,
QtCore.SIGNAL(u'currentIndexChanged(int)'),
self.onVerseTypeComboBoxChanged)
self.verse_regex = re.compile(r'---\[([-\w]+):([\d]+)\]---') self.verse_regex = re.compile(r'---\[([-\w]+):([\d]+)\]---')
def contextMenu(self, point): def contextMenu(self, point):
@ -66,27 +69,43 @@ class EditVerseForm(QtGui.QDialog, Ui_EditVerseDialog):
self.verseTextEdit.setFocus() self.verseTextEdit.setFocus()
def onInsertButtonClicked(self): def onInsertButtonClicked(self):
if self.verseTextEdit.textCursor().columnNumber() != 0:
self.verseTextEdit.insertPlainText(u'\n')
verse_type = self.verseTypeComboBox.currentIndex() verse_type = self.verseTypeComboBox.currentIndex()
if verse_type == VerseType.Verse: if VerseType.to_string(verse_type) is not None:
self.insertVerse(VerseType.to_string(VerseType.Verse), self.insertVerse(VerseType.to_string(verse_type),
self.verseNumberBox.value()) self.verseNumberBox.value())
elif verse_type == VerseType.Chorus:
self.insertVerse(VerseType.to_string(VerseType.Chorus), def onVerseTypeComboBoxChanged(self):
self.verseNumberBox.value()) """
elif verse_type == VerseType.Bridge: Adjusts the verse number SpinBox in regard to the selected verse type
self.insertVerse(VerseType.to_string(VerseType.Bridge)) and the cursor's position.
elif verse_type == VerseType.PreChorus: """
self.insertVerse(VerseType.to_string(VerseType.PreChorus)) position = self.verseTextEdit.textCursor().position()
elif verse_type == VerseType.Intro: text = unicode(self.verseTextEdit.toPlainText())
self.insertVerse(VerseType.to_string(VerseType.Intro)) verse_type = VerseType.to_string(self.verseTypeComboBox.currentIndex())
elif verse_type == VerseType.Ending: if not text:
self.insertVerse(VerseType.to_string(VerseType.Ending)) return
elif verse_type == VerseType.Other: position = text.rfind(u'---[%s' % verse_type, 0, position)
self.insertVerse(VerseType.to_string(VerseType.Other)) 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): 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() position = self.verseTextEdit.textCursor().position()
text = unicode(self.verseTextEdit.toPlainText()) text = unicode(self.verseTextEdit.toPlainText())
if not text: if not text:

View File

@ -35,7 +35,7 @@ from openlp.plugins.songs.lib.importer import SongFormat
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class ImportWizardForm(QtGui.QWizard, Ui_SongImportWizard): class SongImportForm(QtGui.QWizard, Ui_SongImportWizard):
""" """
This is the Song Import Wizard, which allows easy importing of Songs This is the Song Import Wizard, which allows easy importing of Songs
into OpenLP from other formats like OpenLyrics, OpenSong and CCLI. into OpenLP from other formats like OpenLyrics, OpenSong and CCLI.

View File

@ -38,9 +38,9 @@ class CCLIFileImportError(Exception):
class CCLIFileImport(SongImport): class CCLIFileImport(SongImport):
""" """
The :class:`CCLIFileImport` class provides OpenLP with the The :class:`CCLIFileImport` class provides OpenLP with the ability to
ability to import CCLI SongSelect song files in both .txt and import CCLI SongSelect song files in both .txt and .usr formats.
.usr formats. See http://www.ccli.com See http://www.ccli.com/ for more details.
""" """
def __init__(self, manager, **kwargs): def __init__(self, manager, **kwargs):
@ -49,6 +49,7 @@ class CCLIFileImport(SongImport):
``manager`` ``manager``
The song manager for the running OpenLP installation. The song manager for the running OpenLP installation.
``filenames`` ``filenames``
The files to be imported. The files to be imported.
""" """
@ -97,7 +98,7 @@ class CCLIFileImport(SongImport):
def do_import_usr_file(self, textList): 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 with the ability to import CCLI SongSelect songs in
*USR* file format *USR* file format
@ -105,6 +106,7 @@ class CCLIFileImport(SongImport):
An array of strings containing the usr file content. An array of strings containing the usr file content.
**SongSelect .usr file format** **SongSelect .usr file format**
``[File]`` ``[File]``
USR file format first line USR file format first line
``Type=`` ``Type=``
@ -140,6 +142,7 @@ class CCLIFileImport(SongImport):
Contains the songs various lyrics in order as shown by the Contains the songs various lyrics in order as shown by the
*Fields* description *Fields* description
e.g. *Words=Above all powers....* [/n = CR, /n/t = CRLF] e.g. *Words=Above all powers....* [/n = CR, /n/t = CRLF]
""" """
log.debug(u'USR file text: %s', textList) log.debug(u'USR file text: %s', textList)
lyrics = [] lyrics = []
@ -191,48 +194,32 @@ class CCLIFileImport(SongImport):
def do_import_txt_file(self, textList): 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 with the ability to import CCLI SongSelect songs in
*TXT* file format *TXT* file format
``textList`` ``textList``
An array of strings containing the txt file content. An array of strings containing the txt file content.
**SongSelect .txt file format** SongSelect .txt file format::
``Song Title``
Contains the song title
Song Title # Contains the song title
<Empty line> <Empty line>
Verse type and number # e.g. Verse 1, Chorus 1
``Title of following verse/chorus and number`` Verse lyrics
e.g. Verse 1, Chorus 1
``Verse/Chorus lyrics``
<Empty line> <Empty line>
<Empty line> <Empty line>
Verse type and number (repeats)
``Title of next verse/chorus (repeats)`` Verse lyrics
``Verse/Chorus lyrics``
<Empty line> <Empty line>
<Empty line> <Empty line>
Song CCLI number # e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885)
``Song CCLI Number`` Song copyright # e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing
e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885) Song authors # e.g. Lenny LeBlanc | Paul Baloche
``Song Copyright`` Licencing info # e.g. For use solely with the SongSelect Terms of Use.
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 All rights Reserved. www.ccli.com
``CCLI Licence number of user`` CCLI Licence number of user # e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14
""" """
log.debug(u'TXT file text: %s', textList) log.debug(u'TXT file text: %s', textList)
self.set_defaults() self.set_defaults()

View File

@ -28,14 +28,13 @@ The :mod:`ewimport` module provides the functionality for importing
EasyWorship song databases into the current installation database. EasyWorship song databases into the current installation database.
""" """
import sys
import os import os
import struct import struct
from openlp.core.lib import translate from openlp.core.lib import translate
from songimport import SongImport from songimport import SongImport
def strip_rtf(blob): def strip_rtf(blob, encoding):
depth = 0 depth = 0
control = False control = False
clear_text = [] clear_text = []
@ -69,12 +68,42 @@ def strip_rtf(blob):
if control_str == 'par' or control_str == 'line': if control_str == 'par' or control_str == 'line':
clear_text.append(u'\n') clear_text.append(u'\n')
elif control_str == 'tab': 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] == '\'': 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)) 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[:] del control_word[:]
if c == '\\' and new_control: if c == '\\' and new_control:
control = True control = True
@ -126,6 +155,30 @@ class EasyWorshipSongImport(SongImport):
db_file.close() db_file.close()
self.memo_file.close() self.memo_file.close()
return False 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 # There does not appear to be a _reliable_ way of getting the number
# of songs/records, so let's use file blocks for measuring progress. # of songs/records, so let's use file blocks for measuring progress.
total_blocks = (db_size - header_size) / (block_size * 1024) total_blocks = (db_size - header_size) / (block_size * 1024)
@ -139,7 +192,8 @@ class EasyWorshipSongImport(SongImport):
field_names.pop() field_names.pop()
field_descs = [] field_descs = []
for i, field_name in enumerate(field_names): for i, field_name in enumerate(field_names):
field_type, field_size = struct.unpack_from('BB', field_info, i * 2) field_type, field_size = struct.unpack_from('BB',
field_info, i * 2)
field_descs.append(FieldDescEntry(field_name, field_type, field_descs.append(FieldDescEntry(field_name, field_type,
field_size)) field_size))
self.set_record_struct(field_descs) self.set_record_struct(field_descs)
@ -204,7 +258,7 @@ class EasyWorshipSongImport(SongImport):
self.add_author(author_name.strip()) self.add_author(author_name.strip())
if words: if words:
# Format the lyrics # Format the lyrics
words = strip_rtf(words) words = strip_rtf(words, self.encoding)
for verse in words.split(u'\n\n'): for verse in words.split(u'\n\n'):
self.add_verse(verse.strip(), u'V') self.add_verse(verse.strip(), u'V')
if self.stop_import_flag: if self.stop_import_flag:
@ -263,7 +317,7 @@ class EasyWorshipSongImport(SongImport):
# Format the field depending on the field type # Format the field depending on the field type
if field_desc.type == 1: if field_desc.type == 1:
# string # string
return field.rstrip('\0').decode(u'windows-1252') return field.rstrip('\0').decode(self.encoding)
elif field_desc.type == 3: elif field_desc.type == 3:
# 16-bit int # 16-bit int
return field ^ 0x8000 return field ^ 0x8000
@ -277,7 +331,7 @@ class EasyWorshipSongImport(SongImport):
# Memo or Blob # Memo or Blob
block_start, blob_size = \ block_start, blob_size = \
struct.unpack_from('<II', field, len(field)-10) struct.unpack_from('<II', field, len(field)-10)
sub_block = block_start & 0xff; sub_block = block_start & 0xff
block_start &= ~0xff block_start &= ~0xff
self.memo_file.seek(block_start) self.memo_file.seek(block_start)
memo_block_type, = struct.unpack('b', self.memo_file.read(1)) memo_block_type, = struct.unpack('b', self.memo_file.read(1))
@ -285,12 +339,12 @@ class EasyWorshipSongImport(SongImport):
self.memo_file.seek(8, os.SEEK_CUR) self.memo_file.seek(8, os.SEEK_CUR)
elif memo_block_type == 3: elif memo_block_type == 3:
if sub_block > 63: if sub_block > 63:
return u''; return u''
self.memo_file.seek(11 + (5 * sub_block), os.SEEK_CUR) self.memo_file.seek(11 + (5 * sub_block), os.SEEK_CUR)
sub_block_start, = struct.unpack('B', self.memo_file.read(1)) sub_block_start, = struct.unpack('B', self.memo_file.read(1))
self.memo_file.seek(block_start + (sub_block_start * 16)) self.memo_file.seek(block_start + (sub_block_start * 16))
else: else:
return u''; return u''
return self.memo_file.read(blob_size) return self.memo_file.read(blob_size)
else: else:
return 0 return 0

View File

@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \ from openlp.core.lib import MediaManagerItem, BaseListWithDnD, Receiver, \
ItemCapabilities, translate, check_item_selected ItemCapabilities, translate, check_item_selected
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
ImportWizardForm SongImportForm
from openlp.plugins.songs.lib import SongXMLParser from openlp.plugins.songs.lib import SongXMLParser
from openlp.plugins.songs.lib.db import Author, Song from openlp.plugins.songs.lib.db import Author, Song
@ -254,7 +254,7 @@ class SongMediaItem(MediaManagerItem):
def onImportClick(self): def onImportClick(self):
if not hasattr(self, u'import_wizard'): if not hasattr(self, u'import_wizard'):
self.import_wizard = ImportWizardForm(self, self.parent) self.import_wizard = SongImportForm(self, self.parent)
self.import_wizard.exec_() self.import_wizard.exec_()
Receiver.send_message(u'songs_load_list') Receiver.send_message(u'songs_load_list')

View File

@ -29,7 +29,6 @@ The :mod:`songbeamerimport` module provides the functionality for importing
""" """
import logging import logging
import os import os
import re
import chardet import chardet
import codecs import codecs
@ -130,8 +129,7 @@ class SongBeamerImport(SongImport):
def parse_tags(self, line): def parse_tags(self, line):
tag_val = line.split('=') tag_val = line.split('=')
if len(tag_val[0]) == 0 or \ if len(tag_val[0]) == 0 or len(tag_val[1]) == 0:
len(tag_val[1]) == 0:
return True return True
if tag_val[0] == '#(c)': if tag_val[0] == '#(c)':
self.add_copyright(tag_val[1]) self.add_copyright(tag_val[1])
@ -228,8 +226,7 @@ class SongBeamerImport(SongImport):
def check_verse_marks(self, line): def check_verse_marks(self, line):
marks = line.split(' ') marks = line.split(' ')
if len(marks) <= 2 and \ if len(marks) <= 2 and marks[0] in SongBeamerTypes.MarkTypes:
marks[0] in SongBeamerTypes.MarkTypes:
self.current_verse_type = SongBeamerTypes.MarkTypes[marks[0]] self.current_verse_type = SongBeamerTypes.MarkTypes[marks[0]]
if len(marks) == 2: if len(marks) == 2:
#TODO: may check, because of only digits are allowed #TODO: may check, because of only digits are allowed

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