This commit is contained in:
Andreas Preikschat 2010-12-23 07:04:58 +01:00
commit 3ba1b9064c
242 changed files with 36648 additions and 102094 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,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.append(os.path.abspath(os.path.join('..', '..')))
sys.path.insert(0, os.path.abspath(os.path.join('..', '..', '..')))
# -- General configuration -----------------------------------------------------
@ -39,7 +39,7 @@ master_doc = 'index'
# General information about the project.
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
# |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.
version = '2.0'
# 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
# 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
# "<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.
#html_short_title = None
@ -166,7 +166,7 @@ html_static_path = ['_static']
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'OpenLPdoc'
htmlhelp_basename = 'OpenLP-2.0-api'
# -- Options for LaTeX output --------------------------------------------------
@ -180,7 +180,7 @@ htmlhelp_basename = 'OpenLPdoc'
# 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 Documentation',
('index', 'OpenLP.tex', u'OpenLP 2.0 Developer API',
u'Raoul Snyman', 'manual'),
]

View File

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

View File

@ -1,7 +1,7 @@
.. _core-lib:
:mod:`lib` Module
=================
Object Library
==============
.. automodule:: openlp.core.lib
:members:
@ -60,12 +60,6 @@
.. autoclass:: openlp.core.lib.settingstab.SettingsTab
:members:
:mod:`ThemeXML`
---------------
.. autoclass:: openlp.core.lib.themexmlhandler.ThemeXML
:members:
: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::
:maxdepth: 2
openlp
core/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 which 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,26 @@
.. 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
mediamanager
songs
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

View File

@ -0,0 +1,26 @@
=============
Media Manager
=============
Once you get your system set up for OpenLP you will be ready to add content to
your setup. This will all happen through the **Media Manager**. The
`Media Manager` contains all the bibles, songs, presentations, media, and
everything else that you will project through OpenLP.
Enabling the Plugins
--------------------
You may need to enable the plugins that came with OpenLP. As you can see below
this is what the `Media Manager` looks like with all the plugins enabled.
.. image:: pics/mediamanager.png
To enable the plugins navigate to :menuselection:`Settings --> Plugins` or
press `F7`. You will then want to click on the plugin to the left that you want
to enable and select **active** from the drop down box to the right.
.. image:: pics/plugins.png
Now you should be ready to add content to OpenLP check out the section of this
guide on the individual plugins.

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 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: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 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: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 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: 24 KiB

View File

@ -0,0 +1,100 @@
=====
Songs
=====
Managing your songs in OpenLP is a relatively simple process. There are also
converters provided to get data from other formats into OpenLP.
Song Importer
=============
If you are using an earlier version of OpenLP or come from another software
package, you may be able to convert your existing database to work in OpenLP
2.0. To access the Song Importer :menuselection:`File --> Import --> Song`.
You will then see the Song Importer window, then click :guilabel:`Next`.
.. image:: pics/songimporter.png
After choosing :guilabel:`Next` you can then select from the various types of
software that OpenLP will convert songs from.
.. image:: pics/songimporterchoices.png
Then click on the file folder icon to choose the file of the song database you
want to import. See the following sections for information on the different
formats that OpenLP will import.
Importing from OpenLP Version 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Converting from OpenLP Version 1 is a pretty simple process. You will first
need to locate your version 1 database file.
Windows XP::
C:\Documents and Settings\All Users\Application Data\openlp.org\Data\songs.olp
Windows Vista / Windows 7::
C:\ProgramData\openlp.org\Data\songs.olp
After clicking :guilabel:`Next` your conversion should be complete.
.. image:: pics/finishedimport.png
Then press :guilabel:`Finish` and you should now be ready to use your OpenLP
version one songs.
Importing from OpenSong
^^^^^^^^^^^^^^^^^^^^^^^
Converting from OpenSong you will need to locate your songs database. In the
later versions of OpenSong you are asked to define the location of this. The
songs will be located in a folder named :guilabel:`Songs`. This folder should
contain files with all your songs in them without a file extension. (file.xxx).
When you have located this folder you will then need to select the songs from
the folder.
.. image:: pics/selectsongs.png
On most operating systems to select all the songs, first select the first song
in the lest then press shift and select the last song in the list. After this
press :guilabel:`Next` and you should see that your import has been successful.
.. image:: pics/finishedimport.png
Press :guilabel:`Finish` and you will now be ready to use your songs imported
from OpenSong.
Importing from CCLI Song Select
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To import from CCLI Song Select you must be a CCLI Subscriber and also a
subscriber of the Song Select service. For info on that go to:
http://www.ccli.com
The first step for importing from CCLI Song Select is to log into your account.
Then search for your desired song. For this example we will be adding the song
"Amazing Grace".
.. image:: pics/songselectsongsearch.png
For the song you are searching for select `lyrics` This should take you to a
page displaying the lyrics and copyright info for your song.
.. image:: pics/songselectlyrics.png
Next, hover over the :guilabel:`Lyrics` menu from the upper right corner. Then
choose either the .txt or .usr file. You will then be asked to chose a download
location if your browser does not automatically select that for you. Select
this file from the OpenLP import window and then click :guilabel:`Next` You can
also select multiple songs for import at once on most operating systems by
selecting the first item in the list then holding shift select the last item in
the list. When finished you should see that your import has completed.
.. image:: pics/finishedimport.png
Press :guilabel:`Finish` and you will now be ready to use your songs imported
from CCLI SongSelect.

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
from optparse import OptionParser
from traceback import format_exception
from subprocess import Popen, PIPE
from PyQt4 import QtCore, QtGui
@ -71,6 +72,84 @@ class OpenLP(QtGui.QApplication):
"""
log.info(u'OpenLP Application Loaded')
def _get_version(self):
"""
Load and store current Application Version
"""
if u'--dev-version' in sys.argv:
# If we're running the dev version, let's use bzr to get the version
try:
# If bzrlib is availble, use it
from bzrlib.branch import Branch
b = Branch.open_containing('.')[0]
b.lock_read()
try:
# Get the branch's latest revision number.
revno = b.revno()
# Convert said revision number into a bzr revision id.
revision_id = b.dotted_revno_to_revision_id((revno,))
# Get a dict of tags, with the revision id as the key.
tags = b.tags.get_reverse_tag_dict()
# Check if the latest
if revision_id in tags:
full_version = u'%s' % tags[revision_id][0]
else:
full_version = '%s-bzr%s' % \
(sorted(b.tags.get_tag_dict().keys())[-1], revno)
finally:
b.unlock()
except:
# Otherwise run the command line bzr client
bzr = Popen((u'bzr', u'tags', u'--sort', u'time'), stdout=PIPE)
output, error = bzr.communicate()
code = bzr.wait()
if code != 0:
raise Exception(u'Error running bzr tags')
lines = output.splitlines()
if len(lines) == 0:
tag = u'0.0.0'
revision = u'0'
else:
tag, revision = lines[-1].split()
bzr = Popen((u'bzr', u'log', u'--line', u'-r', u'-1'),
stdout=PIPE)
output, error = bzr.communicate()
code = bzr.wait()
if code != 0:
raise Exception(u'Error running bzr log')
latest = output.split(u':')[0]
full_version = latest == revision and tag or \
u'%s-bzr%s' % (tag, latest)
else:
# We're not running the development version, let's use the file
filepath = AppLocation.get_directory(AppLocation.VersionDir)
filepath = os.path.join(filepath, u'.version')
fversion = None
try:
fversion = open(filepath, u'r')
full_version = unicode(fversion.read()).rstrip()
except IOError:
log.exception('Error in version file.')
full_version = u'0.0.0-bzr000'
finally:
if fversion:
fversion.close()
bits = full_version.split(u'-')
app_version = {
u'full': full_version,
u'version': bits[0],
u'build': bits[1] if len(bits) > 1 else None
}
if app_version[u'build']:
log.info(
u'Openlp version %s build %s',
app_version[u'version'],
app_version[u'build']
)
else:
log.info(u'Openlp version %s' % app_version[u'version'])
return app_version
def notify(self, obj, evt):
#TODO needed for presentation exceptions
return QtGui.QApplication.notify(self, obj, evt)
@ -79,39 +158,7 @@ class OpenLP(QtGui.QApplication):
"""
Run the OpenLP application.
"""
#Load and store current Application Version
filepath = AppLocation.get_directory(AppLocation.VersionDir)
filepath = os.path.join(filepath, u'.version')
fversion = None
try:
fversion = open(filepath, u'r')
for line in fversion:
full_version = unicode(line).rstrip() #\
#.replace(u'\r', u'').replace(u'\n', u'')
bits = full_version.split(u'-')
app_version = {
u'full': full_version,
u'version': bits[0],
u'build': bits[1] if len(bits) > 1 else None
}
if app_version[u'build']:
log.info(
u'Openlp version %s build %s',
app_version[u'version'],
app_version[u'build']
)
else:
log.info(u'Openlp version %s' % app_version[u'version'])
except IOError:
log.exception('Error in version file.')
app_version = {
u'full': u'1.9.0-bzr000',
u'version': u'1.9.0',
u'build': u'bzr000'
}
finally:
if fversion:
fversion.close()
app_version = self._get_version()
#provide a listener for widgets to reqest a screen update.
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
@ -172,6 +219,9 @@ def main():
parser.add_option('-p', '--portable', dest='portable',
action='store_true', help='Specify if this should be run as a '
'portable app, off a USB flash drive (not implemented).')
parser.add_option('-d', '--dev-version', dest='dev_version',
action='store_true', help='Ignore the version file and pull the '
'version directly from Bazaar')
parser.add_option('-s', '--style', dest='style',
help='Set the Qt4 style (passed directly to Qt4).')
# Set up logging

View File

@ -38,51 +38,51 @@ log = logging.getLogger(__name__)
# TODO make external and configurable in alpha 4 via a settings dialog
html_expands = []
html_expands.append({u'desc':u'Red', u'start tag':u'{r}',
u'start html':u'<span style="-webkit-text-fill-color:red">',
u'end tag':u'{/r}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Black', u'start tag':u'{b}',
u'start html':u'<span style="-webkit-text-fill-color:black">',
u'end tag':u'{/b}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Blue', u'start tag':u'{bl}',
u'start html':u'<span style="-webkit-text-fill-color:blue">',
u'end tag':u'{/bl}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Yellow', u'start tag':u'{y}',
u'start html':u'<span style="-webkit-text-fill-color:yellow">',
u'end tag':u'{/y}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Green', u'start tag':u'{g}',
u'start html':u'<span style="-webkit-text-fill-color:green">',
u'end tag':u'{/g}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Pink', u'start tag':u'{pk}',
u'start html':u'<span style="-webkit-text-fill-color:#CC33CC">',
u'end tag':u'{/pk}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Orange', u'start tag':u'{o}',
u'start html':u'<span style="-webkit-text-fill-color:#CC0033">',
u'end tag':u'{/o}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Purple', u'start tag':u'{pp}',
u'start html':u'<span style="-webkit-text-fill-color:#9900FF">',
u'end tag':u'{/pp}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'White', u'start tag':u'{w}',
u'start html':u'<span style="-webkit-text-fill-color:white">',
u'end tag':u'{/w}', u'end html':u'</span>', u'protected':False})
html_expands.append({u'desc':u'Superscript', u'start tag':u'{su}',
u'start html':u'<sup>', u'end tag':u'{/su}', u'end html':u'</sup>',
u'protected':True})
html_expands.append({u'desc':u'Subscript', u'start tag':u'{sb}',
u'start html':u'<sub>', u'end tag':u'{/sb}', u'end html':u'</sub>',
u'protected':True})
html_expands.append({u'desc':u'Paragraph', u'start tag':u'{p}',
u'start html':u'<p>', u'end tag':u'{/p}', u'end html':u'</p>',
u'protected':True})
html_expands.append({u'desc':u'Bold', u'start tag':u'{st}',
u'start html':u'<strong>', u'end tag':u'{/st}', u'end html':u'</strong>',
u'protected':True})
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'protected':True})
# Image image_cache to stop regualar image resizing
image_cache = {}
html_expands.append({u'desc': u'Red', u'start tag': u'{r}',
u'start html': u'<span style="-webkit-text-fill-color:red">',
u'end tag': u'{/r}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Black', u'start tag': u'{b}',
u'start html': u'<span style="-webkit-text-fill-color:black">',
u'end tag': u'{/b}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Blue', u'start tag': u'{bl}',
u'start html': u'<span style="-webkit-text-fill-color:blue">',
u'end tag': u'{/bl}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Yellow', u'start tag': u'{y}',
u'start html': u'<span style="-webkit-text-fill-color:yellow">',
u'end tag': u'{/y}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Green', u'start tag': u'{g}',
u'start html': u'<span style="-webkit-text-fill-color:green">',
u'end tag': u'{/g}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Pink', u'start tag': u'{pk}',
u'start html': u'<span style="-webkit-text-fill-color:#CC33CC">',
u'end tag': u'{/pk}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Orange', u'start tag': u'{o}',
u'start html': u'<span style="-webkit-text-fill-color:#CC0033">',
u'end tag': u'{/o}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Purple', u'start tag': u'{pp}',
u'start html': u'<span style="-webkit-text-fill-color:#9900FF">',
u'end tag': u'{/pp}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'White', u'start tag': u'{w}',
u'start html': u'<span style="-webkit-text-fill-color:white">',
u'end tag': u'{/w}', u'end html': u'</span>', u'protected': False})
html_expands.append({u'desc': u'Superscript', u'start tag': u'{su}',
u'start html': u'<sup>', u'end tag': u'{/su}', u'end html': u'</sup>',
u'protected': True})
html_expands.append({u'desc': u'Subscript', u'start tag': u'{sb}',
u'start html': u'<sub>', u'end tag': u'{/sb}', u'end html': u'</sub>',
u'protected': True})
html_expands.append({u'desc': u'Paragraph', u'start tag': u'{p}',
u'start html': u'<p>', u'end tag': u'{/p}', u'end html': u'</p>',
u'protected': True})
html_expands.append({u'desc': u'Bold', u'start tag': u'{st}',
u'start html': u'<strong>', u'end tag': u'{/st}', u'end html': u'</strong>',
u'protected': True})
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'protected': True})
html_expands.append({u'desc': u'Underline', u'start tag': u'{u}',
u'start html': u'<span style="text-decoration: underline;">',
u'end tag': u'{/u}', u'end html': u'</span>', u'protected': True})
def translate(context, text, comment=None):
"""
@ -223,16 +223,13 @@ def image_to_byte(image):
``image``
The image to converted.
"""
log.debug(u'image_to_byte')
log.debug(u'image_to_byte - start')
byte_array = QtCore.QByteArray()
# use buffer to store pixmap into byteArray
buffie = QtCore.QBuffer(byte_array)
buffie.open(QtCore.QIODevice.WriteOnly)
if isinstance(image, QtGui.QImage):
pixmap = QtGui.QPixmap.fromImage(image)
else:
pixmap = QtGui.QPixmap(image)
pixmap.save(buffie, "PNG")
image.save(buffie, "PNG")
log.debug(u'image_to_byte - end')
# convert to base64 encoding so does not get missed!
return byte_array.toBase64()
@ -253,26 +250,25 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
The background colour defaults to black.
"""
log.debug(u'resize_image')
preview = QtGui.QImage(image)
log.debug(u'resize_image - start')
if isinstance(image, QtGui.QImage):
preview = image
else:
preview = QtGui.QImage(image)
if not preview.isNull():
# Only resize if different size
if preview.width() == width and preview.height == height:
return preview
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
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()
realh = preview.height()
# and move it to the centre of the preview space
new_image = QtGui.QImage(width, height,
QtGui.QImage.Format_ARGB32_Premultiplied)
new_image.fill(background)
painter = QtGui.QPainter(new_image)
painter.fillRect(new_image.rect(), background)
painter.drawImage((width - realw) / 2, (height - realh) / 2, preview)
image_cache[image_cache_key] = new_image
return new_image
def check_item_selected(list_widget, message):
@ -310,10 +306,13 @@ def expand_tags(text):
text = text.replace(tag[u'end tag'], tag[u'end html'])
return text
from theme import ThemeLevel, ThemeXML, BackgroundGradientType, \
BackgroundType, HorizontalType, VerticalType
from spelltextedit import SpellTextEdit
from eventreceiver import Receiver
from imagemanager import ImageManager
from settingsmanager import SettingsManager
from plugin import PluginStatus, Plugin
from plugin import PluginStatus, StringContent, Plugin
from pluginmanager import PluginManager
from settingstab import SettingsTab
from serviceitem import ServiceItem
@ -323,7 +322,6 @@ from htmlbuilder import build_html, build_lyrics_format_css, \
build_lyrics_outline_css
from toolbar import OpenLPToolbar
from dockwidget import OpenLPDockWidget
from theme import ThemeLevel, ThemeXML
from renderer import Renderer
from rendermanager import RenderManager
from mediamanageritem import MediaManagerItem

View File

@ -117,6 +117,7 @@ class Manager(object):
settings = QtCore.QSettings()
settings.beginGroup(plugin_name)
self.db_url = u''
self.is_dirty = False
db_type = unicode(
settings.value(u'db type', QtCore.QVariant(u'sqlite')).toString())
if db_type == u'sqlite':
@ -150,12 +151,34 @@ class Manager(object):
self.session.add(object_instance)
if commit:
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError:
self.session.rollback()
log.exception(u'Object save failed')
return False
def save_objects(self, object_list, commit=True):
"""
Save a list of objects to the database
``object_list``
The list of objects to save
``commit``
Commit the session with this object
"""
try:
self.session.add_all(object_list)
if commit:
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError:
self.session.rollback()
log.exception(u'Object list save failed')
return False
def get_object(self, object_class, key=None):
"""
Return the details of an object
@ -205,6 +228,22 @@ class Manager(object):
return query.order_by(order_by_ref).all()
return query.all()
def get_object_count(self, object_class, filter_clause=None):
"""
Returns a count of the number of objects in the database.
``object_class``
The type of objects to return.
``filter_clause``
The filter governing selection of objects to return. Defaults to
None.
"""
query = self.session.query(object_class)
if filter_clause is not None:
query = query.filter(filter_clause)
return query.count()
def delete_object(self, object_class, key):
"""
Delete an object from the database
@ -220,6 +259,7 @@ class Manager(object):
try:
self.session.delete(object_instance)
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError:
self.session.rollback()
@ -241,8 +281,18 @@ class Manager(object):
query = query.filter(filter_clause)
query.delete(synchronize_session=False)
self.session.commit()
self.is_dirty = True
return True
except InvalidRequestError:
self.session.rollback()
log.exception(u'Failed to delete %s records', object_class.__name__)
return False
def finalise(self):
"""
VACUUM the database on exit.
"""
if self.is_dirty:
engine = create_engine(self.db_url)
if self.db_url.startswith(u'sqlite'):
engine.execute("vacuum")

View File

@ -75,7 +75,7 @@ class EventReceiver(QtCore.QObject):
Broadcasts that an item has been made live/previewed
``slidecontroller_{live|preview}_change``
Informs the slidecontroller that a slide change has occurred and to
Informs the slidecontroller that a slide change has occurred and to
update itself
``slidecontroller_{live|preview}_changed``
@ -83,7 +83,7 @@ class EventReceiver(QtCore.QObject):
``slidecontroller_{live|preview}_text_request``
Request the text for the current item in the controller
Returns a slidecontroller_{live|preview}_text_response with an
Returns a slidecontroller_{live|preview}_text_response with an
array of dictionaries with the tag and verse text
``slidecontroller_{live|preview}_blank``
@ -106,23 +106,23 @@ class EventReceiver(QtCore.QObject):
``servicemanager_set_item``
Go live on a specific item, by index
``servicemanager_list_request``
Request the service list. Responds with servicemanager_list_response
containing a array of dictionaries
``maindisplay_blank``
Blank the maindisplay window
Blank the maindisplay window
``maindisplay_hide``
Hide the maindisplay window
Hide the maindisplay window
``maindisplay_show``
Return the maindisplay window
Return the maindisplay window
``maindisplay_active``
The maindisplay has been made active
``maindisplay_status_text``
Changes the bottom status bar text on the maindisplay window
@ -193,9 +193,17 @@ class EventReceiver(QtCore.QObject):
``{plugin}_add_service_item``
Ask the plugin to push the selected items to the service item
``{plugin}_service_load``
Ask the plugin to process an individual service item after it has been
loaded
``service_item_update``
Passes back to the service manager the service item after it has been
processed by the plugin
``alerts_text``
Displays an alert message
``bibles_nobook``
Attempt to find book resulted in no match

View File

@ -25,8 +25,11 @@
###############################################################################
import logging
from PyQt4 import QtWebKit
from openlp.core.lib import BackgroundType, BackgroundGradientType
log = logging.getLogger(__name__)
HTMLSRC = u"""
@ -55,14 +58,17 @@ body {
background-color: black;
display: none;
}
#image {
#bgimage {
z-index:1;
}
#video1 {
#image {
z-index:2;
}
#video1 {
z-index:3;
}
#video2 {
z-index:2;
z-index:3;
}
#alert {
position: absolute;
@ -73,7 +79,7 @@ body {
}
#footer {
position: absolute;
z-index:5;
z-index:6;
%s
}
/* lyric css */
@ -87,16 +93,16 @@ body {
var transition = %s;
function show_video(state, path, volume, loop){
// Note, the preferred method for looping would be to use the
// Note, the preferred method for looping would be to use the
// video tag loop attribute.
// But QtWebKit doesn't support this. Neither does it support the
// onended event, hence the setInterval()
// In addition, setting the currentTime attribute to zero to restart
// the video raises an INDEX_SIZE_ERROR: DOM Exception 1
// To complicate it further, sometimes vid.currentTime stops
// To complicate it further, sometimes vid.currentTime stops
// slightly short of vid.duration and vid.ended is intermittent!
//
// Note, currently the background may go black between loops. Not
// Note, currently the background may go black between loops. Not
// desirable. Need to investigate using two <video>'s, and hiding/
// preloading one, and toggle between the two when looping.
@ -112,7 +118,7 @@ body {
vid2.volume = volume;
}
switch(state){
case 'init':
case 'init':
vid.src = path;
vid2.src = path;
if(loop == null) loop = false;
@ -129,8 +135,8 @@ body {
vid.style.visibility = 'visible';
if(vid.looping){
video_timer = setInterval(
function() {
show_video('poll');
function() {
show_video('poll');
}, 200);
}
break;
@ -294,7 +300,8 @@ body {
</script>
</head>
<body>
<img id="image" class="size" %s />
<img id="bgimage" class="size" %s />
<img id="image" class="size" style="display:none" />
<video id="video1" class="size" style="visibility:hidden" autobuffer preload>
</video>
<video id="video2" class="size" style="visibility:hidden" autobuffer preload>
@ -324,6 +331,7 @@ def build_html(item, screen, alert, islive):
height = screen[u'size'].height()
theme = item.themedata
webkitvers = webkit_version()
# Image generated and poked in
if item.bg_image_bytes:
image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes
else:
@ -363,16 +371,36 @@ def build_background_css(item, width, height):
theme = item.themedata
background = u'background-color: black'
if theme:
if theme.background_type == u'solid':
if theme.background_type == \
BackgroundType.to_string(BackgroundType.Solid):
background = u'background-color: %s' % theme.background_color
else:
if theme.background_direction == u'horizontal':
if theme.background_direction == BackgroundGradientType.to_string \
(BackgroundGradientType.Horizontal):
background = \
u'background: ' \
u'-webkit-gradient(linear, left top, left bottom, ' \
'from(%s), to(%s))' % (theme.background_start_color,
theme.background_end_color)
elif theme.background_direction == u'vertical':
elif theme.background_direction == \
BackgroundGradientType.to_string( \
BackgroundGradientType.LeftTop):
background = \
u'background: ' \
u'-webkit-gradient(linear, left top, right bottom, ' \
'from(%s), to(%s))' % (theme.background_start_color,
theme.background_end_color)
elif theme.background_direction == \
BackgroundGradientType.to_string \
(BackgroundGradientType.LeftBottom):
background = \
u'background: ' \
u'-webkit-gradient(linear, left bottom, right top, ' \
'from(%s), to(%s))' % (theme.background_start_color,
theme.background_end_color)
elif theme.background_direction == \
BackgroundGradientType.to_string \
(BackgroundGradientType.Vertical):
background = \
u'background: -webkit-gradient(linear, left top, ' \
u'right top, from(%s), to(%s))' % \
@ -397,7 +425,7 @@ def build_lyrics_css(item, webkitvers):
"""
style = """
.lyricstable {
z-index:4;
z-index:5;
position: absolute;
display: table;
%s
@ -447,17 +475,17 @@ def build_lyrics_css(item, webkitvers):
lyricsmain += build_lyrics_outline_css(theme)
else:
outline = build_lyrics_outline_css(theme)
if theme.display_shadow:
if theme.display_outline and webkitvers < 534.3:
if theme.font_main_shadow:
if theme.font_main_outline and webkitvers < 534.3:
shadow = u'padding-left: %spx; padding-top: %spx;' % \
(int(theme.display_shadow_size) +
(int(theme.display_outline_size) * 2),
theme.display_shadow_size)
(int(theme.font_main_shadow_size) +
(int(theme.font_main_outline_size) * 2),
theme.font_main_shadow_size)
shadow += build_lyrics_outline_css(theme, True)
else:
lyricsmain += u' text-shadow: %s %spx %spx;' % \
(theme.display_shadow_color, theme.display_shadow_size,
theme.display_shadow_size)
(theme.font_main_shadow_color, theme.font_main_shadow_size,
theme.font_main_shadow_size)
lyrics_css = style % (lyricstable, lyrics, lyricsmain, outline, shadow)
return lyrics_css
@ -472,14 +500,14 @@ def build_lyrics_outline_css(theme, is_shadow=False):
`is_shadow`
If true, use the shadow colors instead
"""
if theme.display_outline:
size = float(theme.display_outline_size) / 16
if theme.font_main_outline:
size = float(theme.font_main_outline_size) / 16
if is_shadow:
fill_color = theme.display_shadow_color
outline_color = theme.display_shadow_color
fill_color = theme.font_main_shadow_color
outline_color = theme.font_main_shadow_color
else:
fill_color = theme.font_main_color
outline_color = theme.display_outline_color
outline_color = theme.font_main_outline_color
return u' -webkit-text-stroke: %sem %s; ' \
u'-webkit-text-fill-color: %s; ' % (size, outline_color, fill_color)
else:
@ -512,23 +540,23 @@ def build_lyrics_format_css(theme, width, height):
valign = u'middle'
else:
valign = u'top'
if theme.display_outline:
left_margin = int(theme.display_outline_size) * 2
if theme.font_main_outline:
left_margin = int(theme.font_main_outline_size) * 2
else:
left_margin = 0
lyrics = u'white-space:pre-wrap; word-wrap: break-word; ' \
'text-align: %s; vertical-align: %s; font-family: %s; ' \
'font-size: %spt; color: %s; line-height: %d%%; margin:0;' \
'padding:0; padding-left:%spx; width: %spx; height: %spx; ' % \
(align, valign, theme.font_main_name, theme.font_main_proportion,
(align, valign, theme.font_main_name, theme.font_main_size,
theme.font_main_color, 100 + int(theme.font_main_line_adjustment),
left_margin, width, height)
if theme.display_outline:
if theme.font_main_outline:
if webkit_version() < 534.3:
lyrics += u' letter-spacing: 1px;'
if theme.font_main_italics:
lyrics += u' font-style:italic; '
if theme.font_main_weight == u'Bold':
if theme.font_main_bold:
lyrics += u' font-weight:bold; '
return lyrics
@ -548,7 +576,7 @@ def build_lyrics_html(item, webkitvers):
# display:table/display:table-cell are required for each lyric block.
lyrics = u''
theme = item.themedata
if webkitvers < 534.4 and theme and theme.display_outline:
if webkitvers < 534.4 and theme and theme.font_main_outline:
lyrics += u'<div class="lyricstable">' \
u'<div id="lyricsshadow" style="opacity:1" ' \
u'class="lyricscell lyricsshadow"></div></div>'
@ -584,7 +612,7 @@ def build_footer_css(item, height):
bottom = height - int(item.footer.y()) - int(item.footer.height())
lyrics_html = style % (item.footer.x(), bottom,
item.footer.width(), theme.font_footer_name,
theme.font_footer_proportion, theme.font_footer_color)
theme.font_footer_size, theme.font_footer_color)
return lyrics_html
def build_alert_css(alertTab, width):

View File

@ -0,0 +1,168 @@
# -*- 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.imageManager = manager
def run(self):
"""
Run the thread.
"""
self.imageManager.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 del_image(self, name):
"""
Delete the Image from the Cache
"""
log.debug(u'del_image %s' % name)
if name in self._cache:
del self._cache[name]
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
else:
log.debug(u'Image in cache %s:%s' % (name, path))
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

@ -0,0 +1,38 @@
PSF LICENSE AGREEMENT FOR PYTHON 2.7.1
1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"),
and the Individual or Organization ("Licensee") accessing and otherwise
using Python 2.7.1 software in source or binary form and its associated
documentation.
2. Subject to the terms and conditions of this License Agreement, PSF hereby
grants Licensee a nonexclusive, royalty-free, world-wide license to
reproduce, analyze, test, perform and/or display publicly, prepare
derivative works, distribute, and otherwise use Python 2.7.1 alone or in any
derivative version, provided, however, that PSF's License Agreement and
PSF's notice of copyright, i.e., "Copyright (c) 2001-2010 Python Software
Foundation; All Rights Reserved" are retained in Python 2.7.1 alone or in
any derivative version prepared by Licensee.
3. In the event Licensee prepares a derivative work that is based on or
incorporates Python 2.7.1 or any part thereof, and wants to make the
derivative work available to others as provided herein, then Licensee hereby
agrees to include in any such work a brief summary of the changes made to
Python 2.7.1.
4. PSF is making Python 2.7.1 available to Licensee on an "AS IS" basis. PSF
MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION
OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
THE USE OF PYTHON 2.7.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.1 FOR
ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.1, OR ANY DERIVATIVE
THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
6. This License Agreement will automatically terminate upon a material breach
of its terms and conditions.
7. Nothing in this License Agreement shall be deemed to create any relationship
of agency, partnership, or joint venture between PSF and Licensee. This
License Agreement does not grant permission to use PSF trademarks or trade
name in a trademark sense to endorse or promote products or services of
Licensee, or any third party.
8. By copying, installing or otherwise using Python 2.7.1, Licensee agrees to
be bound by the terms and conditions of this License Agreement.

View File

@ -0,0 +1,321 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# Utilities for opening files or URLs in the registered default application #
# and for sending e-mail using the user's preferred composer. #
# --------------------------------------------------------------------------- #
# Copyright (c) 2007 Antonio Valentino #
# All rights reserved. #
# --------------------------------------------------------------------------- #
# This program offered under the PSF License as published by the Python #
# Software Foundation. #
# #
# The license text can be found at http://docs.python.org/license.html #
# #
# This code is taken from: http://code.activestate.com/recipes/511443 #
# Modified for use in OpenLP #
###############################################################################
__version__ = u'1.1'
__all__ = [u'open', u'mailto']
import os
import sys
import webbrowser
import subprocess
from email.Utils import encode_rfc2231
_controllers = {}
_open = None
class BaseController(object):
"""
Base class for open program controllers.
"""
def __init__(self, name):
self.name = name
def open(self, filename):
raise NotImplementedError
class Controller(BaseController):
"""
Controller for a generic open program.
"""
def __init__(self, *args):
super(Controller, self).__init__(os.path.basename(args[0]))
self.args = list(args)
def _invoke(self, cmdline):
if sys.platform[:3] == u'win':
closefds = False
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
closefds = True
startupinfo = None
if (os.environ.get(u'DISPLAY') or sys.platform[:3] == u'win' or \
sys.platform == u'darwin'):
inout = file(os.devnull, u'r+')
else:
# for TTY programs, we need stdin/out
inout = None
# if possible, put the child precess in separate process group,
# so keyboard interrupts don't affect child precess as well as
# Python
setsid = getattr(os, u'setsid', None)
if not setsid:
setsid = getattr(os, u'setpgrp', None)
pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout,
stderr=inout, close_fds=closefds, preexec_fn=setsid,
startupinfo=startupinfo)
# It is assumed that this kind of tools (gnome-open, kfmclient,
# exo-open, xdg-open and open for OSX) immediately exit after lauching
# the specific application
returncode = pipe.wait()
if hasattr(self, u'fixreturncode'):
returncode = self.fixreturncode(returncode)
return not returncode
def open(self, filename):
if isinstance(filename, basestring):
cmdline = self.args + [filename]
else:
# assume it is a sequence
cmdline = self.args + filename
try:
return self._invoke(cmdline)
except OSError:
return False
# Platform support for Windows
if sys.platform[:3] == u'win':
class Start(BaseController):
"""
Controller for the win32 start progam through os.startfile.
"""
def open(self, filename):
try:
os.startfile(filename)
except WindowsError:
# [Error 22] No application is associated with the specified
# file for this operation: '<URL>'
return False
else:
return True
_controllers[u'windows-default'] = Start(u'start')
_open = _controllers[u'windows-default'].open
# Platform support for MacOS
elif sys.platform == u'darwin':
_controllers[u'open'] = Controller(u'open')
_open = _controllers[u'open'].open
# Platform support for Unix
else:
import commands
# @WARNING: use the private API of the webbrowser module
from webbrowser import _iscommand
class KfmClient(Controller):
"""
Controller for the KDE kfmclient program.
"""
def __init__(self, kfmclient=u'kfmclient'):
super(KfmClient, self).__init__(kfmclient, u'exec')
self.kde_version = self.detect_kde_version()
def detect_kde_version(self):
kde_version = None
try:
info = commands.getoutput(u'kfmclient --version')
for line in info.splitlines():
if line.startswith(u'KDE'):
kde_version = line.split(u':')[-1].strip()
break
except (OSError, RuntimeError):
pass
return kde_version
def fixreturncode(self, returncode):
if returncode is not None and self.kde_version > u'3.5.4':
return returncode
else:
return os.EX_OK
def detect_desktop_environment():
"""
Checks for known desktop environments
Return the desktop environments name, lowercase (kde, gnome, xfce)
or "generic"
"""
desktop_environment = u'generic'
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
desktop_environment = u'kde'
elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'):
desktop_environment = u'gnome'
else:
try:
info = commands.getoutput(u'xprop -root _DT_SAVE_MODE')
if u' = "xfce4"' in info:
desktop_environment = u'xfce'
except (OSError, RuntimeError):
pass
return desktop_environment
def register_X_controllers():
if _iscommand(u'kfmclient'):
_controllers[u'kde-open'] = KfmClient()
for command in (u'gnome-open', u'exo-open', u'xdg-open'):
if _iscommand(command):
_controllers[command] = Controller(command)
def get():
controllers_map = {
u'gnome': u'gnome-open',
u'kde': u'kde-open',
u'xfce': u'exo-open',
}
desktop_environment = detect_desktop_environment()
try:
controller_name = controllers_map[desktop_environment]
return _controllers[controller_name].open
except KeyError:
if _controllers.has_key(u'xdg-open'):
return _controllers[u'xdg-open'].open
else:
return webbrowser.open
if os.environ.get(u'DISPLAY'):
register_X_controllers()
_open = get()
def open(filename):
"""
Open a file or an URL in the registered default application.
"""
return _open(filename)
def _fix_addersses(**kwargs):
for headername in (u'address', u'to', u'cc', u'bcc'):
try:
headervalue = kwargs[headername]
if not headervalue:
del kwargs[headername]
continue
elif not isinstance(headervalue, basestring):
# assume it is a sequence
headervalue = u','.join(headervalue)
except KeyError:
pass
except TypeError:
raise TypeError(u'string or sequence expected for "%s", %s '
u'found' % (headername, type(headervalue).__name__))
else:
translation_map = {u'%': u'%25', u'&': u'%26', u'?': u'%3F'}
for char, replacement in translation_map.items():
headervalue = headervalue.replace(char, replacement)
kwargs[headername] = headervalue
return kwargs
def mailto_format(**kwargs):
"""
Compile mailto string from call parameters
"""
# @TODO: implement utf8 option
kwargs = _fix_addersses(**kwargs)
parts = []
for headername in (u'to', u'cc', u'bcc', u'subject', u'body', u'attach'):
if kwargs.has_key(headername):
headervalue = kwargs[headername]
if not headervalue:
continue
if headername in (u'address', u'to', u'cc', u'bcc'):
parts.append(u'%s=%s' % (headername, headervalue))
else:
headervalue = encode_rfc2231(headervalue) # @TODO: check
parts.append(u'%s=%s' % (headername, headervalue))
mailto_string = u'mailto:%s' % kwargs.get(u'address', '')
if parts:
mailto_string = u'%s?%s' % (mailto_string, u'&'.join(parts))
return mailto_string
def mailto(address, to=None, cc=None, bcc=None, subject=None, body=None,
attach=None):
"""
Send an e-mail using the user's preferred composer.
Open the user's preferred e-mail composer in order to send a mail to
address(es) that must follow the syntax of RFC822. Multiple addresses
may be provided (for address, cc and bcc parameters) as separate
arguments.
All parameters provided are used to prefill corresponding fields in
the user's e-mail composer. The user will have the opportunity to
change any of this information before actually sending the e-mail.
``address``
specify the destination recipient
``cc``
specify a recipient to be copied on the e-mail
``bcc``
specify a recipient to be blindly copied on the e-mail
``subject``
specify a subject for the e-mail
``body``
specify a body for the e-mail. Since the user will be able to make
changes before actually sending the e-mail, this can be used to provide
the user with a template for the e-mail text may contain linebreaks
``attach``
specify an attachment for the e-mail. file must point to an existing
file
"""
mailto_string = mailto_format(**locals())
return open(mailto_string)

View File

@ -32,7 +32,8 @@ import os
from PyQt4 import QtCore, QtGui
from openlp.core.lib import context_menu_action, context_menu_separator, \
SettingsManager, OpenLPToolbar, ServiceItem, build_icon, translate
SettingsManager, OpenLPToolbar, ServiceItem, StringContent, build_icon, \
translate, Receiver
log = logging.getLogger(__name__)
@ -51,26 +52,19 @@ class MediaManagerItem(QtGui.QWidget):
The parent widget. Usually this will be the *Media Manager*
itself. This needs to be a class descended from ``QWidget``.
``plugin``
The plugin widget. Usually this will be the *Plugin*
itself. This needs to be a class descended from ``Plugin``.
``icon``
Either a ``QIcon``, a resource path, or a file name. This is
the icon which is displayed in the *Media Manager*.
``title``
The title visible on the item in the *Media Manager*.
**Member Variables**
When creating a descendant class from this class for your plugin,
the following member variables should be set.
``self.PluginNameShort``
The shortened (usually singular) name for the plugin e.g. *'Song'*
for the Songs plugin.
``self.pluginNameVisible``
The user visible name for a plugin which should use a suitable
translation function.
``self.OnNewPrompt``
Defaults to *'Select Image(s)'*.
@ -93,13 +87,17 @@ class MediaManagerItem(QtGui.QWidget):
"""
log.info(u'Media Item loaded')
def __init__(self, parent=None, icon=None, title=None):
def __init__(self, parent=None, plugin=None, icon=None):
"""
Constructor to create the media manager item.
"""
QtGui.QWidget.__init__(self)
self.parent = parent
self.settingsSection = title.lower()
#TODO: plugin should not be the parent in future
self.plugin = parent # plugin
visible_title = self.plugin.getString(StringContent.VisibleName)
self.title = unicode(visible_title[u'title'])
self.settingsSection = self.plugin.name.lower()
if isinstance(icon, QtGui.QIcon):
self.icon = icon
elif isinstance(icon, basestring):
@ -107,8 +105,6 @@ class MediaManagerItem(QtGui.QWidget):
QtGui.QIcon.Normal, QtGui.QIcon.Off)
else:
self.icon = None
if title:
self.title = title
self.toolbar = None
self.remoteTriggered = None
self.serviceItemIconName = None
@ -119,6 +115,9 @@ class MediaManagerItem(QtGui.QWidget):
self.requiredIcons()
self.setupUi()
self.retranslateUi()
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
self.serviceLoad)
def requiredIcons(self):
"""
@ -208,64 +207,58 @@ class MediaManagerItem(QtGui.QWidget):
"""
## Import Button ##
if self.hasImportIcon:
import_string = self.plugin.getString(StringContent.Import)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'Import %s')) %
self.PluginNameShort,
unicode(translate('OpenLP.MediaManagerItem', 'Import a %s')) %
self.pluginNameVisible,
import_string[u'title'],
import_string[u'tooltip'],
u':/general/general_import.png', self.onImportClick)
## File Button ##
## Load Button ##
if self.hasFileIcon:
load_string = self.plugin.getString(StringContent.Load)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'Load %s')) %
self.PluginNameShort,
unicode(translate('OpenLP.MediaManagerItem', 'Load a new %s')) %
self.pluginNameVisible,
load_string[u'title'],
load_string[u'tooltip'],
u':/general/general_open.png', self.onFileClick)
## New Button ##
if self.hasNewIcon:
new_string = self.plugin.getString(StringContent.New)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'New %s')) %
self.PluginNameShort,
unicode(translate('OpenLP.MediaManagerItem', 'Add a new %s')) %
self.pluginNameVisible,
new_string[u'title'],
new_string[u'tooltip'],
u':/general/general_new.png', self.onNewClick)
## Edit Button ##
if self.hasEditIcon:
edit_string = self.plugin.getString(StringContent.Edit)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'Edit %s')) %
self.PluginNameShort,
unicode(translate(
'OpenLP.MediaManagerItem', 'Edit the selected %s')) %
self.pluginNameVisible,
edit_string[u'title'],
edit_string[u'tooltip'],
u':/general/general_edit.png', self.onEditClick)
## Delete Button ##
if self.hasDeleteIcon:
delete_string = self.plugin.getString(StringContent.Delete)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'Delete %s')) %
self.PluginNameShort,
translate('OpenLP.MediaManagerItem',
'Delete the selected item'),
delete_string[u'title'],
delete_string[u'tooltip'],
u':/general/general_delete.png', self.onDeleteClick)
## Separator Line ##
self.addToolbarSeparator()
## Preview ##
preview_string = self.plugin.getString(StringContent.Preview)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'Preview %s')) %
self.PluginNameShort,
translate('OpenLP.MediaManagerItem', 'Preview the selected item'),
preview_string[u'title'],
preview_string[u'tooltip'],
u':/general/general_preview.png', self.onPreviewClick)
## Live Button ##
live_string = self.plugin.getString(StringContent.Live)
self.addToolbarButton(
u'Go Live',
translate('OpenLP.MediaManagerItem', 'Send the selected item live'),
live_string[u'title'],
live_string[u'tooltip'],
u':/general/general_live.png', self.onLiveClick)
## Add to service Button ##
service_string = self.plugin.getString(StringContent.Service)
self.addToolbarButton(
unicode(translate('OpenLP.MediaManagerItem', 'Add %s to Service')) %
self.PluginNameShort,
translate('OpenLP.MediaManagerItem',
'Add the selected item(s) to the service'),
service_string[u'title'],
service_string[u'tooltip'],
u':/general/general_add.png', self.onAddClick)
def addListViewToToolBar(self):
@ -281,17 +274,18 @@ class MediaManagerItem(QtGui.QWidget):
QtGui.QAbstractItemView.ExtendedSelection)
self.listView.setAlternatingRowColors(True)
self.listView.setDragEnabled(True)
self.listView.setObjectName(u'%sListView' % self.PluginNameShort)
self.listView.setObjectName(u'%sListView' % self.plugin.name)
#Add to pageLayout
self.pageLayout.addWidget(self.listView)
#define and add the context menu
self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
name_string = self.plugin.getString(StringContent.Name)
if self.hasEditIcon:
self.listView.addAction(
context_menu_action(
self.listView, u':/general/general_edit.png',
unicode(translate('OpenLP.MediaManagerItem', '&Edit %s')) %
self.pluginNameVisible,
name_string[u'singular'],
self.onEditClick))
self.listView.addAction(context_menu_separator(self.listView))
if self.hasDeleteIcon:
@ -300,14 +294,14 @@ class MediaManagerItem(QtGui.QWidget):
self.listView, u':/general/general_delete.png',
unicode(translate('OpenLP.MediaManagerItem',
'&Delete %s')) %
self.pluginNameVisible,
name_string[u'singular'],
self.onDeleteClick))
self.listView.addAction(context_menu_separator(self.listView))
self.listView.addAction(
context_menu_action(
self.listView, u':/general/general_preview.png',
unicode(translate('OpenLP.MediaManagerItem', '&Preview %s')) %
self.pluginNameVisible,
name_string[u'singular'],
self.onPreviewClick))
self.listView.addAction(
context_menu_action(
@ -326,15 +320,9 @@ class MediaManagerItem(QtGui.QWidget):
translate('OpenLP.MediaManagerItem',
'&Add to selected Service Item'),
self.onAddEditClick))
if QtCore.QSettings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool():
QtCore.QObject.connect(self.listView,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onLiveClick)
else:
QtCore.QObject.connect(self.listView,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onPreviewClick)
QtCore.QObject.connect(self.listView,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onClickPressed)
def initialise(self):
"""
@ -432,10 +420,20 @@ class MediaManagerItem(QtGui.QWidget):
raise NotImplementedError(u'MediaManagerItem.onDeleteClick needs to '
u'be defined by the plugin')
def generateSlideData(self, service_item, item=None):
def generateSlideData(self, serviceItem, item=None, xmlVersion=False):
raise NotImplementedError(u'MediaManagerItem.generateSlideData needs '
u'to be defined by the plugin')
def onClickPressed(self):
"""
Allows the list click action to be determined dynamically
"""
if QtCore.QSettings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool():
self.onLiveClick()
else:
self.onPreviewClick()
def onPreviewClick(self):
"""
Preview an item by building a service item then adding that service
@ -447,11 +445,11 @@ class MediaManagerItem(QtGui.QWidget):
translate('OpenLP.MediaManagerItem',
'You must select one or more items to preview.'))
else:
log.debug(self.PluginNameShort + u' Preview requested')
service_item = self.buildServiceItem()
if service_item:
service_item.from_plugin = True
self.parent.previewController.addServiceItem(service_item)
log.debug(self.plugin.name + u' Preview requested')
serviceItem = self.buildServiceItem()
if serviceItem:
serviceItem.from_plugin = True
self.parent.previewController.addServiceItem(serviceItem)
def onLiveClick(self):
"""
@ -464,11 +462,11 @@ class MediaManagerItem(QtGui.QWidget):
translate('OpenLP.MediaManagerItem',
'You must select one or more items to send live.'))
else:
log.debug(self.PluginNameShort + u' Live requested')
service_item = self.buildServiceItem()
if service_item:
service_item.from_plugin = True
self.parent.liveController.addServiceItem(service_item)
log.debug(self.plugin.name + u' Live requested')
serviceItem = self.buildServiceItem()
if serviceItem:
serviceItem.from_plugin = True
self.parent.liveController.addServiceItem(serviceItem)
def onAddClick(self):
"""
@ -480,22 +478,22 @@ class MediaManagerItem(QtGui.QWidget):
translate('OpenLP.MediaManagerItem',
'You must select one or more items.'))
else:
#Is it posssible to process multiple list items to generate multiple
#service items?
# Is it posssible to process multiple list items to generate
# multiple service items?
if self.singleServiceItem or self.remoteTriggered:
log.debug(self.PluginNameShort + u' Add requested')
service_item = self.buildServiceItem()
if service_item:
service_item.from_plugin = False
self.parent.serviceManager.addServiceItem(service_item,
log.debug(self.plugin.name + u' Add requested')
serviceItem = self.buildServiceItem(None, True)
if serviceItem:
serviceItem.from_plugin = False
self.parent.serviceManager.addServiceItem(serviceItem,
replace=self.remoteTriggered)
else:
items = self.listView.selectedIndexes()
for item in items:
service_item = self.buildServiceItem(item)
if service_item:
service_item.from_plugin = False
self.parent.serviceManager.addServiceItem(service_item)
serviceItem = self.buildServiceItem(item, True)
if serviceItem:
serviceItem.from_plugin = False
self.parent.serviceManager.addServiceItem(serviceItem)
def onAddEditClick(self):
"""
@ -507,36 +505,43 @@ class MediaManagerItem(QtGui.QWidget):
translate('OpenLP.MediaManagerItem',
'You must select one or more items'))
else:
log.debug(self.PluginNameShort + u' Add requested')
service_item = self.parent.serviceManager.getServiceItem()
if not service_item:
log.debug(self.plugin.name + u' Add requested')
serviceItem = self.parent.serviceManager.getServiceItem()
if not serviceItem:
QtGui.QMessageBox.information(self,
translate('OpenLP.MediaManagerItem',
'No Service Item Selected'),
translate('OpenLP.MediaManagerItem',
'You must select an existing service item to add to.'))
elif self.title.lower() == service_item.name.lower():
self.generateSlideData(service_item)
self.parent.serviceManager.addServiceItem(service_item,
elif self.title.lower() == serviceItem.name.lower():
self.generateSlideData(serviceItem)
self.parent.serviceManager.addServiceItem(serviceItem,
replace=True)
else:
#Turn off the remote edit update message indicator
# Turn off the remote edit update message indicator
QtGui.QMessageBox.information(self,
translate('OpenLP.MediaManagerItem',
'Invalid Service Item'),
unicode(translate('OpenLP.MediaManagerItem',
'You must select a %s service item.')) % self.title)
def buildServiceItem(self, item=None):
def buildServiceItem(self, item=None, xmlVersion=False):
"""
Common method for generating a service item
"""
service_item = ServiceItem(self.parent)
serviceItem = ServiceItem(self.parent)
if self.serviceItemIconName:
service_item.add_icon(self.serviceItemIconName)
serviceItem.add_icon(self.serviceItemIconName)
else:
service_item.add_icon(self.parent.icon_path)
if self.generateSlideData(service_item, item):
return service_item
serviceItem.add_icon(self.parent.icon_path)
if self.generateSlideData(serviceItem, item, xmlVersion):
return serviceItem
else:
return None
def serviceLoad(self, message):
"""
Method to add processing when a service has been loaded and
individual service items need to be processed by the plugins
"""
pass

View File

@ -42,6 +42,18 @@ class PluginStatus(object):
Inactive = 0
Disabled = -1
class StringContent(object):
Name = u'name'
Import = u'import'
Load = u'load'
New = u'new'
Edit = u'edit'
Delete = u'delete'
Preview = u'preview'
Live = u'live'
Service = u'service'
VisibleName = u'visible_name'
class Plugin(QtCore.QObject):
"""
Base class for openlp plugins to inherit from.
@ -96,7 +108,7 @@ class Plugin(QtCore.QObject):
"""
log.info(u'loaded')
def __init__(self, name, version=None, plugin_helpers=None):
def __init__(self, name, version=None, pluginHelpers=None):
"""
This is the constructor for the plugin object. This provides an easy
way for descendent plugins to populate common data. This method *must*
@ -112,11 +124,13 @@ class Plugin(QtCore.QObject):
``version``
Defaults to *None*. The version of the plugin.
``plugin_helpers``
``pluginHelpers``
Defaults to *None*. A list of helper objects.
"""
QtCore.QObject.__init__(self)
self.name = name
self.textStrings = {}
self.setPluginTextStrings()
if version:
self.version = version
self.settingsSection = self.name.lower()
@ -125,14 +139,14 @@ class Plugin(QtCore.QObject):
self.status = PluginStatus.Inactive
# Set up logging
self.log = logging.getLogger(self.name)
self.previewController = plugin_helpers[u'preview']
self.liveController = plugin_helpers[u'live']
self.renderManager = plugin_helpers[u'render']
self.serviceManager = plugin_helpers[u'service']
self.settingsForm = plugin_helpers[u'settings form']
self.mediadock = plugin_helpers[u'toolbox']
self.pluginManager = plugin_helpers[u'pluginmanager']
self.formparent = plugin_helpers[u'formparent']
self.previewController = pluginHelpers[u'preview']
self.liveController = pluginHelpers[u'live']
self.renderManager = pluginHelpers[u'render']
self.serviceManager = pluginHelpers[u'service']
self.settingsForm = pluginHelpers[u'settings form']
self.mediadock = pluginHelpers[u'toolbox']
self.pluginManager = pluginHelpers[u'pluginmanager']
self.formparent = pluginHelpers[u'formparent']
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_add_service_item' % self.name),
self.processAddServiceEvent)
@ -257,9 +271,9 @@ class Plugin(QtCore.QObject):
Called by the plugin to remove toolbar
"""
if self.mediaItem:
self.mediadock.remove_dock(self.name)
self.mediadock.remove_dock(self.mediaItem)
if self.settings_tab:
self.settingsForm.removeTab(self.name)
self.settingsForm.removeTab(self.settings_tab)
def insertToolboxItem(self):
"""
@ -289,3 +303,15 @@ class Plugin(QtCore.QObject):
The new name the plugin should now use.
"""
pass
def getString(self, name):
"""
encapsulate access of plugins translated text strings
"""
return self.textStrings[name]
def setPluginTextStrings(self):
"""
Called to define all translatable texts of the plugin
"""
pass

View File

@ -30,7 +30,7 @@ import os
import sys
import logging
from openlp.core.lib import Plugin, PluginStatus
from openlp.core.lib import Plugin, StringContent, PluginStatus
log = logging.getLogger(__name__)
@ -152,12 +152,15 @@ class PluginManager(object):
for plugin in self.plugins:
if plugin.status is not PluginStatus.Disabled:
plugin.settings_tab = plugin.getSettingsTab()
visible_title = plugin.getString(StringContent.VisibleName)
if plugin.settings_tab:
log.debug(u'Inserting settings tab item from %s' %
plugin.name)
settingsform.addTab(plugin.name, plugin.settings_tab)
visible_title[u'title'])
settingsform.addTab(visible_title[u'title'],
plugin.settings_tab)
else:
log.debug(u'No tab settings in %s' % plugin.name)
log.debug(
u'No tab settings in %s' % visible_title[u'title'])
def hook_import_menu(self, import_menu):
"""

View File

@ -29,11 +29,10 @@ format it for the output display.
"""
import logging
from PyQt4 import QtGui, QtCore, QtWebKit
from openlp.core.lib import resize_image, expand_tags, \
build_lyrics_format_css, build_lyrics_outline_css, image_to_byte
from PyQt4 import QtWebKit
from openlp.core.lib import expand_tags, build_lyrics_format_css, \
build_lyrics_outline_css, Receiver
log = logging.getLogger(__name__)
@ -51,11 +50,6 @@ class Renderer(object):
self._rect = None
self.theme_name = 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):
"""
@ -66,14 +60,7 @@ class Renderer(object):
"""
log.debug(u'set 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
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):
"""
@ -90,9 +77,9 @@ class Renderer(object):
self._rect_footer = rect_footer
self.page_width = self._rect.width()
self.page_height = self._rect.height()
if self._theme.display_shadow:
self.page_width -= int(self._theme.display_shadow_size)
self.page_height -= int(self._theme.display_shadow_size)
if self._theme.font_main_shadow:
self.page_width -= int(self._theme.font_main_shadow_size)
self.page_height -= int(self._theme.font_main_shadow_size)
self.web = QtWebKit.QWebView()
self.web.setVisible(False)
self.web.resize(self.page_width, self.page_height)
@ -105,46 +92,20 @@ class Renderer(object):
(build_lyrics_format_css(self._theme, self.page_width,
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, force_page=False):
"""
Figure out how much text can appear on a slide, using the current
theme settings.
``words``
The words to be fitted on the slide.
``line_break``
Add line endings after each line of text used for bibles.
``force_page``
Flag to tell message lines in page.
"""
log.debug(u'format_slide - Start')
line_end = u''
@ -160,17 +121,27 @@ class Renderer(object):
formatted = []
html_text = u''
styled_text = u''
line_count = 0
for line in text:
if line_count != -1:
line_count += 1
styled_line = expand_tags(line) + line_end
styled_text += styled_line
html = self.page_shell + styled_text + u'</div></body></html>'
self.web.setHtml(html)
# Text too long so go to next page
if self.web_frame.contentsSize().height() > self.page_height:
if force_page and line_count > 0:
Receiver.send_message(u'theme_line_count', line_count)
line_count = -1
if html_text.endswith(u'<br>'):
html_text = html_text[:len(html_text)-4]
formatted.append(html_text)
html_text = u''
styled_text = styled_line
html_text += line + line_end
if html_text.endswith(u'<br>'):
html_text = html_text[:len(html_text)-4]
formatted.append(html_text)
log.debug(u'format_slide - End')
return formatted

View File

@ -28,7 +28,7 @@ import logging
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
log = logging.getLogger(__name__)
@ -56,7 +56,9 @@ class RenderManager(object):
"""
log.debug(u'Initilisation started')
self.screens = screens
self.image_manager = ImageManager()
self.display = MainDisplay(self, screens, False)
self.display.imageManager = self.image_manager
self.display.setup()
self.theme_manager = theme_manager
self.renderer = Renderer()
@ -65,8 +67,9 @@ class RenderManager(object):
self.service_theme = u''
self.theme_level = u''
self.override_background = None
self.themedata = None
self.theme_data = None
self.alertTab = None
self.force_page = False
def update_display(self):
"""
@ -75,9 +78,11 @@ class RenderManager(object):
log.debug(u'Update Display')
self.calculate_default(self.screens.current[u'size'])
self.display = MainDisplay(self, self.screens, False)
self.display.imageManager = self.image_manager
self.display.setup()
self.renderer.bg_frame = None
self.themedata = None
self.theme_data = None
self.image_manager.update_display(self.width, self.height)
def set_global_theme(self, global_theme, theme_level=ThemeLevel.Global):
"""
@ -95,7 +100,7 @@ class RenderManager(object):
self.theme_level = theme_level
self.global_theme_data = \
self.theme_manager.getThemeData(self.global_theme)
self.themedata = None
self.theme_data = None
def set_service_theme(self, service_theme):
"""
@ -105,7 +110,7 @@ class RenderManager(object):
The service-level theme to be set.
"""
self.service_theme = service_theme
self.themedata = None
self.theme_data = None
def set_override_theme(self, theme, overrideLevels=False):
"""
@ -142,18 +147,19 @@ class RenderManager(object):
self.theme = self.service_theme
else:
self.theme = self.global_theme
if self.theme != self.renderer.theme_name or self.themedata is None \
if self.theme != self.renderer.theme_name or self.theme_data is None \
or overrideLevels:
log.debug(u'theme is now %s', self.theme)
# Force the theme to be the one passed in.
if overrideLevels:
self.themedata = theme
self.theme_data = theme
else:
self.themedata = self.theme_manager.getThemeData(self.theme)
self.theme_data = self.theme_manager.getThemeData(self.theme)
self.calculate_default(self.screens.current[u'size'])
self.renderer.set_theme(self.themedata)
self.build_text_rectangle(self.themedata)
self.renderer.set_frame_dest(self.width, self.height)
self.renderer.set_theme(self.theme_data)
self.build_text_rectangle(self.theme_data)
self.image_manager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename)
return self.renderer._rect, self.renderer._rect_footer
def build_text_rectangle(self, theme):
@ -182,14 +188,19 @@ class RenderManager(object):
theme.font_footer_height - 1)
self.renderer.set_text_rectangle(main_rect, footer_rect)
def generate_preview(self, themedata):
def generate_preview(self, theme_data, force_page=False):
"""
Generate a preview of a theme.
``themedata``
``theme_data``
The theme to generated a preview for.
``force_page``
Flag to tell message lines per page need to be generated.
"""
log.debug(u'generate preview')
# save value for use in format_slide
self.force_page = force_page
# set the default image size for previews
self.calculate_default(self.screens.preview[u'size'])
verse = u'The Lord said to {r}Noah{/r}: \n' \
@ -199,23 +210,29 @@ class RenderManager(object):
'Get those children out of the muddy, muddy \n' \
'{r}C{/r}{b}h{/b}{bl}i{/bl}{y}l{/y}{g}d{/g}{pk}' \
'r{/pk}{o}e{/o}{pp}n{/pp} of the Lord\n'
# make big page for theme edit dialog to get line count
if self.force_page:
verse = verse + verse + verse
else:
self.image_manager.del_image(self.theme_data.theme_name)
footer = []
footer.append(u'Arky Arky (Unknown)' )
footer.append(u'Public Domain')
footer.append(u'CCLI 123456')
# build a service item to generate preview
serviceItem = ServiceItem()
serviceItem.theme = themedata
serviceItem.theme = theme_data
serviceItem.add_from_text(u'', verse, footer)
serviceItem.render_manager = self
serviceItem.raw_footer = footer
serviceItem.render(True)
self.display.buildHtml(serviceItem)
raw_html = serviceItem.get_rendered_frame(0)[1]
preview = self.display.text(raw_html)
# Reset the real screen size for subsequent render requests
self.calculate_default(self.screens.current[u'size'])
return preview
if not self.force_page:
self.display.buildHtml(serviceItem)
raw_html = serviceItem.get_rendered_frame(0)
preview = self.display.text(raw_html)
# Reset the real screen size for subsequent render requests
self.calculate_default(self.screens.current[u'size'])
return preview
def format_slide(self, words, line_break):
"""
@ -223,9 +240,12 @@ class RenderManager(object):
``words``
The words to go on the slides.
``line_break``
Add line endings after each line of text used for bibles.
"""
log.debug(u'format slide')
return self.renderer.format_slide(words, line_break)
return self.renderer.format_slide(words, line_break, self.force_page)
def calculate_default(self, screen):
"""

View File

@ -30,12 +30,9 @@ type and capability of an item.
import logging
import os
import time
import uuid
from PyQt4 import QtGui
from openlp.core.lib import build_icon, resize_image, clean_tags, expand_tags
from openlp.core.lib import build_icon, clean_tags, expand_tags
log = logging.getLogger(__name__)
@ -47,6 +44,7 @@ class ServiceItemType(object):
Image = 2
Command = 3
class ItemCapabilities(object):
"""
Provides an enumeration of a serviceitem's capabilities
@ -58,6 +56,9 @@ class ItemCapabilities(object):
AllowsLoop = 5
AllowsAdditions = 6
NoLineBreaks = 7
OnLoadUpdate = 8
AddIfNewItem = 9
class ServiceItem(object):
"""
@ -98,6 +99,11 @@ class ServiceItem(object):
self.main = None
self.footer = None
self.bg_image_bytes = None
self.search_string = u''
self.data_string = u''
self.edit_id = None
self.xml_version = None
self._new_item()
def _new_item(self):
"""
@ -149,17 +155,15 @@ class ServiceItem(object):
line_break = True
if self.is_capable(ItemCapabilities.NoLineBreaks):
line_break = False
theme = None
if self.theme:
theme = self.theme
self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride)
self.themedata = self.render_manager.renderer._theme
if self.service_item_type == ServiceItemType.Text:
log.debug(u'Formatting slides')
theme = None
if self.theme:
theme = self.theme
self.main, self.footer = \
self.render_manager.set_override_theme(theme, useOverride)
self.bg_image_bytes = self.render_manager.renderer.bg_image_bytes
self.themedata = self.render_manager.renderer._theme
for slide in self._raw_frames:
before = time.time()
formatted = self.render_manager \
.format_slide(slide[u'raw_slide'], line_break)
for page in formatted:
@ -168,13 +172,8 @@ class ServiceItem(object):
u'text': clean_tags(page.rstrip()),
u'html': expand_tags(page.rstrip()),
u'verseTag': slide[u'verseTag'] })
log.log(15, u'Formatting took %4s' % (time.time() - before))
elif self.service_item_type == ServiceItemType.Image:
self.themedata = self.render_manager.global_theme_data
for slide in self._raw_frames:
slide[u'image'] = resize_image(slide[u'image'],
self.render_manager.width, self.render_manager.height)
elif self.service_item_type == ServiceItemType.Command:
elif self.service_item_type == ServiceItemType.Image or \
self.service_item_type == ServiceItemType.Command:
pass
else:
log.error(u'Invalid value renderer :%s' % self.service_item_type)
@ -187,7 +186,7 @@ class ServiceItem(object):
else:
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.
@ -196,13 +195,11 @@ class ServiceItem(object):
``title``
A title for the slide in the service item.
``image``
The actual image file name.
"""
self.service_item_type = ServiceItemType.Image
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()
def add_from_text(self, title, raw_slide, verse_tag=None):
@ -218,7 +215,7 @@ class ServiceItem(object):
self.service_item_type = ServiceItemType.Text
title = title.split(u'\n')[0]
self._raw_frames.append(
{u'title': title, u'raw_slide': raw_slide, u'verseTag':verse_tag})
{u'title': title, u'raw_slide': raw_slide, u'verseTag': verse_tag})
self._new_item()
def add_from_command(self, path, file_name, image):
@ -247,15 +244,18 @@ class ServiceItem(object):
service_header = {
u'name': self.name.lower(),
u'plugin': self.name,
u'theme':self.theme,
u'title':self.title,
u'icon':self.icon,
u'footer':self.raw_footer,
u'type':self.service_item_type,
u'audit':self.audit,
u'notes':self.notes,
u'from_plugin':self.from_plugin,
u'capabilities':self.capabilities
u'theme': self.theme,
u'title': self.title,
u'icon': self.icon,
u'footer': self.raw_footer,
u'type': self.service_item_type,
u'audit': self.audit,
u'notes': self.notes,
u'from_plugin': self.from_plugin,
u'capabilities': self.capabilities,
u'search': self.search_string,
u'data': self.data_string,
u'xml_version': self.xml_version
}
service_data = []
if self.service_item_type == ServiceItemType.Text:
@ -267,7 +267,7 @@ class ServiceItem(object):
elif self.service_item_type == ServiceItemType.Command:
for slide in self._raw_frames:
service_data.append(
{u'title':slide[u'title'], u'image':slide[u'image']})
{u'title': slide[u'title'], u'image': slide[u'image']})
return {u'header': service_header, u'data': service_data}
def set_from_service(self, serviceitem, path=None):
@ -293,19 +293,25 @@ class ServiceItem(object):
self.notes = header[u'notes']
self.from_plugin = header[u'from_plugin']
self.capabilities = header[u'capabilities']
# Added later so may not be present in older services.
if u'search' in header:
self.search_string = header[u'search']
self.data_string = header[u'data']
if u'xml_version' in header:
self.xml_version = header[u'xml_version']
if self.service_item_type == ServiceItemType.Text:
for slide in serviceitem[u'serviceitem'][u'data']:
self._raw_frames.append(slide)
elif self.service_item_type == ServiceItemType.Image:
for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image)
real_image = QtGui.QImage(unicode(filename))
self.add_from_image(path, text_image, real_image)
self.add_from_image(filename, text_image)
elif self.service_item_type == ServiceItemType.Command:
for text_image in serviceitem[u'serviceitem'][u'data']:
filename = os.path.join(path, text_image[u'title'])
self.add_from_command(
path, text_image[u'title'], text_image[u'image'] )
self._new_item()
def merge(self, other):
"""
@ -375,9 +381,11 @@ class ServiceItem(object):
renders it if required.
"""
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:
return self._raw_frames[row][u'image'], u''
return self._raw_frames[row][u'image']
def get_frame_title(self, row=0):
"""
@ -387,6 +395,6 @@ class ServiceItem(object):
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']

View File

@ -31,16 +31,19 @@ class SettingsTab(QtGui.QWidget):
SettingsTab is a helper widget for plugins to define Tabs for the settings
dialog.
"""
def __init__(self, title):
def __init__(self, title, visible_title=None):
"""
Constructor to create the Settings tab item.
``title``
The title of the tab, which is used internally for the tab handling.
``visible_title``
The title of the tab, which is usually displayed on the tab.
"""
QtGui.QWidget.__init__(self)
self.tabTitle = title
self.tabTitleVisible = None
self.tabTitleVisible = visible_title
self.settingsSection = self.tabTitle.lower()
self.setupUi()
self.retranslateUi()
@ -84,8 +87,12 @@ class SettingsTab(QtGui.QWidget):
"""
pass
def postSetUp(self):
def postSetUp(self, postUpdate=False):
"""
Changes which need to be made after setup of application
``postUpdate``
Indicates if called before or after updates.
"""
pass

View File

@ -25,7 +25,6 @@
###############################################################################
import re
import sys
try:
import enchant
from enchant import DictNotFoundError
@ -34,12 +33,15 @@ except ImportError:
enchant_available = False
# based on code from
# 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 openlp.core.lib import html_expands, translate, context_menu_action
from openlp.core.lib import html_expands, translate
class SpellTextEdit(QtGui.QPlainTextEdit):
"""
Spell checking widget based on QPlanTextEdit.
"""
def __init__(self, *args):
QtGui.QPlainTextEdit.__init__(self, *args)
# Default dictionary based on the current locale.
@ -61,7 +63,7 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
QtGui.QPlainTextEdit.mousePressEvent(self, event)
def contextMenuEvent(self, event):
popup_menu = self.createStandardContextMenu()
popupMenu = self.createStandardContextMenu()
# Select the word under the cursor.
cursor = self.textCursor()
# only select text if not already selected
@ -82,17 +84,17 @@ class SpellTextEdit(QtGui.QPlainTextEdit):
# Only add the spelling suggests to the menu if there are
# suggestions.
if len(spell_menu.actions()) != 0:
popup_menu.insertSeparator(popup_menu.actions()[0])
popup_menu.insertMenu(popup_menu.actions()[0], spell_menu)
tag_menu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',
popupMenu.insertSeparator(popupMenu.actions()[0])
popupMenu.insertMenu(popupMenu.actions()[0], spell_menu)
tagMenu = QtGui.QMenu(translate('OpenLP.SpellTextEdit',
'Formatting Tags'))
for html in html_expands:
action = SpellAction( html[u'desc'], tag_menu)
action = SpellAction( html[u'desc'], tagMenu)
action.correct.connect(self.htmlTag)
tag_menu.addAction(action)
popup_menu.insertSeparator(popup_menu.actions()[0])
popup_menu.insertMenu(popup_menu.actions()[0], tag_menu)
popup_menu.exec_(event.globalPos())
tagMenu.addAction(action)
popupMenu.insertSeparator(popupMenu.actions()[0])
popupMenu.insertMenu(popupMenu.actions()[0], tagMenu)
popupMenu.exec_(event.globalPos())
def correctWord(self, word):
"""

View File

@ -28,52 +28,55 @@ Provide the theme XML and handling functions for OpenLP v2 themes.
"""
import os
import re
import logging
from xml.dom.minidom import Document
from xml.etree.ElementTree import ElementTree, XML
from lxml import etree, objectify
from openlp.core.lib import str_to_bool
log = logging.getLogger(__name__)
BLANK_THEME_XML = \
'''<?xml version="1.0" encoding="utf-8"?>
<theme version="1.0">
<name>BlankStyle</name>
<background mode="transparent"/>
<background type="solid" mode="opaque">
<color>#000000</color>
<name> </name>
<background type="image">
<filename></filename>
</background>
<background type="gradient" mode="opaque">
<background type="gradient">
<startColor>#000000</startColor>
<endColor>#000000</endColor>
<direction>vertical</direction>
</background>
<background type="image" mode="opaque">
<filename></filename>
<background type="solid">
<color>#000000</color>
</background>
<font type="main">
<name>Arial</name>
<color>#000000</color>
<proportion>30</proportion>
<weight>Normal</weight>
<color>#FFFFFF</color>
<size>40</size>
<bold>False</bold>
<italics>False</italics>
<line_adjustment>0</line_adjustment>
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
<outline outlineColor="#000000" outlineSize="2">False</outline>
<location override="False" x="10" y="10" width="1004" height="690"/>
</font>
<font type="footer">
<name>Arial</name>
<color>#000000</color>
<proportion>12</proportion>
<weight>Normal</weight>
<color>#FFFFFF</color>
<size>12</size>
<bold>False</bold>
<italics>False</italics>
<line_adjustment>0</line_adjustment>
<shadow shadowColor="#000000" shadowSize="5">True</shadow>
<outline outlineColor="#000000" outlineSize="2">False</outline>
<location override="False" x="10" y="690" width="1004" height="78"/>
</font>
<display>
<shadow color="#000000" size="5">True</shadow>
<outline color="#000000" size="2">False</outline>
<horizontalAlign>0</horizontalAlign>
<verticalAlign>0</verticalAlign>
<wrapStyle>0</wrapStyle>
<slideTransition>False</slideTransition>
</display>
</theme>
@ -87,12 +90,78 @@ class ThemeLevel(object):
Service = 2
Song = 3
boolean_list = [u'italics', u'override', u'outline', u'shadow', \
u'slide_transition']
class BackgroundType(object):
Solid = 0
Gradient = 1
Image = 2
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'vertical_align', u'wrap_style' ]
@staticmethod
def to_string(type):
if type == BackgroundType.Solid:
return u'solid'
elif type == BackgroundType.Gradient:
return u'gradient'
elif type == BackgroundType.Image:
return u'image'
@staticmethod
def from_string(type_string):
if type_string == u'solid':
return BackgroundType.Solid
elif type_string == u'gradient':
return BackgroundType.Gradient
elif type_string == u'image':
return BackgroundType.Image
class BackgroundGradientType(object):
Horizontal = 0
Vertical = 1
Circular = 2
LeftTop = 3
LeftBottom = 4
@staticmethod
def to_string(type):
if type == BackgroundGradientType.Horizontal:
return u'horizontal'
elif type == BackgroundGradientType.Vertical:
return u'vertical'
elif type == BackgroundGradientType.Circular:
return u'circular'
elif type == BackgroundGradientType.LeftTop:
return u'leftTop'
elif type == BackgroundGradientType.LeftBottom:
return u'leftBottom'
@staticmethod
def from_string(type_string):
if type_string == u'horizontal':
return BackgroundGradientType.Horizontal
elif type_string == u'vertical':
return BackgroundGradientType.Vertical
elif type_string == u'circular':
return BackgroundGradientType.Circular
elif type_string == u'leftTop':
return BackgroundGradientType.LeftTop
elif type_string == u'leftBottom':
return BackgroundGradientType.LeftBottom
class HorizontalType(object):
Left = 0
Center = 1
Right = 2
class VerticalType(object):
Top = 0
Middle = 1
Bottom = 2
boolean_list = [u'italics', u'override', u'outline', u'shadow',
u'slide_transition']
integer_list = [u'size', u'line_adjustment', u'x', u'height', u'y',
u'width', u'shadow_size', u'outline_size', u'horizontal_align',
u'vertical_align', u'wrap_style']
class ThemeXML(object):
"""
@ -104,6 +173,7 @@ class ThemeXML(object):
"""
# Create the minidom document
self.theme_xml = Document()
self.parse_xml(BLANK_THEME_XML)
def extend_image_filename(self, path):
"""
@ -112,19 +182,21 @@ class ThemeXML(object):
``path``
The path name to be added.
"""
if self.background_filename and path:
self.theme_name = self.theme_name.strip()
self.background_filename = self.background_filename.strip()
self.background_filename = os.path.join(path, self.theme_name,
self.background_filename)
if self.background_type == u'image':
if self.background_filename and path:
self.theme_name = self.theme_name.strip()
self.background_filename = self.background_filename.strip()
self.background_filename = os.path.join(path, self.theme_name,
self.background_filename)
def new_document(self, name):
def _new_document(self, name):
"""
Create a new theme XML document.
"""
self.theme_xml = Document()
self.theme = self.theme_xml.createElement(u'theme')
self.theme_xml.appendChild(self.theme)
self.theme.setAttribute(u'version', u'1.0')
self.theme.setAttribute(u'version', u'2.0')
self.name = self.theme_xml.createElement(u'name')
text_node = self.theme_xml.createTextNode(name)
self.name.appendChild(text_node)
@ -146,10 +218,9 @@ class ThemeXML(object):
The color of the background.
"""
background = self.theme_xml.createElement(u'background')
background.setAttribute(u'mode', u'opaque')
background.setAttribute(u'type', u'solid')
self.theme.appendChild(background)
self.child_element(background, u'color', bkcolor)
self.child_element(background, u'color', unicode(bkcolor))
def add_background_gradient(self, startcolor, endcolor, direction):
"""
@ -165,15 +236,14 @@ class ThemeXML(object):
The direction of the gradient.
"""
background = self.theme_xml.createElement(u'background')
background.setAttribute(u'mode', u'opaque')
background.setAttribute(u'type', u'gradient')
self.theme.appendChild(background)
# Create startColor element
self.child_element(background, u'startColor', startcolor)
self.child_element(background, u'startColor', unicode(startcolor))
# Create endColor element
self.child_element(background, u'endColor', endcolor)
self.child_element(background, u'endColor', unicode(endcolor))
# Create direction element
self.child_element(background, u'direction', direction)
self.child_element(background, u'direction', unicode(direction))
def add_background_image(self, filename):
"""
@ -183,15 +253,16 @@ class ThemeXML(object):
The file name of the image.
"""
background = self.theme_xml.createElement(u'background')
background.setAttribute(u'mode', u'opaque')
background.setAttribute(u'type', u'image')
self.theme.appendChild(background)
#Create Filename element
# Create Filename element
self.child_element(background, u'filename', filename)
def add_font(self, name, color, proportion, override, fonttype=u'main',
weight=u'Normal', italics=u'False', line_adjustment=0,
xpos=0, ypos=0, width=0, height=0):
def add_font(self, name, color, size, override, fonttype=u'main',
bold=u'False', italics=u'False', line_adjustment=0,
xpos=0, ypos=0, width=0, height=0 , outline=u'False',
outline_color=u'#ffffff', outline_pixel=2, shadow=u'False',
shadow_color=u'#ffffff', shadow_pixel=5):
"""
Add a Font.
@ -201,7 +272,7 @@ class ThemeXML(object):
``color``
The colour of the font.
``proportion``
``size``
The size of the font.
``override``
@ -227,45 +298,6 @@ class ThemeXML(object):
``height``
The height of the text block.
"""
background = self.theme_xml.createElement(u'font')
background.setAttribute(u'type', fonttype)
self.theme.appendChild(background)
#Create Font name element
self.child_element(background, u'name', name)
#Create Font color element
self.child_element(background, u'color', color)
#Create Proportion name element
self.child_element(background, u'proportion', proportion)
#Create weight name element
self.child_element(background, u'weight', weight)
#Create italics name element
self.child_element(background, u'italics', italics)
#Create indentation name element
self.child_element(
background, u'line_adjustment', unicode(line_adjustment))
#Create Location element
element = self.theme_xml.createElement(u'location')
element.setAttribute(u'override', override)
if override == u'True':
element.setAttribute(u'x', xpos)
element.setAttribute(u'y', ypos)
element.setAttribute(u'width', width)
element.setAttribute(u'height', height)
background.appendChild(element)
def add_display(self, shadow, shadow_color, outline, outline_color,
horizontal, vertical, wrap, transition, shadow_pixel=5,
outline_pixel=2):
"""
Add a Display options.
``shadow``
Whether or not to show a shadow.
``shadow_color``
The colour of the shadow.
``outline``
Whether or not to show an outline.
@ -273,53 +305,87 @@ class ThemeXML(object):
``outline_color``
The colour of the outline.
``outline_size``
How big the Shadow is
``shadow``
Whether or not to show a shadow.
``shadow_color``
The colour of the shadow.
``shadow_size``
How big the Shadow is
"""
background = self.theme_xml.createElement(u'font')
background.setAttribute(u'type', fonttype)
self.theme.appendChild(background)
# Create Font name element
self.child_element(background, u'name', name)
# Create Font color element
self.child_element(background, u'color', unicode(color))
# Create Proportion name element
self.child_element(background, u'size', unicode(size))
# Create weight name element
self.child_element(background, u'bold', unicode(bold))
# Create italics name element
self.child_element(background, u'italics', unicode(italics))
# Create indentation name element
self.child_element(
background, u'line_adjustment', unicode(line_adjustment))
# Create Location element
element = self.theme_xml.createElement(u'location')
element.setAttribute(u'override', unicode(override))
element.setAttribute(u'x', unicode(xpos))
element.setAttribute(u'y', unicode(ypos))
element.setAttribute(u'width', unicode(width))
element.setAttribute(u'height', unicode(height))
background.appendChild(element)
# Shadow
element = self.theme_xml.createElement(u'shadow')
element.setAttribute(u'shadowColor', unicode(shadow_color))
element.setAttribute(u'shadowSize', unicode(shadow_pixel))
value = self.theme_xml.createTextNode(unicode(shadow))
element.appendChild(value)
background.appendChild(element)
# Outline
element = self.theme_xml.createElement(u'outline')
element.setAttribute(u'outlineColor', unicode(outline_color))
element.setAttribute(u'outlineSize', unicode(outline_pixel))
value = self.theme_xml.createTextNode(unicode(outline))
element.appendChild(value)
background.appendChild(element)
def add_display(self, horizontal, vertical, transition):
"""
Add a Display options.
``horizontal``
The horizontal alignment of the text.
``vertical``
The vertical alignment of the text.
``wrap``
Wrap style.
``transition``
Whether the slide transition is active.
"""
background = self.theme_xml.createElement(u'display')
self.theme.appendChild(background)
# Shadow
element = self.theme_xml.createElement(u'shadow')
element.setAttribute(u'color', shadow_color)
element.setAttribute(u'size', unicode(shadow_pixel))
value = self.theme_xml.createTextNode(shadow)
element.appendChild(value)
background.appendChild(element)
# Outline
element = self.theme_xml.createElement(u'outline')
element.setAttribute(u'color', outline_color)
element.setAttribute(u'size', unicode(outline_pixel))
value = self.theme_xml.createTextNode(outline)
element.appendChild(value)
background.appendChild(element)
# Horizontal alignment
element = self.theme_xml.createElement(u'horizontalAlign')
value = self.theme_xml.createTextNode(horizontal)
value = self.theme_xml.createTextNode(unicode(horizontal))
element.appendChild(value)
background.appendChild(element)
# Vertical alignment
element = self.theme_xml.createElement(u'verticalAlign')
value = self.theme_xml.createTextNode(vertical)
element.appendChild(value)
background.appendChild(element)
# Wrap style
element = self.theme_xml.createElement(u'wrapStyle')
value = self.theme_xml.createTextNode(wrap)
value = self.theme_xml.createTextNode(unicode(vertical))
element.appendChild(value)
background.appendChild(element)
# Slide Transition
element = self.theme_xml.createElement(u'slideTransition')
value = self.theme_xml.createTextNode(transition)
value = self.theme_xml.createTextNode(unicode(transition))
element.appendChild(value)
background.appendChild(element)
@ -342,12 +408,14 @@ class ThemeXML(object):
"""
Print out the XML string.
"""
self._build_xml_from_attrs()
return self.theme_xml.toxml(u'utf-8').decode(u'utf-8')
def extract_formatted_xml(self):
"""
Pull out the XML string formatted for human consumption
"""
self._build_xml_from_attrs()
return self.theme_xml.toprettyxml(indent=u' ', newl=u'\n',
encoding=u'utf-8')
@ -358,8 +426,7 @@ class ThemeXML(object):
``xml``
The XML string to parse.
"""
self.parse_xml(BLANK_THEME_XML)
self.parse_xml(xml)
self.parse_xml(unicode(xml))
def parse_xml(self, xml):
"""
@ -368,47 +435,97 @@ class ThemeXML(object):
``xml``
The XML string to parse.
"""
theme_xml = ElementTree(element=XML(xml.encode(u'ascii',
u'xmlcharrefreplace')))
# remove encoding string
line = xml.find(u'?>')
if line:
xml = xml[line + 2:]
try:
theme_xml = objectify.fromstring(xml)
except etree.XMLSyntaxError:
log.exception(u'Invalid xml %s', xml)
return
xml_iter = theme_xml.getiterator()
master = u''
for element in xml_iter:
if not isinstance(element.text, unicode):
element.text = unicode(str(element.text), u'utf-8')
if element.getchildren():
master = element.tag + u'_'
parent = element.getparent()
master = u''
if parent is not None:
if element.getparent().tag == u'font':
master = element.getparent().tag + u'_' + \
element.getparent().attrib[u'type']
# set up Outline and Shadow Tags and move to font_main
if element.getparent().tag == u'display':
if element.tag.startswith(u'shadow') or \
element.tag.startswith(u'outline'):
self._create_attr(u'font_main', element.tag,
element.text)
master = element.getparent().tag
if element.getparent().tag == u'background':
master = element.getparent().tag
if element.getparent().attrib:
for attr in element.getparent().attrib:
self._create_attr(master, attr, \
element.getparent().attrib[attr])
if master:
self._create_attr(master, element.tag, element.text)
if element.attrib:
for attr in element.attrib:
base_element = attr
# correction for the shadow and outline tags
if element.tag == u'shadow' or \
element.tag == u'outline':
if not attr.startswith(element.tag):
base_element = element.tag + u'_' + attr
self._create_attr(master, base_element,
element.attrib[attr])
else:
# background transparent tags have no children so special case
if element.tag == u'background':
for e in element.attrib.iteritems():
self._create_attr(element.tag , e[0], e[1])
if element.attrib:
for e in element.attrib.iteritems():
if master == u'font_' and e[0] == u'type':
master += e[1] + u'_'
elif master == u'display_' and (element.tag == u'shadow' \
or element.tag == u'outline' ):
self._create_attr(master, element.tag, element.text)
self._create_attr(master, element.tag + u'_'+ e[0], e[1])
else:
field = master + e[0]
self._create_attr(master, e[0], e[1])
if element.tag == u'name':
self._create_attr(u'theme', element.tag, element.text)
def _translate_tags(self, master, element, value):
"""
Clean up XML removing and redefining tags
"""
master = master.strip().lstrip()
element = element.strip().lstrip()
value = unicode(value).strip().lstrip()
if master == u'display':
if element == u'wrapStyle':
return True, None, None, None
if element.startswith(u'shadow') or element.startswith(u'outline'):
master = u'font_main'
# fix bold font
if element == u'weight':
element = u'bold'
if value == u'Normal':
value = False
else:
if element.tag:
element.text = element.text.strip().lstrip()
self._create_attr(master , element.tag, element.text)
value = True
if element == u'proportion':
element = u'size'
return False, master, element, value
def _create_attr(self, master , element, value):
"""
Create the attributes with the correct data types and name format
"""
reject, master, element, value = \
self._translate_tags(master, element, value)
if reject:
return
field = self._de_hump(element)
tag = master + u'_' + field
if field in boolean_list:
setattr(self, master + field, str_to_bool(value))
setattr(self, tag, str_to_bool(value))
elif field in integer_list:
setattr(self, master + field, int(value))
setattr(self, tag, int(value))
else:
setattr(self, master + field, unicode(value))
# make string value unicode
if not isinstance(value, unicode):
value = unicode(str(value), u'utf-8')
# None means an empty string so lets have one.
if value == u'None':
value = u''
setattr(self, tag, unicode(value).strip().lstrip())
def __str__(self):
"""
@ -424,6 +541,61 @@ class ThemeXML(object):
"""
Change Camel Case string to python string
"""
s1 = re.sub(u'(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub(u'([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
sub_name = re.sub(u'(.)([A-Z][a-z]+)', r'\1_\2', name)
return re.sub(u'([a-z0-9])([A-Z])', r'\1_\2', sub_name).lower()
def _build_xml_from_attrs(self):
"""
Build the XML from the varables in the object
"""
self._new_document(self.theme_name)
if self.background_type == \
BackgroundType.to_string(BackgroundType.Solid):
self.add_background_solid(self.background_color)
elif self.background_type == \
BackgroundType.to_string(BackgroundType.Gradient):
self.add_background_gradient(
self.background_start_color,
self.background_end_color,
self.background_direction)
else:
filename = \
os.path.split(self.background_filename)[1]
self.add_background_image(filename)
self.add_font(self.font_main_name,
self.font_main_color,
self.font_main_size,
self.font_main_override, u'main',
self.font_main_bold,
self.font_main_italics,
self.font_main_line_adjustment,
self.font_main_x,
self.font_main_y,
self.font_main_width,
self.font_main_height,
self.font_main_outline,
self.font_main_outline_color,
self.font_main_outline_size,
self.font_main_shadow,
self.font_main_shadow_color,
self.font_main_shadow_size)
self.add_font(self.font_footer_name,
self.font_footer_color,
self.font_footer_size,
self.font_footer_override, u'footer',
self.font_footer_bold,
self.font_footer_italics,
0, # line adjustment
self.font_footer_x,
self.font_footer_y,
self.font_footer_width,
self.font_footer_height,
self.font_footer_outline,
self.font_footer_outline_color,
self.font_footer_outline_size,
self.font_footer_shadow,
self.font_footer_shadow_color,
self.font_footer_shadow_size)
self.add_display(self.display_horizontal_align,
self.display_vertical_align,
self.display_slide_transition)

View File

@ -37,13 +37,12 @@ class HideMode(object):
Theme = 2
Screen = 3
from themeform import ThemeForm
from filerenameform import FileRenameForm
from maindisplay import MainDisplay
from slidecontroller import HideMode
from servicenoteform import ServiceNoteForm
from serviceitemeditform import ServiceItemEditForm
from screen import ScreenList
from amendthemeform import AmendThemeForm
from slidecontroller import SlideController
from splashscreen import SplashScreen
from generaltab import GeneralTab
@ -52,10 +51,11 @@ from advancedtab import AdvancedTab
from aboutform import AboutForm
from pluginform import PluginForm
from settingsform import SettingsForm
from shortcutlistform import ShortcutListForm
from mediadockmanager import MediaDockManager
from servicemanager import ServiceManager
from thememanager import ThemeManager
__all__ = ['SplashScreen', 'AboutForm', 'SettingsForm',
'MainDisplay', 'SlideController', 'ServiceManager', 'ThemeManager',
'AmendThemeForm', 'MediaDockManager', 'ServiceItemEditForm']
'MediaDockManager', 'ServiceItemEditForm']

View File

@ -166,6 +166,17 @@ class Ui_AboutDialog(object):
' PyQt4: http://www.riverbankcomputing.co.uk/software/pyqt/'
'intro\n'
' Oxygen Icons: http://oxygen-icons.org/\n'
'\n'
'Final Credit\n'
' "For God so loved the world that He gave\n'
' His one and only Son, so that whoever\n'
' believes in Him will not perish but inherit\n'
' eternal life." -- John 3:16\n\n'
' And last but not least, final credit goes to\n'
' God our Father, for sending His Son to die\n'
' on the cross, setting us free from sin. We\n'
' bring this software to you for free because\n'
' He has set us free.'
))
self.aboutNotebook.setTabText(
self.aboutNotebook.indexOf(self.creditsTab),

View File

@ -81,7 +81,15 @@ class AdvancedTab(SettingsTab):
self.doubleClickLiveCheckBox = QtGui.QCheckBox(self.uiGroupBox)
self.doubleClickLiveCheckBox.setObjectName(u'doubleClickLiveCheckBox')
self.uiLayout.addWidget(self.doubleClickLiveCheckBox)
# self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox)
# self.expandServiceItemCheckBox.setObjectName(
# u'expandServiceItemCheckBox')
# self.uiLayout.addWidget(self.expandServiceItemCheckBox)
self.leftLayout.addWidget(self.uiGroupBox)
self.expandServiceItemCheckBox = QtGui.QCheckBox(self.uiGroupBox)
self.expandServiceItemCheckBox.setObjectName(
u'expandServiceItemCheckBox')
self.uiLayout.addWidget(self.expandServiceItemCheckBox)
# self.sharedDirGroupBox = QtGui.QGroupBox(self.leftWidget)
# self.sharedDirGroupBox.setObjectName(u'sharedDirGroupBox')
# self.sharedDirGroupBox.setGeometry(QtCore.QRect(0, 65, 500, 85))
@ -139,7 +147,9 @@ class AdvancedTab(SettingsTab):
self.mediaPluginCheckBox.setText(translate('OpenLP.AdvancedTab',
'Remember active media manager tab on startup'))
self.doubleClickLiveCheckBox.setText(translate('OpenLP.AdvancedTab',
'Double-click to send items straight to live (requires restart)'))
'Double-click to send items straight to live'))
self.expandServiceItemCheckBox.setText(translate('OpenLP.AdvancedTab',
'Expand new service items on creation'))
# self.sharedDirGroupBox.setTitle(
# translate('AdvancedTab', 'Central Data Store'))
# self.sharedCheckBox.setText(
@ -167,6 +177,9 @@ class AdvancedTab(SettingsTab):
self.doubleClickLiveCheckBox.setChecked(
settings.value(u'double click live',
QtCore.QVariant(False)).toBool())
self.expandServiceItemCheckBox.setChecked(
settings.value(u'expand service item',
QtCore.QVariant(False)).toBool())
settings.endGroup()
def save(self):
@ -181,6 +194,8 @@ class AdvancedTab(SettingsTab):
QtCore.QVariant(self.mediaPluginCheckBox.isChecked()))
settings.setValue(u'double click live',
QtCore.QVariant(self.doubleClickLiveCheckBox.isChecked()))
settings.setValue(u'expand service item',
QtCore.QVariant(self.expandServiceItemCheckBox.isChecked()))
settings.endGroup()
def onSharedCheckBoxChanged(self, checked):

View File

@ -1,799 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate
class Ui_AmendThemeDialog(object):
def setupUi(self, amendThemeDialog):
amendThemeDialog.setObjectName(u'amendThemeDialog')
amendThemeDialog.setWindowModality(QtCore.Qt.ApplicationModal)
amendThemeDialog.resize(586, 651)
icon = build_icon(u':/icon/openlp-logo-16x16.png')
amendThemeDialog.setWindowIcon(icon)
amendThemeDialog.setModal(True)
self.amendThemeLayout = QtGui.QVBoxLayout(amendThemeDialog)
self.amendThemeLayout.setSpacing(8)
self.amendThemeLayout.setMargin(8)
self.amendThemeLayout.setObjectName(u'amendThemeLayout')
self.themeNameWidget = QtGui.QWidget(amendThemeDialog)
self.themeNameWidget.setObjectName(u'themeNameWidget')
self.themeNameLayout = QtGui.QHBoxLayout(self.themeNameWidget)
self.themeNameLayout.setSpacing(8)
self.themeNameLayout.setMargin(0)
self.themeNameLayout.setObjectName(u'themeNameLayout')
self.themeNameLabel = QtGui.QLabel(self.themeNameWidget)
self.themeNameLabel.setObjectName(u'themeNameLabel')
self.themeNameLayout.addWidget(self.themeNameLabel)
self.themeNameEdit = QtGui.QLineEdit(self.themeNameWidget)
self.themeNameEdit.setObjectName(u'themeNameEdit')
self.themeNameLabel.setBuddy(self.themeNameEdit)
self.themeNameLayout.addWidget(self.themeNameEdit)
self.amendThemeLayout.addWidget(self.themeNameWidget)
self.contentWidget = QtGui.QWidget(amendThemeDialog)
self.contentWidget.setObjectName(u'contentWidget')
self.contentLayout = QtGui.QHBoxLayout(self.contentWidget)
self.contentLayout.setSpacing(8)
self.contentLayout.setMargin(0)
self.contentLayout.setObjectName(u'contentLayout')
self.themeTabWidget = QtGui.QTabWidget(self.contentWidget)
self.themeTabWidget.setObjectName(u'themeTabWidget')
self.backgroundTab = QtGui.QWidget()
self.backgroundTab.setObjectName(u'backgroundTab')
self.backgroundLayout = QtGui.QFormLayout(self.backgroundTab)
self.backgroundLayout.setMargin(8)
self.backgroundLayout.setSpacing(8)
self.backgroundLayout.setObjectName(u'backgroundLayout')
self.backgroundTypeLabel = QtGui.QLabel(self.backgroundTab)
self.backgroundTypeLabel.setObjectName(u'backgroundTypeLabel')
self.backgroundLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.backgroundTypeLabel)
self.backgroundTypeComboBox = QtGui.QComboBox(self.backgroundTab)
self.backgroundTypeComboBox.setObjectName(u'backgroundTypeComboBox')
self.backgroundTypeComboBox.addItem(QtCore.QString())
self.backgroundTypeComboBox.addItem(QtCore.QString())
self.backgroundTypeComboBox.addItem(QtCore.QString())
self.backgroundLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.backgroundTypeComboBox)
self.color1Label = QtGui.QLabel(self.backgroundTab)
self.color1Label.setObjectName(u'color1Label')
self.backgroundLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.color1Label)
self.color1PushButton = QtGui.QPushButton(self.backgroundTab)
self.color1PushButton.setObjectName(u'color1PushButton')
self.backgroundLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.color1PushButton)
self.color2Label = QtGui.QLabel(self.backgroundTab)
self.color2Label.setObjectName(u'color2Label')
self.backgroundLayout.setWidget(3, QtGui.QFormLayout.LabelRole,
self.color2Label)
self.color2PushButton = QtGui.QPushButton(self.backgroundTab)
self.color2PushButton.setObjectName(u'color2PushButton')
self.backgroundLayout.setWidget(3, QtGui.QFormLayout.FieldRole,
self.color2PushButton)
self.imageLabel = QtGui.QLabel(self.backgroundTab)
self.imageLabel.setObjectName(u'imageLabel')
self.backgroundLayout.setWidget(4, QtGui.QFormLayout.LabelRole,
self.imageLabel)
self.gradientLabel = QtGui.QLabel(self.backgroundTab)
self.gradientLabel.setObjectName(u'gradientLabel')
self.backgroundLayout.setWidget(6, QtGui.QFormLayout.LabelRole,
self.gradientLabel)
self.gradientComboBox = QtGui.QComboBox(self.backgroundTab)
self.gradientComboBox.setObjectName(u'gradientComboBox')
self.gradientComboBox.addItem(QtCore.QString())
self.gradientComboBox.addItem(QtCore.QString())
self.gradientComboBox.addItem(QtCore.QString())
self.backgroundLayout.setWidget(6, QtGui.QFormLayout.FieldRole,
self.gradientComboBox)
self.imageFilenameWidget = QtGui.QWidget(self.backgroundTab)
self.imageFilenameWidget.setObjectName(u'imageFilenameWidget')
self.horizontalLayout2 = QtGui.QHBoxLayout(self.imageFilenameWidget)
self.horizontalLayout2.setSpacing(0)
self.horizontalLayout2.setMargin(0)
self.horizontalLayout2.setObjectName(u'horizontalLayout2')
self.imageLineEdit = QtGui.QLineEdit(self.imageFilenameWidget)
self.imageLineEdit.setObjectName(u'imageLineEdit')
self.horizontalLayout2.addWidget(self.imageLineEdit)
self.imageToolButton = QtGui.QToolButton(self.imageFilenameWidget)
self.imageToolButton.setIcon(build_icon(u':/general/general_open.png'))
self.imageToolButton.setObjectName(u'imageToolButton')
self.imageToolButton.setAutoRaise(True)
self.horizontalLayout2.addWidget(self.imageToolButton)
self.backgroundLayout.setWidget(4, QtGui.QFormLayout.FieldRole,
self.imageFilenameWidget)
self.themeTabWidget.addTab(self.backgroundTab, u'')
self.fontMainTab = QtGui.QWidget()
self.fontMainTab.setObjectName(u'fontMainTab')
self.fontMainLayout = QtGui.QHBoxLayout(self.fontMainTab)
self.fontMainLayout.setSpacing(8)
self.fontMainLayout.setMargin(8)
self.fontMainLayout.setObjectName(u'fontMainLayout')
self.mainLeftWidget = QtGui.QWidget(self.fontMainTab)
self.mainLeftWidget.setObjectName(u'mainLeftWidget')
self.mainLeftLayout = QtGui.QVBoxLayout(self.mainLeftWidget)
self.mainLeftLayout.setSpacing(8)
self.mainLeftLayout.setMargin(0)
self.mainLeftLayout.setObjectName(u'mainLeftLayout')
self.fontMainGroupBox = QtGui.QGroupBox(self.mainLeftWidget)
self.fontMainGroupBox.setObjectName(u'fontMainGroupBox')
self.mainFontLayout = QtGui.QFormLayout(self.fontMainGroupBox)
self.mainFontLayout.setFormAlignment(QtCore.Qt.AlignLeading |
QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.mainFontLayout.setMargin(8)
self.mainFontLayout.setSpacing(8)
self.mainFontLayout.setObjectName(u'mainFontLayout')
self.fontMainlabel = QtGui.QLabel(self.fontMainGroupBox)
self.fontMainlabel.setObjectName(u'fontMainlabel')
self.mainFontLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.fontMainlabel)
self.fontMainComboBox = QtGui.QFontComboBox(self.fontMainGroupBox)
self.fontMainComboBox.setObjectName(u'fontMainComboBox')
self.mainFontLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.fontMainComboBox)
self.fontMainColorLabel = QtGui.QLabel(self.fontMainGroupBox)
self.fontMainColorLabel.setObjectName(u'fontMainColorLabel')
self.mainFontLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.fontMainColorLabel)
self.fontMainColorPushButton = QtGui.QPushButton(self.fontMainGroupBox)
self.fontMainColorPushButton.setObjectName(u'fontMainColorPushButton')
self.mainFontLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.fontMainColorPushButton)
self.fontMainSize = QtGui.QLabel(self.fontMainGroupBox)
self.fontMainSize.setObjectName(u'fontMainSize')
self.mainFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.fontMainSize)
self.fontMainSizeSpinBox = QtGui.QSpinBox(self.fontMainGroupBox)
defaultSizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Fixed)
defaultSizePolicy.setHeightForWidth(
self.fontMainSizeSpinBox.sizePolicy().hasHeightForWidth())
self.fontMainSizeSpinBox.setSizePolicy(defaultSizePolicy)
self.fontMainSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0))
self.fontMainSizeSpinBox.setProperty(u'value', QtCore.QVariant(16))
self.fontMainSizeSpinBox.setMaximum(999)
self.fontMainSizeSpinBox.setObjectName(u'fontMainSizeSpinBox')
self.mainFontLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.fontMainSizeSpinBox)
self.fontMainWeightComboBox = QtGui.QComboBox(self.fontMainGroupBox)
self.fontMainWeightComboBox.setObjectName(u'fontMainWeightComboBox')
self.fontMainWeightComboBox.addItem(QtCore.QString())
self.fontMainWeightComboBox.addItem(QtCore.QString())
self.fontMainWeightComboBox.addItem(QtCore.QString())
self.fontMainWeightComboBox.addItem(QtCore.QString())
self.mainFontLayout.setWidget(3, QtGui.QFormLayout.FieldRole,
self.fontMainWeightComboBox)
self.fontMainWeightLabel = QtGui.QLabel(self.fontMainGroupBox)
self.fontMainWeightLabel.setObjectName(u'fontMainWeightLabel')
self.mainFontLayout.setWidget(3, QtGui.QFormLayout.LabelRole,
self.fontMainWeightLabel)
self.mainLeftLayout.addWidget(self.fontMainGroupBox)
self.fontMainWrapLineAdjustmentLabel = QtGui.QLabel(
self.fontMainGroupBox)
self.fontMainWrapLineAdjustmentLabel.setObjectName(
u'fontMainWrapLineAdjustmentLabel')
self.mainFontLayout.setWidget(4, QtGui.QFormLayout.LabelRole,
self.fontMainWrapLineAdjustmentLabel)
self.fontMainLineAdjustmentSpinBox = QtGui.QSpinBox(
self.fontMainGroupBox)
self.fontMainLineAdjustmentSpinBox.setObjectName(
u'fontMainLineAdjustmentSpinBox')
self.fontMainLineAdjustmentSpinBox.setMinimum(-99)
self.mainFontLayout.setWidget(4, QtGui.QFormLayout.FieldRole,
self.fontMainLineAdjustmentSpinBox)
self.fontMainLinesPageLabel = QtGui.QLabel(self.fontMainGroupBox)
self.fontMainLinesPageLabel.setObjectName(u'fontMainLinesPageLabel')
self.mainFontLayout.addRow(self.fontMainLinesPageLabel)
spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.mainLeftLayout.addItem(spacerItem1)
self.fontMainLayout.addWidget(self.mainLeftWidget)
self.mainRightWidget = QtGui.QWidget(self.fontMainTab)
self.mainRightWidget.setObjectName(u'mainRightWidget')
self.mainRightLayout = QtGui.QVBoxLayout(self.mainRightWidget)
self.mainRightLayout.setSpacing(8)
self.mainRightLayout.setMargin(0)
self.mainRightLayout.setObjectName(u'mainRightLayout')
self.mainLocationGroupBox = QtGui.QGroupBox(self.mainRightWidget)
self.mainLocationGroupBox.setObjectName(u'mainLocationGroupBox')
self.mainLocationLayout = QtGui.QFormLayout(self.mainLocationGroupBox)
self.mainLocationLayout.setMargin(8)
self.mainLocationLayout.setSpacing(8)
self.mainLocationLayout.setObjectName(u'mainLocationLayout')
self.defaultLocationLabel = QtGui.QLabel(self.mainLocationGroupBox)
self.defaultLocationLabel.setObjectName(u'defaultLocationLabel')
self.mainLocationLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.defaultLocationLabel)
self.fontMainDefaultCheckBox = QtGui.QCheckBox(
self.mainLocationGroupBox)
self.fontMainDefaultCheckBox.setTristate(False)
self.fontMainDefaultCheckBox.setObjectName(u'fontMainDefaultCheckBox')
self.mainLocationLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.fontMainDefaultCheckBox)
self.fontMainXLabel = QtGui.QLabel(self.mainLocationGroupBox)
self.fontMainXLabel.setObjectName(u'fontMainXLabel')
self.mainLocationLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.fontMainXLabel)
self.fontMainYLabel = QtGui.QLabel(self.mainLocationGroupBox)
self.fontMainYLabel.setObjectName(u'fontMainYLabel')
self.mainLocationLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.fontMainYLabel)
self.fontMainWidthLabel = QtGui.QLabel(self.mainLocationGroupBox)
self.fontMainWidthLabel.setObjectName(u'fontMainWidthLabel')
self.mainLocationLayout.setWidget(3, QtGui.QFormLayout.LabelRole,
self.fontMainWidthLabel)
self.fontMainHeightLabel = QtGui.QLabel(self.mainLocationGroupBox)
self.fontMainHeightLabel.setObjectName(u'fontMainHeightLabel')
self.mainLocationLayout.setWidget(4, QtGui.QFormLayout.LabelRole,
self.fontMainHeightLabel)
self.fontMainXSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontMainXSpinBox.sizePolicy().hasHeightForWidth())
self.fontMainXSpinBox.setSizePolicy(defaultSizePolicy)
self.fontMainXSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontMainXSpinBox.setProperty(u'value', QtCore.QVariant(0))
self.fontMainXSpinBox.setMaximum(9999)
self.fontMainXSpinBox.setObjectName(u'fontMainXSpinBox')
self.mainLocationLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.fontMainXSpinBox)
self.fontMainYSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontMainYSpinBox.sizePolicy().hasHeightForWidth())
self.fontMainYSpinBox.setSizePolicy(defaultSizePolicy)
self.fontMainYSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontMainYSpinBox.setMaximum(9999)
self.fontMainYSpinBox.setObjectName(u'fontMainYSpinBox')
self.mainLocationLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.fontMainYSpinBox)
self.fontMainWidthSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontMainWidthSpinBox.sizePolicy().hasHeightForWidth())
self.fontMainWidthSpinBox.setSizePolicy(defaultSizePolicy)
self.fontMainWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontMainWidthSpinBox.setMaximum(9999)
self.fontMainWidthSpinBox.setObjectName(u'fontMainWidthSpinBox')
self.mainLocationLayout.setWidget(3, QtGui.QFormLayout.FieldRole,
self.fontMainWidthSpinBox)
self.fontMainHeightSpinBox = QtGui.QSpinBox(self.mainLocationGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontMainHeightSpinBox.sizePolicy().hasHeightForWidth())
self.fontMainHeightSpinBox.setSizePolicy(defaultSizePolicy)
self.fontMainHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontMainHeightSpinBox.setMaximum(9999)
self.fontMainHeightSpinBox.setObjectName(u'fontMainHeightSpinBox')
self.mainLocationLayout.setWidget(4, QtGui.QFormLayout.FieldRole,
self.fontMainHeightSpinBox)
self.mainRightLayout.addWidget(self.mainLocationGroupBox)
spacerItem2 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.mainRightLayout.addItem(spacerItem2)
self.fontMainLayout.addWidget(self.mainRightWidget)
self.themeTabWidget.addTab(self.fontMainTab, u'')
self.fontFooterTab = QtGui.QWidget()
self.fontFooterTab.setObjectName(u'fontFooterTab')
self.fontFooterLayout = QtGui.QHBoxLayout(self.fontFooterTab)
self.fontFooterLayout.setSpacing(8)
self.fontFooterLayout.setMargin(8)
self.fontFooterLayout.setObjectName(u'fontFooterLayout')
self.footerLeftWidget = QtGui.QWidget(self.fontFooterTab)
self.footerLeftWidget.setObjectName(u'footerLeftWidget')
self.footerLeftLayout = QtGui.QVBoxLayout(self.footerLeftWidget)
self.footerLeftLayout.setSpacing(8)
self.footerLeftLayout.setMargin(0)
self.footerLeftLayout.setObjectName(u'footerLeftLayout')
self.footerFontGroupBox = QtGui.QGroupBox(self.footerLeftWidget)
self.footerFontGroupBox.setObjectName(u'footerFontGroupBox')
self.footerFontLayout = QtGui.QFormLayout(self.footerFontGroupBox)
self.footerFontLayout.setFieldGrowthPolicy(
QtGui.QFormLayout.ExpandingFieldsGrow)
self.footerFontLayout.setFormAlignment(QtCore.Qt.AlignLeading |
QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.footerFontLayout.setMargin(8)
self.footerFontLayout.setSpacing(8)
self.footerFontLayout.setObjectName(u'footerFontLayout')
self.fontFooterLabel = QtGui.QLabel(self.footerFontGroupBox)
self.fontFooterLabel.setObjectName(u'fontFooterLabel')
self.footerFontLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.fontFooterLabel)
self.fontFooterComboBox = QtGui.QFontComboBox(self.footerFontGroupBox)
self.fontFooterComboBox.setObjectName(u'fontFooterComboBox')
self.footerFontLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.fontFooterComboBox)
self.fontFooterColorLabel = QtGui.QLabel(self.footerFontGroupBox)
self.fontFooterColorLabel.setObjectName(u'fontFooterColorLabel')
self.footerFontLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.fontFooterColorLabel)
self.fontFooterColorPushButton = QtGui.QPushButton(
self.footerFontGroupBox)
self.fontFooterColorPushButton.setObjectName(
u'fontFooterColorPushButton')
self.footerFontLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.fontFooterColorPushButton)
self.fontFooterSizeLabel = QtGui.QLabel(self.footerFontGroupBox)
self.fontFooterSizeLabel.setObjectName(u'fontFooterSizeLabel')
self.footerFontLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.fontFooterSizeLabel)
self.fontFooterSizeSpinBox = QtGui.QSpinBox(self.footerFontGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontFooterSizeSpinBox.sizePolicy().hasHeightForWidth())
self.fontFooterSizeSpinBox.setSizePolicy(defaultSizePolicy)
self.fontFooterSizeSpinBox.setMinimumSize(QtCore.QSize(70, 0))
self.fontFooterSizeSpinBox.setProperty(u'value', QtCore.QVariant(10))
self.fontFooterSizeSpinBox.setMaximum(999)
self.fontFooterSizeSpinBox.setObjectName(u'fontFooterSizeSpinBox')
self.footerFontLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.fontFooterSizeSpinBox)
self.fontFooterWeightComboBox = QtGui.QComboBox(self.footerFontGroupBox)
self.fontFooterWeightComboBox.setObjectName(u'fontFooterWeightComboBox')
self.fontFooterWeightComboBox.addItem(QtCore.QString())
self.fontFooterWeightComboBox.addItem(QtCore.QString())
self.fontFooterWeightComboBox.addItem(QtCore.QString())
self.fontFooterWeightComboBox.addItem(QtCore.QString())
self.footerFontLayout.setWidget(3, QtGui.QFormLayout.FieldRole,
self.fontFooterWeightComboBox)
self.fontFooterWeightLabel = QtGui.QLabel(self.footerFontGroupBox)
self.fontFooterWeightLabel.setObjectName(u'fontFooterWeightLabel')
self.footerFontLayout.setWidget(3, QtGui.QFormLayout.LabelRole,
self.fontFooterWeightLabel)
self.footerLeftLayout.addWidget(self.footerFontGroupBox)
spacerItem3 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.footerLeftLayout.addItem(spacerItem3)
self.fontFooterLayout.addWidget(self.footerLeftWidget)
self.footerRightWidget = QtGui.QWidget(self.fontFooterTab)
self.footerRightWidget.setObjectName(u'footerRightWidget')
self.footerRightLayout = QtGui.QVBoxLayout(self.footerRightWidget)
self.footerRightLayout.setSpacing(8)
self.footerRightLayout.setMargin(0)
self.footerRightLayout.setObjectName(u'footerRightLayout')
self.locationFooterGroupBox = QtGui.QGroupBox(self.footerRightWidget)
self.locationFooterGroupBox.setObjectName(u'locationFooterGroupBox')
self.locationFooterLayout = QtGui.QFormLayout(
self.locationFooterGroupBox)
self.locationFooterLayout.setFieldGrowthPolicy(
QtGui.QFormLayout.ExpandingFieldsGrow)
self.locationFooterLayout.setFormAlignment(QtCore.Qt.AlignLeading |
QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.locationFooterLayout.setMargin(8)
self.locationFooterLayout.setSpacing(8)
self.locationFooterLayout.setObjectName(u'locationFooterLayout')
self.fontFooterDefaultLabel = QtGui.QLabel(self.locationFooterGroupBox)
self.fontFooterDefaultLabel.setObjectName(u'fontFooterDefaultLabel')
self.locationFooterLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.fontFooterDefaultLabel)
self.fontFooterDefaultCheckBox = QtGui.QCheckBox(
self.locationFooterGroupBox)
self.fontFooterDefaultCheckBox.setTristate(False)
self.fontFooterDefaultCheckBox.setObjectName(
u'fontFooterDefaultCheckBox')
self.locationFooterLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.fontFooterDefaultCheckBox)
self.fontFooterXLabel = QtGui.QLabel(self.locationFooterGroupBox)
self.fontFooterXLabel.setObjectName(u'fontFooterXLabel')
self.locationFooterLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.fontFooterXLabel)
self.fontFooterYLabel = QtGui.QLabel(self.locationFooterGroupBox)
self.fontFooterYLabel.setObjectName(u'fontFooterYLabel')
self.locationFooterLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.fontFooterYLabel)
self.fontFooterWidthLabel = QtGui.QLabel(self.locationFooterGroupBox)
self.fontFooterWidthLabel.setObjectName(u'fontFooterWidthLabel')
self.locationFooterLayout.setWidget(3, QtGui.QFormLayout.LabelRole,
self.fontFooterWidthLabel)
self.fontFooterHeightLabel = QtGui.QLabel(self.locationFooterGroupBox)
self.fontFooterHeightLabel.setObjectName(u'fontFooterHeightLabel')
self.locationFooterLayout.setWidget(4, QtGui.QFormLayout.LabelRole,
self.fontFooterHeightLabel)
self.fontFooterXSpinBox = QtGui.QSpinBox(self.locationFooterGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontFooterXSpinBox.sizePolicy().hasHeightForWidth())
self.fontFooterXSpinBox.setSizePolicy(defaultSizePolicy)
self.fontFooterXSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontFooterXSpinBox.setProperty(u'value', QtCore.QVariant(0))
self.fontFooterXSpinBox.setMaximum(9999)
self.fontFooterXSpinBox.setObjectName(u'fontFooterXSpinBox')
self.locationFooterLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.fontFooterXSpinBox)
self.fontFooterYSpinBox = QtGui.QSpinBox(self.locationFooterGroupBox)
defaultSizePolicy.setHeightForWidth(
self.fontFooterXSpinBox.sizePolicy().hasHeightForWidth())
self.fontFooterYSpinBox.setSizePolicy(defaultSizePolicy)
self.fontFooterYSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontFooterYSpinBox.setProperty(u'value', QtCore.QVariant(0))
self.fontFooterYSpinBox.setMaximum(9999)
self.fontFooterYSpinBox.setObjectName(u'fontFooterYSpinBox')
self.locationFooterLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.fontFooterYSpinBox)
self.fontFooterWidthSpinBox = QtGui.QSpinBox(
self.locationFooterGroupBox)
self.fontFooterWidthSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontFooterWidthSpinBox.setMaximum(9999)
self.fontFooterWidthSpinBox.setObjectName(u'fontFooterWidthSpinBox')
self.locationFooterLayout.setWidget(3, QtGui.QFormLayout.FieldRole,
self.fontFooterWidthSpinBox)
self.fontFooterHeightSpinBox = QtGui.QSpinBox(
self.locationFooterGroupBox)
self.fontFooterHeightSpinBox.setMinimumSize(QtCore.QSize(78, 0))
self.fontFooterHeightSpinBox.setMaximum(9999)
self.fontFooterHeightSpinBox.setObjectName(u'fontFooterHeightSpinBox')
self.locationFooterLayout.setWidget(4, QtGui.QFormLayout.FieldRole,
self.fontFooterHeightSpinBox)
self.footerRightLayout.addWidget(self.locationFooterGroupBox)
spacerItem4 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.footerRightLayout.addItem(spacerItem4)
self.fontFooterLayout.addWidget(self.footerRightWidget)
self.themeTabWidget.addTab(self.fontFooterTab, u'')
self.otherOptionsTab = QtGui.QWidget()
self.otherOptionsTab.setObjectName(u'otherOptionsTab')
self.otherOptionsLayout = QtGui.QHBoxLayout(self.otherOptionsTab)
self.otherOptionsLayout.setSpacing(8)
self.otherOptionsLayout.setMargin(8)
self.otherOptionsLayout.setObjectName(u'otherOptionsLayout')
self.optionsLeftWidget = QtGui.QWidget(self.otherOptionsTab)
self.optionsLeftWidget.setObjectName(u'optionsLeftWidget')
self.optionsLeftLayout = QtGui.QVBoxLayout(self.optionsLeftWidget)
self.optionsLeftLayout.setSpacing(8)
self.optionsLeftLayout.setMargin(0)
self.optionsLeftLayout.setObjectName(u'optionsLeftLayout')
self.outlineGroupBox = QtGui.QGroupBox(self.optionsLeftWidget)
self.outlineGroupBox.setObjectName(u'outlineGroupBox')
self.verticalLayout = QtGui.QVBoxLayout(self.outlineGroupBox)
self.verticalLayout.setSpacing(8)
self.verticalLayout.setMargin(8)
self.verticalLayout.setObjectName(u'verticalLayout')
self.outlineWidget = QtGui.QWidget(self.outlineGroupBox)
self.outlineWidget.setObjectName(u'outlineWidget')
self.outlineLayout = QtGui.QFormLayout(self.outlineWidget)
self.outlineLayout.setMargin(0)
self.outlineLayout.setSpacing(8)
self.outlineLayout.setObjectName(u'outlineLayout')
self.outlineCheckBox = QtGui.QCheckBox(self.outlineWidget)
self.outlineCheckBox.setObjectName(u'outlineCheckBox')
self.outlineLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.outlineCheckBox)
self.outlineSpinBox = QtGui.QSpinBox(self.outlineWidget)
self.outlineSpinBox.setObjectName(u'outlineSpinBox')
self.outlineSpinBox.setMaximum(10)
self.outlineLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.outlineSpinBox)
self.outlineSpinBoxLabel = QtGui.QLabel(self.outlineWidget)
self.outlineSpinBoxLabel.setObjectName(u'outlineSpinBoxLabel')
self.outlineLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.outlineSpinBoxLabel)
self.outlineColorLabel = QtGui.QLabel(self.outlineWidget)
self.outlineColorLabel.setObjectName(u'outlineColorLabel')
self.outlineLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.outlineColorLabel)
self.outlineColorPushButton = QtGui.QPushButton(self.outlineWidget)
self.outlineColorPushButton.setObjectName(u'outlineColorPushButton')
self.outlineLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.outlineColorPushButton)
self.outlineEnabledLabel = QtGui.QLabel(self.outlineWidget)
self.outlineEnabledLabel.setObjectName(u'outlineEnabledLabel')
self.outlineLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.outlineEnabledLabel)
self.verticalLayout.addWidget(self.outlineWidget)
self.optionsLeftLayout.addWidget(self.outlineGroupBox)
self.shadowGroupBox = QtGui.QGroupBox(self.optionsLeftWidget)
self.shadowGroupBox.setObjectName(u'shadowGroupBox')
self.verticalLayout = QtGui.QVBoxLayout(self.shadowGroupBox)
self.verticalLayout.setSpacing(8)
self.verticalLayout.setMargin(8)
self.verticalLayout.setObjectName(u'verticalLayout')
self.shadowWidget = QtGui.QWidget(self.shadowGroupBox)
self.shadowWidget.setObjectName(u'shadowWidget')
self.shadowLayout = QtGui.QFormLayout(self.shadowWidget)
self.shadowLayout.setMargin(0)
self.shadowLayout.setSpacing(8)
self.shadowLayout.setObjectName(u'shadowLayout')
self.shadowCheckBox = QtGui.QCheckBox(self.shadowWidget)
self.shadowCheckBox.setObjectName(u'shadowCheckBox')
self.shadowLayout.setWidget(0, QtGui.QFormLayout.FieldRole,
self.shadowCheckBox)
self.shadowSpinBox = QtGui.QSpinBox(self.outlineWidget)
self.shadowSpinBox.setObjectName(u'shadowSpinBox')
self.shadowSpinBox.setMaximum(10)
self.shadowLayout.setWidget(1, QtGui.QFormLayout.FieldRole,
self.shadowSpinBox)
self.shadowSpinBoxLabel = QtGui.QLabel(self.outlineWidget)
self.shadowSpinBoxLabel.setObjectName(u'shadowSpinBoxLabel')
self.shadowLayout.setWidget(1, QtGui.QFormLayout.LabelRole,
self.shadowSpinBoxLabel)
self.shadowColorLabel = QtGui.QLabel(self.shadowWidget)
self.shadowColorLabel.setObjectName(u'shadowColorLabel')
self.shadowLayout.setWidget(2, QtGui.QFormLayout.LabelRole,
self.shadowColorLabel)
self.shadowColorPushButton = QtGui.QPushButton(self.shadowWidget)
self.shadowColorPushButton.setObjectName(u'shadowColorPushButton')
self.shadowLayout.setWidget(2, QtGui.QFormLayout.FieldRole,
self.shadowColorPushButton)
self.shadowEnabledLabel = QtGui.QLabel(self.shadowWidget)
self.shadowEnabledLabel.setObjectName(u'shadowEnabledLabel')
self.shadowLayout.setWidget(0, QtGui.QFormLayout.LabelRole,
self.shadowEnabledLabel)
self.verticalLayout.addWidget(self.shadowWidget)
self.optionsLeftLayout.addWidget(self.shadowGroupBox)
spacerItem5 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.optionsLeftLayout.addItem(spacerItem5)
self.otherOptionsLayout.addWidget(self.optionsLeftWidget)
self.optionsRightWidget = QtGui.QWidget(self.otherOptionsTab)
self.optionsRightWidget.setObjectName(u'optionsRightWidget')
self.optionsRightLayout = QtGui.QVBoxLayout(self.optionsRightWidget)
self.optionsRightLayout.setSpacing(8)
self.optionsRightLayout.setMargin(0)
self.optionsRightLayout.setObjectName(u'optionsRightLayout')
self.alignmentGroupBox = QtGui.QGroupBox(self.optionsRightWidget)
self.alignmentGroupBox.setObjectName(u'alignmentGroupBox')
self.gridLayout4 = QtGui.QGridLayout(self.alignmentGroupBox)
self.gridLayout4.setObjectName(u'gridLayout4')
self.horizontalLabel = QtGui.QLabel(self.alignmentGroupBox)
self.horizontalLabel.setObjectName(u'horizontalLabel')
self.gridLayout4.addWidget(self.horizontalLabel, 0, 0, 1, 1)
self.horizontalComboBox = QtGui.QComboBox(self.alignmentGroupBox)
self.horizontalComboBox.setObjectName(u'horizontalComboBox')
self.horizontalComboBox.addItem(QtCore.QString())
self.horizontalComboBox.addItem(QtCore.QString())
self.horizontalComboBox.addItem(QtCore.QString())
self.gridLayout4.addWidget(self.horizontalComboBox, 0, 1, 1, 1)
self.verticalLabel = QtGui.QLabel(self.alignmentGroupBox)
self.verticalLabel.setObjectName(u'verticalLabel')
self.gridLayout4.addWidget(self.verticalLabel, 1, 0, 1, 1)
self.verticalComboBox = QtGui.QComboBox(self.alignmentGroupBox)
self.verticalComboBox.setObjectName(u'verticalComboBox')
self.verticalComboBox.addItem(QtCore.QString())
self.verticalComboBox.addItem(QtCore.QString())
self.verticalComboBox.addItem(QtCore.QString())
self.gridLayout4.addWidget(self.verticalComboBox, 1, 1, 1, 1)
self.optionsRightLayout.addWidget(self.alignmentGroupBox)
self.transitionGroupBox = QtGui.QGroupBox(self.optionsRightWidget)
self.transitionGroupBox.setObjectName(u'transitionGroupBox')
self.gridLayout5 = QtGui.QGridLayout(self.transitionGroupBox)
self.gridLayout5.setObjectName(u'gridLayout5')
self.slideTransitionCheckBoxLabel = QtGui.QLabel(
self.transitionGroupBox)
self.slideTransitionCheckBoxLabel.setObjectName(
u'slideTransitionCheckBoxLabel')
self.gridLayout5.addWidget(
self.slideTransitionCheckBoxLabel, 0, 0, 1, 1)
self.slideTransitionCheckBox = QtGui.QCheckBox(self.alignmentGroupBox)
self.slideTransitionCheckBox.setTristate(False)
self.gridLayout5.addWidget(self.slideTransitionCheckBox, 0, 1, 1, 1)
self.optionsRightLayout.addWidget(self.transitionGroupBox)
spacerItem6 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.optionsRightLayout.addItem(spacerItem6)
self.otherOptionsLayout.addWidget(self.optionsRightWidget)
self.themeTabWidget.addTab(self.otherOptionsTab, u'')
self.contentLayout.addWidget(self.themeTabWidget)
self.amendThemeLayout.addWidget(self.contentWidget)
self.previewGroupBox = QtGui.QGroupBox(amendThemeDialog)
self.previewGroupBox.setObjectName(u'previewGroupBox')
self.themePreviewLayout = QtGui.QHBoxLayout(self.previewGroupBox)
self.themePreviewLayout.setSpacing(8)
self.themePreviewLayout.setMargin(8)
self.themePreviewLayout.setObjectName(u'themePreviewLayout')
spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
self.themePreviewLayout.addItem(spacerItem7)
self.themePreview = QtGui.QLabel(self.previewGroupBox)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(
self.themePreview.sizePolicy().hasHeightForWidth())
self.themePreview.setSizePolicy(sizePolicy)
self.themePreview.setMaximumSize(QtCore.QSize(300, 225))
self.themePreview.setFrameShape(QtGui.QFrame.WinPanel)
self.themePreview.setFrameShadow(QtGui.QFrame.Sunken)
self.themePreview.setLineWidth(1)
self.themePreview.setScaledContents(True)
self.themePreview.setObjectName(u'themePreview')
self.themePreviewLayout.addWidget(self.themePreview)
spacerItem8 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
self.themePreviewLayout.addItem(spacerItem8)
self.amendThemeLayout.addWidget(self.previewGroupBox)
self.themeButtonBox = QtGui.QDialogButtonBox(amendThemeDialog)
self.themeButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
QtGui.QDialogButtonBox.Ok)
self.themeButtonBox.setObjectName(u'themeButtonBox')
self.amendThemeLayout.addWidget(self.themeButtonBox)
self.retranslateUi(amendThemeDialog)
self.themeTabWidget.setCurrentIndex(0)
QtCore.QObject.connect(self.themeButtonBox,
QtCore.SIGNAL(u'accepted()'), amendThemeDialog.accept)
QtCore.QObject.connect(self.themeButtonBox,
QtCore.SIGNAL(u'rejected()'), amendThemeDialog.reject)
QtCore.QMetaObject.connectSlotsByName(amendThemeDialog)
def retranslateUi(self, amendThemeDialog):
amendThemeDialog.setWindowTitle(
translate('OpenLP.AmendThemeForm', 'Theme Maintenance'))
self.themeNameLabel.setText(
translate('OpenLP.AmendThemeForm', 'Theme &name:'))
self.backgroundTypeLabel.setText(
translate('OpenLP.AmendThemeForm', 'Type:'))
self.backgroundTypeComboBox.setItemText(0,
translate('OpenLP.AmendThemeForm', 'Solid Color'))
self.backgroundTypeComboBox.setItemText(1,
translate('OpenLP.AmendThemeForm', 'Gradient'))
self.backgroundTypeComboBox.setItemText(2,
translate('OpenLP.AmendThemeForm', 'Image'))
self.color1Label.setText(u'<color1>:')
self.color2Label.setText(u'<color2>:')
self.imageLabel.setText(
translate('OpenLP.AmendThemeForm', 'Image:'))
self.gradientLabel.setText(
translate('OpenLP.AmendThemeForm', 'Gradient:'))
self.gradientComboBox.setItemText(0,
translate('OpenLP.AmendThemeForm', 'Horizontal'))
self.gradientComboBox.setItemText(1,
translate('OpenLP.AmendThemeForm', 'Vertical'))
self.gradientComboBox.setItemText(2,
translate('OpenLP.AmendThemeForm', 'Circular'))
self.themeTabWidget.setTabText(
self.themeTabWidget.indexOf(self.backgroundTab),
translate('OpenLP.AmendThemeForm', '&Background'))
self.fontMainGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Main Font'))
self.fontMainlabel.setText(
translate('OpenLP.AmendThemeForm', 'Font:'))
self.fontMainColorLabel.setText(
translate('OpenLP.AmendThemeForm', 'Color:'))
self.fontMainSize.setText(
translate('OpenLP.AmendThemeForm', 'Size:'))
self.fontMainSizeSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'pt'))
self.fontMainWrapLineAdjustmentLabel.setText(
translate('OpenLP.AmendThemeForm', 'Adjust line spacing:'))
self.fontMainWeightComboBox.setItemText(0,
translate('OpenLP.AmendThemeForm', 'Normal'))
self.fontMainWeightComboBox.setItemText(1,
translate('OpenLP.AmendThemeForm', 'Bold'))
self.fontMainWeightComboBox.setItemText(2,
translate('OpenLP.AmendThemeForm', 'Italics'))
self.fontMainWeightComboBox.setItemText(3,
translate('OpenLP.AmendThemeForm', 'Bold/Italics'))
self.fontMainWeightLabel.setText(
translate('OpenLP.AmendThemeForm', 'Style:'))
self.mainLocationGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Display Location'))
self.defaultLocationLabel.setText(
translate('OpenLP.AmendThemeForm', 'Use default location'))
self.fontMainXLabel.setText(
translate('OpenLP.AmendThemeForm', 'X position:'))
self.fontMainYLabel.setText(
translate('OpenLP.AmendThemeForm', 'Y position:'))
self.fontMainWidthLabel.setText(
translate('OpenLP.AmendThemeForm', 'Width:'))
self.fontMainHeightLabel.setText(
translate('OpenLP.AmendThemeForm', 'Height:'))
self.fontMainXSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.fontMainYSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.fontMainWidthSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.fontMainHeightSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.themeTabWidget.setTabText(
self.themeTabWidget.indexOf(self.fontMainTab),
translate('OpenLP.AmendThemeForm', '&Main Font'))
self.footerFontGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Footer Font'))
self.fontFooterLabel.setText(
translate('OpenLP.AmendThemeForm', 'Font:'))
self.fontFooterColorLabel.setText(
translate('OpenLP.AmendThemeForm', 'Color:'))
self.fontFooterSizeLabel.setText(
translate('OpenLP.AmendThemeForm', 'Size:'))
self.fontFooterSizeSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'pt'))
self.fontFooterWeightComboBox.setItemText(0,
translate('OpenLP.AmendThemeForm', 'Normal'))
self.fontFooterWeightComboBox.setItemText(1,
translate('OpenLP.AmendThemeForm', 'Bold'))
self.fontFooterWeightComboBox.setItemText(2,
translate('OpenLP.AmendThemeForm', 'Italics'))
self.fontFooterWeightComboBox.setItemText(3,
translate('OpenLP.AmendThemeForm', 'Bold/Italics'))
self.fontFooterWeightLabel.setText(
translate('OpenLP.AmendThemeForm', 'Style:'))
self.locationFooterGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Display Location'))
self.fontFooterDefaultLabel.setText(
translate('OpenLP.AmendThemeForm', 'Use default location'))
self.fontFooterXLabel.setText(
translate('OpenLP.AmendThemeForm', 'X position:'))
self.fontFooterYLabel.setText(
translate('OpenLP.AmendThemeForm', 'Y position:'))
self.fontFooterWidthLabel.setText(
translate('OpenLP.AmendThemeForm', 'Width:'))
self.fontFooterHeightLabel.setText(
translate('OpenLP.AmendThemeForm', 'Height:'))
self.fontFooterXSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.fontFooterYSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.fontFooterWidthSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.fontFooterHeightSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.themeTabWidget.setTabText(
self.themeTabWidget.indexOf(self.fontFooterTab),
translate('OpenLP.AmendThemeForm', '&Footer Font'))
self.outlineGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Outline'))
self.outlineSpinBoxLabel.setText(
translate('OpenLP.AmendThemeForm', 'Outline size:'))
self.outlineSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.outlineColorLabel.setText(
translate('OpenLP.AmendThemeForm', 'Outline color:'))
self.outlineEnabledLabel.setText(
translate('OpenLP.AmendThemeForm', 'Show outline:'))
self.shadowGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Shadow'))
self.shadowSpinBoxLabel.setText(
translate('OpenLP.AmendThemeForm', 'Shadow size:'))
self.shadowSpinBox.setSuffix(
translate('OpenLP.AmendThemeForm', 'px'))
self.shadowColorLabel.setText(
translate('OpenLP.AmendThemeForm', 'Shadow color:'))
self.shadowEnabledLabel.setText(
translate('OpenLP.AmendThemeForm', 'Show shadow:'))
self.alignmentGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Alignment'))
self.horizontalLabel.setText(
translate('OpenLP.AmendThemeForm', 'Horizontal align:'))
self.horizontalComboBox.setItemText(0,
translate('OpenLP.AmendThemeForm', 'Left'))
self.horizontalComboBox.setItemText(1,
translate('OpenLP.AmendThemeForm', 'Right'))
self.horizontalComboBox.setItemText(2,
translate('OpenLP.AmendThemeForm', 'Center'))
self.verticalLabel.setText(
translate('OpenLP.AmendThemeForm', 'Vertical align:'))
self.verticalComboBox.setItemText(0,
translate('OpenLP.AmendThemeForm', 'Top'))
self.verticalComboBox.setItemText(1,
translate('OpenLP.AmendThemeForm', 'Middle'))
self.verticalComboBox.setItemText(2,
translate('OpenLP.AmendThemeForm', 'Bottom'))
self.transitionGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Slide Transition'))
self.slideTransitionCheckBoxLabel.setText(
translate('OpenLP.AmendThemeForm', 'Transition active'))
self.themeTabWidget.setTabText(
self.themeTabWidget.indexOf(self.otherOptionsTab),
translate('OpenLP.AmendThemeForm', '&Other Options'))
self.previewGroupBox.setTitle(
translate('OpenLP.AmendThemeForm', 'Preview'))

View File

@ -1,717 +0,0 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
import os.path
from PyQt4 import QtCore, QtGui
from openlp.core.lib import ThemeXML, translate
from openlp.core.utils import get_images_filter
from amendthemedialog import Ui_AmendThemeDialog
log = logging.getLogger(u'AmendThemeForm')
class AmendThemeForm(QtGui.QDialog, Ui_AmendThemeDialog):
"""
The :class:`AmendThemeForm` class provides the user interface to set up
new and edit existing themes.
"""
def __init__(self, parent):
"""
Initialise the theme editor user interface
"""
QtGui.QDialog.__init__(self, parent)
self.thememanager = parent
self.path = None
self.theme = ThemeXML()
self.setupUi(self)
# Buttons
QtCore.QObject.connect(self.color1PushButton,
QtCore.SIGNAL(u'pressed()'), self.onColor1PushButtonClicked)
QtCore.QObject.connect(self.color2PushButton,
QtCore.SIGNAL(u'pressed()'), self.onColor2PushButtonClicked)
QtCore.QObject.connect(self.fontMainColorPushButton,
QtCore.SIGNAL(u'pressed()'), self.onFontMainColorPushButtonClicked)
QtCore.QObject.connect(self.fontFooterColorPushButton,
QtCore.SIGNAL(u'pressed()'),
self.onFontFooterColorPushButtonClicked)
QtCore.QObject.connect(self.outlineColorPushButton,
QtCore.SIGNAL(u'pressed()'), self.onOutlineColorPushButtonClicked)
QtCore.QObject.connect(self.shadowColorPushButton,
QtCore.SIGNAL(u'pressed()'), self.onShadowColorPushButtonClicked)
QtCore.QObject.connect(self.imageToolButton,
QtCore.SIGNAL(u'clicked()'), self.onImageToolButtonClicked)
# Combo boxes
QtCore.QObject.connect(self.backgroundTypeComboBox,
QtCore.SIGNAL(u'activated(int)'),
self.onBackgroundTypeComboBoxSelected)
QtCore.QObject.connect(self.gradientComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onGradientComboBoxSelected)
QtCore.QObject.connect(self.fontMainComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onFontMainComboBoxSelected)
QtCore.QObject.connect(self.fontMainWeightComboBox,
QtCore.SIGNAL(u'activated(int)'),
self.onFontMainWeightComboBoxSelected)
QtCore.QObject.connect(self.fontFooterComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onFontFooterComboBoxSelected)
QtCore.QObject.connect(self.fontFooterWeightComboBox,
QtCore.SIGNAL(u'activated(int)'),
self.onFontFooterWeightComboBoxSelected)
QtCore.QObject.connect(self.horizontalComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onHorizontalComboBoxSelected)
QtCore.QObject.connect(self.verticalComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onVerticalComboBoxSelected)
# Spin boxes
QtCore.QObject.connect(self.fontMainSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontMainSizeSpinBoxChanged)
QtCore.QObject.connect(self.fontFooterSizeSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterSizeSpinBoxChanged)
QtCore.QObject.connect(self.fontMainXSpinBox,
QtCore.SIGNAL(u'editingFinished()'), self.onFontMainXSpinBoxChanged)
QtCore.QObject.connect(self.fontMainYSpinBox,
QtCore.SIGNAL(u'editingFinished()'), self.onFontMainYSpinBoxChanged)
QtCore.QObject.connect(self.fontMainWidthSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontMainWidthSpinBoxChanged)
QtCore.QObject.connect(self.fontMainHeightSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontMainHeightSpinBoxChanged)
QtCore.QObject.connect(self.fontMainLineAdjustmentSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontMainLineAdjustmentSpinBoxChanged)
QtCore.QObject.connect(self.fontFooterXSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterXSpinBoxChanged)
QtCore.QObject.connect(self.fontFooterYSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterYSpinBoxChanged)
QtCore.QObject.connect(self.fontFooterWidthSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterWidthSpinBoxChanged)
QtCore.QObject.connect(self.fontFooterHeightSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onFontFooterHeightSpinBoxChanged)
QtCore.QObject.connect(self.shadowSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onShadowSpinBoxChanged)
QtCore.QObject.connect(self.outlineSpinBox,
QtCore.SIGNAL(u'editingFinished()'),
self.onOutlineSpinBoxChanged)
# CheckBoxes
QtCore.QObject.connect(self.fontMainDefaultCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onFontMainDefaultCheckBoxChanged)
QtCore.QObject.connect(self.fontFooterDefaultCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onFontFooterDefaultCheckBoxChanged)
QtCore.QObject.connect(self.outlineCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onOutlineCheckBoxChanged)
QtCore.QObject.connect(self.shadowCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'), self.onShadowCheckBoxChanged)
QtCore.QObject.connect(self.slideTransitionCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onSlideTransitionCheckBoxChanged)
def accept(self):
new_theme = ThemeXML()
theme_name = unicode(self.themeNameEdit.text())
new_theme.new_document(theme_name)
save_from = None
save_to = None
if self.theme.background_type == u'solid':
new_theme.add_background_solid(
unicode(self.theme.background_color))
elif self.theme.background_type == u'gradient':
new_theme.add_background_gradient(
unicode(self.theme.background_start_color),
unicode(self.theme.background_end_color),
self.theme.background_direction)
else:
filename = \
os.path.split(unicode(self.theme.background_filename))[1]
new_theme.add_background_image(filename)
save_to = os.path.join(self.path, theme_name, filename)
save_from = self.theme.background_filename
new_theme.add_font(unicode(self.theme.font_main_name),
unicode(self.theme.font_main_color),
unicode(self.theme.font_main_proportion),
unicode(self.theme.font_main_override), u'main',
unicode(self.theme.font_main_weight),
unicode(self.theme.font_main_italics),
unicode(self.theme.font_main_line_adjustment),
unicode(self.theme.font_main_x),
unicode(self.theme.font_main_y),
unicode(self.theme.font_main_width),
unicode(self.theme.font_main_height))
new_theme.add_font(unicode(self.theme.font_footer_name),
unicode(self.theme.font_footer_color),
unicode(self.theme.font_footer_proportion),
unicode(self.theme.font_footer_override), u'footer',
unicode(self.theme.font_footer_weight),
unicode(self.theme.font_footer_italics),
0, # line adjustment
unicode(self.theme.font_footer_x),
unicode(self.theme.font_footer_y),
unicode(self.theme.font_footer_width),
unicode(self.theme.font_footer_height))
new_theme.add_display(unicode(self.theme.display_shadow),
unicode(self.theme.display_shadow_color),
unicode(self.theme.display_outline),
unicode(self.theme.display_outline_color),
unicode(self.theme.display_horizontal_align),
unicode(self.theme.display_vertical_align),
unicode(self.theme.display_wrap_style),
unicode(self.theme.display_slide_transition),
unicode(self.theme.display_shadow_size),
unicode(self.theme.display_outline_size))
theme = new_theme.extract_xml()
pretty_theme = new_theme.extract_formatted_xml()
if self.thememanager.saveTheme(theme_name, theme, pretty_theme,
save_from, save_to) is not False:
return QtGui.QDialog.accept(self)
def loadTheme(self, theme):
log.debug(u'LoadTheme %s', theme)
self.theme = theme
# Stop the initial screen setup generating 1 preview per field!
self.allowPreview = False
self.paintUi(self.theme)
self.allowPreview = True
self.previewTheme()
def onImageToolButtonClicked(self):
images_filter = get_images_filter()
images_filter = '%s;;%s (*.*) (*)' % (images_filter,
translate('OpenLP.AmendThemeForm', 'All Files'))
filename = QtGui.QFileDialog.getOpenFileName(self,
translate('OpenLP.AmendThemeForm', 'Select Image'), u'',
images_filter)
if filename:
self.imageLineEdit.setText(filename)
self.theme.background_filename = filename
self.previewTheme()
#
# Main Font Tab
#
def onFontMainComboBoxSelected(self):
self.theme.font_main_name = self.fontMainComboBox.currentFont().family()
self.previewTheme()
def onFontMainWeightComboBoxSelected(self, value):
if value == 0:
self.theme.font_main_weight = u'Normal'
self.theme.font_main_italics = False
elif value == 1:
self.theme.font_main_weight = u'Bold'
self.theme.font_main_italics = False
elif value == 2:
self.theme.font_main_weight = u'Normal'
self.theme.font_main_italics = True
else:
self.theme.font_main_weight = u'Bold'
self.theme.font_main_italics = True
self.previewTheme()
def onFontMainColorPushButtonClicked(self):
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.font_main_color), self)
if new_color.isValid():
self.theme.font_main_color = new_color.name()
self.fontMainColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(self.theme.font_main_color))
self.previewTheme()
def onFontMainSizeSpinBoxChanged(self):
if self.theme.font_main_proportion != self.fontMainSizeSpinBox.value():
self.theme.font_main_proportion = self.fontMainSizeSpinBox.value()
self.previewTheme()
def onFontMainDefaultCheckBoxChanged(self, value):
if value == 2: # checked
self.theme.font_main_override = False
else:
self.theme.font_main_override = True
if not self.theme.font_main_x and not self.theme.font_main_y and \
not self.theme.font_main_width and not self.theme.font_main_height:
self.theme.font_main_x = u'10'
self.theme.font_main_y = u'10'
self.theme.font_main_width = u'1024'
self.theme.font_main_height = u'730'
self.fontMainXSpinBox.setValue(self.theme.font_main_x)
self.fontMainYSpinBox.setValue(self.theme.font_main_y)
self.fontMainWidthSpinBox.setValue(self.theme.font_main_width)
self.fontMainHeightSpinBox.setValue(self.theme.font_main_height)
self.fontMainLineAdjustmentSpinBox.setValue(
self.theme.font_main_line_adjustment)
self.stateChanging(self.theme)
self.previewTheme()
def onFontMainXSpinBoxChanged(self):
if self.theme.font_main_x != self.fontMainXSpinBox.value():
self.theme.font_main_x = self.fontMainXSpinBox.value()
self.previewTheme()
def onFontMainYSpinBoxChanged(self):
if self.theme.font_main_y != self.fontMainYSpinBox.value():
self.theme.font_main_y = self.fontMainYSpinBox.value()
self.previewTheme()
def onFontMainWidthSpinBoxChanged(self):
if self.theme.font_main_width != self.fontMainWidthSpinBox.value():
self.theme.font_main_width = self.fontMainWidthSpinBox.value()
self.previewTheme()
def onFontMainLineAdjustmentSpinBoxChanged(self):
if self.theme.font_main_line_adjustment != \
self.fontMainLineAdjustmentSpinBox.value():
self.theme.font_main_line_adjustment = \
self.fontMainLineAdjustmentSpinBox.value()
self.previewTheme()
def onFontMainHeightSpinBoxChanged(self):
if self.theme.font_main_height != self.fontMainHeightSpinBox.value():
self.theme.font_main_height = self.fontMainHeightSpinBox.value()
self.previewTheme()
#
# Footer Font Tab
#
def onFontFooterComboBoxSelected(self):
self.theme.font_footer_name = \
self.fontFooterComboBox.currentFont().family()
self.previewTheme()
def onFontFooterWeightComboBoxSelected(self, value):
if value == 0:
self.theme.font_footer_weight = u'Normal'
self.theme.font_footer_italics = False
elif value == 1:
self.theme.font_footer_weight = u'Bold'
self.theme.font_footer_italics = False
elif value == 2:
self.theme.font_footer_weight = u'Normal'
self.theme.font_footer_italics = True
else:
self.theme.font_footer_weight = u'Bold'
self.theme.font_footer_italics = True
self.previewTheme()
def onFontFooterColorPushButtonClicked(self):
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.font_footer_color), self)
if new_color.isValid():
self.theme.font_footer_color = new_color.name()
self.fontFooterColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(self.theme.font_footer_color))
self.previewTheme()
def onFontFooterSizeSpinBoxChanged(self):
if self.theme.font_footer_proportion != \
self.fontFooterSizeSpinBox.value():
self.theme.font_footer_proportion = \
self.fontFooterSizeSpinBox.value()
self.previewTheme()
def onFontFooterDefaultCheckBoxChanged(self, value):
if value == 2: # checked
self.theme.font_footer_override = False
else:
self.theme.font_footer_override = True
if not self.theme.font_footer_x and not self.theme.font_footer_y and \
not self.theme.font_footer_width and \
not self.theme.font_footer_height:
self.theme.font_footer_x = u'10'
self.theme.font_footer_y = u'730'
self.theme.font_footer_width = u'1024'
self.theme.font_footer_height = u'38'
self.fontFooterXSpinBox.setValue(self.theme.font_footer_x)
self.fontFooterYSpinBox.setValue(self.theme.font_footer_y)
self.fontFooterWidthSpinBox.setValue(self.theme.font_footer_width)
self.fontFooterHeightSpinBox.setValue(
self.theme.font_footer_height)
self.stateChanging(self.theme)
self.previewTheme()
def onFontFooterXSpinBoxChanged(self):
if self.theme.font_footer_x != self.fontFooterXSpinBox.value():
self.theme.font_footer_x = self.fontFooterXSpinBox.value()
self.previewTheme()
def onFontFooterYSpinBoxChanged(self):
if self.theme.font_footer_y != self.fontFooterYSpinBox.value():
self.theme.font_footer_y = self.fontFooterYSpinBox.value()
self.previewTheme()
def onFontFooterWidthSpinBoxChanged(self):
if self.theme.font_footer_width != self.fontFooterWidthSpinBox.value():
self.theme.font_footer_width = self.fontFooterWidthSpinBox.value()
self.previewTheme()
def onFontFooterHeightSpinBoxChanged(self):
if self.theme.font_footer_height != \
self.fontFooterHeightSpinBox.value():
self.theme.font_footer_height = \
self.fontFooterHeightSpinBox.value()
self.previewTheme()
#
# Background Tab
#
def onGradientComboBoxSelected(self, currentIndex):
self.setBackground(self.backgroundTypeComboBox.currentIndex(),
currentIndex)
def onBackgroundTypeComboBoxSelected(self, currentIndex):
self.setBackground(currentIndex, self.gradientComboBox.currentIndex())
def setBackground(self, background, gradient):
if background == 0: # Solid
self.theme.background_type = u'solid'
if self.theme.background_color is None:
self.theme.background_color = u'#000000'
self.imageLineEdit.setText(u'')
elif background == 1: # Gradient
self.theme.background_type = u'gradient'
if gradient == 0: # Horizontal
self.theme.background_direction = u'horizontal'
elif gradient == 1: # vertical
self.theme.background_direction = u'vertical'
else:
self.theme.background_direction = u'circular'
if self.theme.background_start_color is None:
self.theme.background_start_color = u'#000000'
if self.theme.background_end_color is None:
self.theme.background_end_color = u'#ff0000'
self.imageLineEdit.setText(u'')
else:
self.theme.background_type = u'image'
self.stateChanging(self.theme)
self.previewTheme()
def onColor1PushButtonClicked(self):
if self.theme.background_type == u'solid':
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.background_color), self)
if new_color.isValid():
self.theme.background_color = new_color.name()
self.color1PushButton.setStyleSheet(u'background-color: %s' %
unicode(self.theme.background_color))
else:
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.background_start_color), self)
if new_color.isValid():
self.theme.background_start_color = new_color.name()
self.color1PushButton.setStyleSheet(u'background-color: %s' %
unicode(self.theme.background_start_color))
self.previewTheme()
def onColor2PushButtonClicked(self):
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.background_end_color), self)
if new_color.isValid():
self.theme.background_end_color = new_color.name()
self.color2PushButton.setStyleSheet(u'background-color: %s' %
unicode(self.theme.background_end_color))
self.previewTheme()
#
# Other Tab
#
def onOutlineCheckBoxChanged(self, value):
if value == 2: # checked
self.theme.display_outline = True
else:
self.theme.display_outline = False
self.stateChanging(self.theme)
self.previewTheme()
def onOutlineSpinBoxChanged(self):
if self.theme.display_outline_size != self.outlineSpinBox.value():
self.theme.display_outline_size = self.outlineSpinBox.value()
self.previewTheme()
def onShadowSpinBoxChanged(self):
if self.theme.display_shadow_size != self.shadowSpinBox.value():
self.theme.display_shadow_size = self.shadowSpinBox.value()
self.previewTheme()
def onOutlineColorPushButtonClicked(self):
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.display_outline_color), self)
if new_color.isValid():
self.theme.display_outline_color = new_color.name()
self.outlineColorPushButton.setStyleSheet(u'background-color: %s' %
unicode(self.theme.display_outline_color))
self.previewTheme()
def onShadowCheckBoxChanged(self, value):
if value == 2: # checked
self.theme.display_shadow = True
else:
self.theme.display_shadow = False
self.stateChanging(self.theme)
self.previewTheme()
def onSlideTransitionCheckBoxChanged(self, value):
if value == 2: # checked
self.theme.display_slide_transition = True
else:
self.theme.display_slide_transition = False
self.stateChanging(self.theme)
self.previewTheme()
def onShadowColorPushButtonClicked(self):
new_color = QtGui.QColorDialog.getColor(
QtGui.QColor(self.theme.display_shadow_color), self)
if new_color.isValid():
self.theme.display_shadow_color = new_color.name()
self.shadowColorPushButton.setStyleSheet(u'background-color: %s' %
unicode(self.theme.display_shadow_color))
self.previewTheme()
def onHorizontalComboBoxSelected(self, currentIndex):
self.theme.display_horizontal_align = currentIndex
self.stateChanging(self.theme)
self.previewTheme()
def onVerticalComboBoxSelected(self, currentIndex):
self.theme.display_vertical_align = currentIndex
self.stateChanging(self.theme)
self.previewTheme()
#
# Local Methods
#
def paintUi(self, theme):
self.stateChanging(theme)
self.themeNameEdit.setText(self.theme.theme_name)
# Background Tab
self.imageLineEdit.setText(u'')
if theme.background_type == u'solid':
self.backgroundTypeComboBox.setCurrentIndex(0)
elif theme.background_type == u'gradient':
self.backgroundTypeComboBox.setCurrentIndex(1)
else:
self.backgroundTypeComboBox.setCurrentIndex(2)
self.imageLineEdit.setText(self.theme.background_filename)
if self.theme.background_direction == u'horizontal':
self.gradientComboBox.setCurrentIndex(0)
elif self.theme.background_direction == u'vertical':
self.gradientComboBox.setCurrentIndex(1)
else:
self.gradientComboBox.setCurrentIndex(2)
# Font Main Tab
self.fontMainComboBox.setCurrentFont(
QtGui.QFont(self.theme.font_main_name))
self.fontMainSizeSpinBox.setValue(self.theme.font_main_proportion)
if not self.theme.font_main_italics and \
self.theme.font_main_weight == u'Normal':
self.fontMainWeightComboBox.setCurrentIndex(0)
elif not self.theme.font_main_italics and \
self.theme.font_main_weight == u'Bold':
self.fontMainWeightComboBox.setCurrentIndex(1)
elif self.theme.font_main_italics and \
self.theme.font_main_weight == u'Normal':
self.fontMainWeightComboBox.setCurrentIndex(2)
else:
self.fontMainWeightComboBox.setCurrentIndex(3)
self.fontMainXSpinBox.setValue(self.theme.font_main_x)
self.fontMainYSpinBox.setValue(self.theme.font_main_y)
self.fontMainWidthSpinBox.setValue(self.theme.font_main_width)
self.fontMainHeightSpinBox.setValue(self.theme.font_main_height)
# Font Footer Tab
self.fontFooterComboBox.setCurrentFont(
QtGui.QFont(self.theme.font_footer_name))
self.fontFooterSizeSpinBox.setValue(
self.theme.font_footer_proportion)
if not self.theme.font_footer_italics and \
self.theme.font_footer_weight == u'Normal':
self.fontFooterWeightComboBox.setCurrentIndex(0)
elif not self.theme.font_footer_italics and \
self.theme.font_footer_weight == u'Bold':
self.fontFooterWeightComboBox.setCurrentIndex(1)
elif self.theme.font_footer_italics and \
self.theme.font_footer_weight == u'Normal':
self.fontFooterWeightComboBox.setCurrentIndex(2)
else:
self.fontFooterWeightComboBox.setCurrentIndex(3)
self.fontFooterXSpinBox.setValue(self.theme.font_footer_x)
self.fontFooterYSpinBox.setValue(self.theme.font_footer_y)
self.fontFooterWidthSpinBox.setValue(self.theme.font_footer_width)
self.fontFooterHeightSpinBox.setValue(self.theme.font_footer_height)
self.fontMainColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(theme.font_main_color))
self.fontFooterColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(theme.font_footer_color))
if not self.theme.font_main_override:
self.fontMainDefaultCheckBox.setChecked(True)
else:
self.fontMainDefaultCheckBox.setChecked(False)
if not self.theme.font_footer_override:
self.fontFooterDefaultCheckBox.setChecked(True)
else:
self.fontFooterDefaultCheckBox.setChecked(False)
self.outlineColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(theme.display_outline_color))
self.shadowColorPushButton.setStyleSheet(
u'background-color: %s' % unicode(theme.display_shadow_color))
if self.theme.display_outline:
self.outlineCheckBox.setChecked(True)
self.outlineColorPushButton.setEnabled(True)
else:
self.outlineCheckBox.setChecked(False)
self.outlineColorPushButton.setEnabled(False)
self.outlineSpinBox.setValue(int(self.theme.display_outline_size))
if self.theme.display_shadow:
self.shadowCheckBox.setChecked(True)
self.shadowColorPushButton.setEnabled(True)
else:
self.shadowCheckBox.setChecked(False)
self.shadowColorPushButton.setEnabled(False)
self.shadowSpinBox.setValue(int(self.theme.display_shadow_size))
if self.theme.display_slide_transition:
self.slideTransitionCheckBox.setCheckState(QtCore.Qt.Checked)
else:
self.slideTransitionCheckBox.setCheckState(QtCore.Qt.Unchecked)
self.horizontalComboBox.setCurrentIndex(
self.theme.display_horizontal_align)
self.verticalComboBox.setCurrentIndex(self.theme.display_vertical_align)
def stateChanging(self, theme):
self.backgroundTypeComboBox.setVisible(True)
self.backgroundTypeLabel.setVisible(True)
if theme.background_type == u'solid':
self.color1PushButton.setStyleSheet(
u'background-color: %s' % unicode(theme.background_color))
self.color1Label.setText(
translate('OpenLP.AmendThemeForm', 'Color:'))
self.color1Label.setVisible(True)
self.color1PushButton.setVisible(True)
self.color2Label.setVisible(False)
self.color2PushButton.setVisible(False)
self.imageLabel.setVisible(False)
self.imageLineEdit.setVisible(False)
self.imageFilenameWidget.setVisible(False)
self.gradientLabel.setVisible(False)
self.gradientComboBox.setVisible(False)
elif theme.background_type == u'gradient':
self.color1PushButton.setStyleSheet(u'background-color: %s' \
% unicode(theme.background_start_color))
self.color2PushButton.setStyleSheet(u'background-color: %s' \
% unicode(theme.background_end_color))
self.color1Label.setText(
translate('OpenLP.AmendThemeForm', 'First color:'))
self.color2Label.setText(
translate('OpenLP.AmendThemeForm', 'Second color:'))
self.color1Label.setVisible(True)
self.color1PushButton.setVisible(True)
self.color2Label.setVisible(True)
self.color2PushButton.setVisible(True)
self.imageLabel.setVisible(False)
self.imageLineEdit.setVisible(False)
self.imageFilenameWidget.setVisible(False)
self.gradientLabel.setVisible(True)
self.gradientComboBox.setVisible(True)
else: # must be image
self.color1Label.setVisible(False)
self.color1PushButton.setVisible(False)
self.color2Label.setVisible(False)
self.color2PushButton.setVisible(False)
self.imageLabel.setVisible(True)
self.imageLineEdit.setVisible(True)
self.imageFilenameWidget.setVisible(True)
self.gradientLabel.setVisible(False)
self.gradientComboBox.setVisible(False)
if not theme.font_main_override:
self.fontMainXSpinBox.setEnabled(False)
self.fontMainYSpinBox.setEnabled(False)
self.fontMainWidthSpinBox.setEnabled(False)
self.fontMainHeightSpinBox.setEnabled(False)
else:
self.fontMainXSpinBox.setEnabled(True)
self.fontMainYSpinBox.setEnabled(True)
self.fontMainWidthSpinBox.setEnabled(True)
self.fontMainHeightSpinBox.setEnabled(True)
if not theme.font_footer_override:
self.fontFooterXSpinBox.setEnabled(False)
self.fontFooterYSpinBox.setEnabled(False)
self.fontFooterWidthSpinBox.setEnabled(False)
self.fontFooterHeightSpinBox.setEnabled(False)
else:
self.fontFooterXSpinBox.setEnabled(True)
self.fontFooterYSpinBox.setEnabled(True)
self.fontFooterWidthSpinBox.setEnabled(True)
self.fontFooterHeightSpinBox.setEnabled(True)
if self.theme.display_outline:
self.outlineColorPushButton.setEnabled(True)
else:
self.outlineColorPushButton.setEnabled(False)
if self.theme.display_shadow:
self.shadowColorPushButton.setEnabled(True)
else:
self.shadowColorPushButton.setEnabled(False)
def previewTheme(self):
if self.allowPreview:
#calculate main number of rows
metrics = self._getThemeMetrics()
line_height = metrics.height() \
+ int(self.theme.font_main_line_adjustment)
if self.theme.display_shadow:
line_height += int(self.theme.display_shadow_size)
if self.theme.display_outline:
# pixels top/bottom
line_height += 2 * int(self.theme.display_outline_size)
page_length = \
((self.fontMainHeightSpinBox.value()) / line_height )
log.debug(u'Page Length area height %s, metrics %s, lines %s' %
(self.fontMainHeightSpinBox.value(), metrics.height(),
page_length))
page_length_text = unicode(
translate('OpenLP.AmendThemeForm', 'Slide height is %s rows.'))
self.fontMainLinesPageLabel.setText(page_length_text % page_length)
frame = self.thememanager.generateImage(self.theme)
self.themePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
def _getThemeMetrics(self):
main_weight = 50
if self.theme.font_main_weight == u'Bold':
main_weight = 75
mainFont = QtGui.QFont(self.theme.font_main_name,
self.theme.font_main_proportion, # size
main_weight, # weight
self.theme.font_main_italics)# italic
mainFont.setPixelSize(self.theme.font_main_proportion)
metrics = QtGui.QFontMetrics(mainFont)
# Validate that the screen width is big enough to display the text
if self.theme.font_main_width < metrics.maxWidth() * 2 + 64:
self.theme.font_main_width = metrics.maxWidth() * 2 + 64
self.fontMainWidthSpinBox.setValue(self.theme.font_main_width)
return metrics

View File

@ -26,7 +26,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
from openlp.core.lib import translate, build_icon
class Ui_ExceptionDialog(object):
def setupUi(self, exceptionDialog):
@ -63,12 +63,27 @@ class Ui_ExceptionDialog(object):
self.exceptionButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Close)
self.exceptionButtonBox.setObjectName(u'exceptionButtonBox')
self.exceptionLayout.addWidget(self.exceptionButtonBox)
self.sendReportButton = QtGui.QPushButton(exceptionDialog)
self.sendReportButton.setIcon(build_icon(
u':/general/general_email.png'))
self.sendReportButton.setObjectName(u'sendReportButton')
self.exceptionButtonBox.addButton(self.sendReportButton,
QtGui.QDialogButtonBox.ActionRole)
self.saveReportButton = QtGui.QPushButton(exceptionDialog)
self.saveReportButton.setIcon(build_icon(u':/general/general_save.png'))
self.saveReportButton.setObjectName(u'saveReportButton')
self.exceptionButtonBox.addButton(self.saveReportButton,
QtGui.QDialogButtonBox.ActionRole)
self.retranslateUi(exceptionDialog)
QtCore.QObject.connect(self.exceptionButtonBox,
QtCore.SIGNAL(u'accepted()'), exceptionDialog.accept)
QtCore.QObject.connect(self.exceptionButtonBox,
QtCore.SIGNAL(u'rejected()'), exceptionDialog.reject)
QtCore.QObject.connect(self.sendReportButton,
QtCore.SIGNAL(u'pressed()'), self.onSendReportButtonPressed)
QtCore.QObject.connect(self.saveReportButton,
QtCore.SIGNAL(u'pressed()'), self.onSaveReportButtonPressed)
QtCore.QMetaObject.connectSlotsByName(exceptionDialog)
def retranslateUi(self, exceptionDialog):
@ -80,3 +95,7 @@ class Ui_ExceptionDialog(object):
'developers, so please e-mail it to bugs@openlp.org, along with a '
'detailed description of what you were doing when the problem '
'occurred.'))
self.sendReportButton.setText(translate('OpenLP.ExceptionDialog',
'Send E-Mail'))
self.saveReportButton.setText(translate('OpenLP.ExceptionDialog',
'Save to File'))

View File

@ -23,11 +23,44 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import re
import os
import platform
from PyQt4 import QtCore, QtGui
import sqlalchemy
import BeautifulSoup
from lxml import etree
from PyQt4 import Qt, QtCore, QtGui
try:
from PyQt4.phonon import Phonon
phonon_version = Phonon.phononVersion()
except ImportError:
phonon_version = u'-'
try:
import chardet
chardet_version = chardet.__version__
except ImportError:
chardet_version = u'-'
try:
import enchant
enchant_version = enchant.__version__
except ImportError:
enchant_version = u'-'
try:
import sqlite
sqlite_version = sqlite.version
except ImportError:
sqlite_version = u'-'
from openlp.core.lib import translate, SettingsManager
from openlp.core.lib.mailto import mailto
from exceptiondialog import Ui_ExceptionDialog
log = logging.getLogger(__name__)
class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
"""
The exception dialog
@ -35,3 +68,80 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
def __init__(self, parent):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
self.settingsSection = u'crashreport'
def _createReport(self):
openlp_version = self.parent().applicationVersion[u'full']
traceback = unicode(self.exceptionTextEdit.toPlainText())
system = unicode(translate('OpenLP.ExceptionForm',
'Platform: %s\n')) % platform.platform()
libraries = u'Python: %s\n' % platform.python_version() + \
u'Qt4: %s\n' % Qt.qVersion() + \
u'Phonon: %s\n' % phonon_version + \
u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \
u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \
u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \
u'lxml: %s\n' % etree.__version__ + \
u'Chardet: %s\n' % chardet_version + \
u'PyEnchant: %s\n' % enchant_version + \
u'PySQLite: %s\n' % sqlite_version
if platform.system() == u'Linux':
if os.environ.get(u'KDE_FULL_SESSION') == u'true':
system = system + u'Desktop: KDE SC\n'
elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'):
system = system + u'Desktop: GNOME\n'
return (openlp_version, traceback, system, libraries)
def onSaveReportButtonPressed(self):
"""
Saving exception log and system informations to a file.
"""
report = unicode(translate('OpenLP.ExceptionForm',
'**OpenLP Bug Report**\n'
'Version: %s\n\n'
'--- Exception Traceback ---\n%s\n'
'--- System information ---\n%s\n'
'--- Library Versions ---\n%s\n'))
filename = QtGui.QFileDialog.getSaveFileName(self,
translate('OpenLP.ExceptionForm', 'Save Crash Report'),
SettingsManager.get_last_dir(self.settingsSection),
translate('OpenLP.ExceptionForm',
'Text files (*.txt *.log *.text)'))
if filename:
filename = unicode(QtCore.QDir.toNativeSeparators(filename))
SettingsManager.set_last_dir(self.settingsSection, os.path.dirname(
filename))
report = report % self._createReport()
try:
file = open(filename, u'w')
try:
file.write(report)
except UnicodeError:
file.close()
file = open(filename, u'wb')
file.write(report.encode(u'utf-8'))
file.close()
except IOError:
log.exception(u'Failed to write crash report')
def onSendReportButtonPressed(self):
"""
Opening systems default email client and inserting exception log and
system informations.
"""
body = unicode(translate('OpenLP.ExceptionForm',
'*OpenLP Bug Report*\n'
'Version: %s\n\n'
'--- Please enter the report below this line. ---\n\n\n'
'--- Exception Traceback ---\n%s\n'
'--- System information ---\n%s\n'
'--- Library Versions ---\n%s\n'))
content = self._createReport()
for line in content[1].split(u'\n'):
if re.search(r'[/\\]openlp[/\\]', line):
source = re.sub(r'.*[/\\]openlp[/\\](.*)".*', r'\1', line)
if u':' in line:
exception = line.split(u'\n')[-1].split(u':')[0]
subject = u'Bug report: %s in %s' % (exception, source)
mailto(address=u'bugs@openlp.org', subject=subject,
body=body % content)

View File

@ -30,23 +30,24 @@ from openlp.core.lib import translate
class Ui_FileRenameDialog(object):
def setupUi(self, FileRenameDialog):
FileRenameDialog.setObjectName("FileRenameDialog")
FileRenameDialog.setObjectName(u'FileRenameDialog')
FileRenameDialog.resize(400, 87)
self.buttonBox = QtGui.QDialogButtonBox(FileRenameDialog)
self.buttonBox.setGeometry(QtCore.QRect(210, 50, 171, 25))
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel |
QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(u'buttonBox')
self.widget = QtGui.QWidget(FileRenameDialog)
self.widget.setGeometry(QtCore.QRect(10, 10, 381, 35))
self.widget.setObjectName("widget")
self.widget.setObjectName(u'widget')
self.horizontalLayout = QtGui.QHBoxLayout(self.widget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.FileRenameLabel = QtGui.QLabel(self.widget)
self.FileRenameLabel.setObjectName("FileRenameLabel")
self.horizontalLayout.addWidget(self.FileRenameLabel)
self.FileNameEdit = QtGui.QLineEdit(self.widget)
self.FileNameEdit.setObjectName("FileNameEdit")
self.horizontalLayout.addWidget(self.FileNameEdit)
self.horizontalLayout.setObjectName(u'horizontalLayout')
self.fileRenameLabel = QtGui.QLabel(self.widget)
self.fileRenameLabel.setObjectName(u'fileRenameLabel')
self.horizontalLayout.addWidget(self.fileRenameLabel)
self.fileNameEdit = QtGui.QLineEdit(self.widget)
self.fileNameEdit.setObjectName(u'fileNameEdit')
self.horizontalLayout.addWidget(self.fileNameEdit)
self.retranslateUi(FileRenameDialog)
QtCore.QMetaObject.connectSlotsByName(FileRenameDialog)
@ -54,6 +55,5 @@ class Ui_FileRenameDialog(object):
def retranslateUi(self, FileRenameDialog):
FileRenameDialog.setWindowTitle(translate('OpenLP.FileRenameForm',
'File Rename'))
self.FileRenameLabel.setText(translate('OpenLP.FileRenameForm',
self.fileRenameLabel.setText(translate('OpenLP.FileRenameForm',
'New File Name:'))

View File

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

View File

@ -23,11 +23,34 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import SettingsTab, Receiver, translate
log = logging.getLogger(__name__)
class ValidEdit(QtGui.QLineEdit):
"""
Only allow numeric characters to be edited
"""
def __init__(self, parent):
"""
Set up Override and Validator
"""
QtGui.QLineEdit.__init__(self, parent)
self.setValidator(QtGui.QIntValidator(0, 9999, self))
def validText(self):
"""
Only return Integers. Space is 0
"""
if self.text().isEmpty():
return QtCore.QString(u'0')
else:
return self.text()
class GeneralTab(SettingsTab):
"""
GeneralTab is the general settings tab in the settings dialog.
@ -240,7 +263,7 @@ class GeneralTab(SettingsTab):
self.customXLabel.setAlignment(QtCore.Qt.AlignCenter)
self.customXLabel.setObjectName(u'customXLabel')
self.customXLayout.addWidget(self.customXLabel)
self.customXValueEdit = QtGui.QLineEdit(self.displayGroupBox)
self.customXValueEdit = ValidEdit(self.displayGroupBox)
self.customXValueEdit.setObjectName(u'customXValueEdit')
self.customXLayout.addWidget(self.customXValueEdit)
self.customLayout.addLayout(self.customXLayout)
@ -252,7 +275,7 @@ class GeneralTab(SettingsTab):
self.customYLabel.setAlignment(QtCore.Qt.AlignCenter)
self.customYLabel.setObjectName(u'customYLabel')
self.customYLayout.addWidget(self.customYLabel)
self.customYValueEdit = QtGui.QLineEdit(self.displayGroupBox)
self.customYValueEdit = ValidEdit(self.displayGroupBox)
self.customYValueEdit.setObjectName(u'customYValueEdit')
self.customYLayout.addWidget(self.customYValueEdit)
self.customLayout.addLayout(self.customYLayout)
@ -265,7 +288,7 @@ class GeneralTab(SettingsTab):
self.customWidthLabel.setAlignment(QtCore.Qt.AlignCenter)
self.customWidthLabel.setObjectName(u'customWidthLabel')
self.customWidthLayout.addWidget(self.customWidthLabel)
self.customWidthValueEdit = QtGui.QLineEdit(self.displayGroupBox)
self.customWidthValueEdit = ValidEdit(self.displayGroupBox)
self.customWidthValueEdit.setObjectName(u'customWidthValueEdit')
self.customWidthLayout.addWidget(self.customWidthValueEdit)
self.customLayout.addLayout(self.customWidthLayout)
@ -277,7 +300,7 @@ class GeneralTab(SettingsTab):
self.customHeightLabel.setAlignment(QtCore.Qt.AlignCenter)
self.customHeightLabel.setObjectName(u'customHeightLabel')
self.customHeightLayout.addWidget(self.customHeightLabel)
self.customHeightValueEdit = QtGui.QLineEdit(self.displayGroupBox)
self.customHeightValueEdit = ValidEdit(self.displayGroupBox)
self.customHeightValueEdit.setObjectName(u'customHeightValueEdit')
self.customHeightLayout.addWidget(self.customHeightValueEdit)
self.customLayout.addLayout(self.customHeightLayout)
@ -465,10 +488,10 @@ class GeneralTab(SettingsTab):
# Reset screens after initial definition
if self.overrideChanged:
self.screens.override[u'size'] = QtCore.QRect(
int(self.customXValueEdit.text()),
int(self.customYValueEdit.text()),
int(self.customWidthValueEdit.text()),
int(self.customHeightValueEdit.text()))
int(self.customXValueEdit.validText()),
int(self.customYValueEdit.validText()),
int(self.customWidthValueEdit.validText()),
int(self.customHeightValueEdit.validText()))
if self.overrideCheckBox.isChecked():
self.screens.set_override_display()
else:

View File

@ -23,20 +23,21 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
"""
import logging
import os
from PyQt4 import QtCore, QtGui, QtWebKit
from PyQt4.phonon import Phonon
from openlp.core.lib import Receiver, resize_image, build_html, ServiceItem, \
image_to_byte
from openlp.core.lib import Receiver, build_html, ServiceItem, image_to_byte
from openlp.core.ui import HideMode
log = logging.getLogger(__name__)
#http://www.steveheffernan.com/html5-video-player/demo-video-player.html
#http://html5demos.com/two-videos
class DisplayWidget(QtGui.QGraphicsView):
"""
@ -90,6 +91,9 @@ class DisplayWidget(QtGui.QGraphicsView):
event.ignore()
class MainDisplay(DisplayWidget):
"""
This is the display screen.
"""
def __init__(self, parent, screens, live):
DisplayWidget.__init__(self, live, parent=None)
@ -97,7 +101,7 @@ class MainDisplay(DisplayWidget):
self.screens = screens
self.isLive = live
self.alertTab = None
self.hide_mode = None
self.hideMode = None
self.setWindowTitle(u'OpenLP Display')
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
self.setWindowFlags(QtCore.Qt.FramelessWindowHint |
@ -114,21 +118,23 @@ class MainDisplay(DisplayWidget):
"""
log.debug(u'Setup live = %s for %s ' % (self.isLive,
self.screens.monitor_number))
self.usePhonon = QtCore.QSettings().value(
u'media/use phonon', QtCore.QVariant(True)).toBool()
self.phononActive = False
self.screen = self.screens.current
self.setVisible(False)
self.setGeometry(self.screen[u'size'])
try:
self.webView = QtWebKit.QGraphicsWebView()
self.scene = QtGui.QGraphicsScene(self)
self.setScene(self.scene)
self.scene.addItem(self.webView)
self.webView.setGeometry(QtCore.QRectF(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height()))
except AttributeError:
# QGraphicsWebView a recent addition, so fall back to QWebView
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height())
self.videoWidget = Phonon.VideoWidget(self)
self.videoWidget.setVisible(False)
self.videoWidget.setGeometry(QtCore.QRect(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height()))
self.mediaObject = Phonon.MediaObject(self)
self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self.mediaObject)
Phonon.createPath(self.mediaObject, self.videoWidget)
Phonon.createPath(self.mediaObject, self.audio)
self.webView = QtWebKit.QWebView(self)
self.webView.setGeometry(0, 0,
self.screen[u'size'].width(), self.screen[u'size'].height())
self.page = self.webView.page()
self.frame = self.page.mainFrame()
QtCore.QObject.connect(self.webView,
@ -182,7 +188,7 @@ class MainDisplay(DisplayWidget):
`slide`
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.
while not self.loaded:
Receiver.send_message(u'openlp_process_events')
@ -197,9 +203,9 @@ class MainDisplay(DisplayWidget):
`slide`
The slide text to be displayed
"""
log.debug(u'alert')
log.debug(u'alert to display')
if self.height() != self.screen[u'size'].height() \
or not self.isVisible():
or not self.isVisible() or self.videoWidget.isVisible():
shrink = True
else:
shrink = False
@ -208,14 +214,26 @@ class MainDisplay(DisplayWidget):
u'top' if shrink else u'')
height = self.frame.evaluateJavaScript(js)
if shrink:
if text:
self.resize(self.width(), int(height.toString()))
self.setVisible(True)
if self.phononActive:
shrinkItem = self.webView
else:
self.setGeometry(self.screen[u'size'])
self.setVisible(False)
shrinkItem = self
if text:
shrinkItem.resize(self.width(), int(height.toString()))
shrinkItem.setVisible(True)
else:
shrinkItem.setVisible(False)
shrinkItem.resize(self.screen[u'size'].width(),
self.screen[u'size'].height())
def image(self, image):
def directImage(self, name, path):
"""
API for replacement backgrounds so Images are added directly to cache
"""
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
bytestream on route.
@ -223,25 +241,21 @@ class MainDisplay(DisplayWidget):
`Image`
The Image to be displayed can be QImage or QPixmap
"""
log.debug(u'image')
image = resize_image(image, self.screen[u'size'].width(),
self.screen[u'size'].height())
log.debug(u'image to display')
image = self.imageManager.get_image_bytes(name)
self.resetVideo()
self.displayImage(image)
# show screen
if self.isLive:
self.setVisible(True)
return self.preview()
def displayImage(self, image):
"""
Display an image, as is.
"""
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:
js = u'show_image("");'
self.frame.evaluateJavaScript(js)
@ -259,14 +273,24 @@ class MainDisplay(DisplayWidget):
Used after Video plugin has changed the background
"""
log.debug(u'resetVideo')
self.frame.evaluateJavaScript(u'show_video("close");')
if self.phononActive:
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.webView.setVisible(True)
self.videoWidget.setVisible(False)
self.phononActive = False
else:
self.frame.evaluateJavaScript(u'show_video("close");')
def videoPlay(self):
"""
Responds to the request to play a loaded video
"""
log.debug(u'videoPlay')
self.frame.evaluateJavaScript(u'show_video("play");')
if self.phononActive:
self.mediaObject.play()
else:
self.frame.evaluateJavaScript(u'show_video("play");')
# show screen
if self.isLive:
self.setVisible(True)
@ -276,32 +300,54 @@ class MainDisplay(DisplayWidget):
Responds to the request to pause a loaded video
"""
log.debug(u'videoPause')
self.frame.evaluateJavaScript(u'show_video("pause");')
if self.phononActive:
self.mediaObject.pause()
else:
self.frame.evaluateJavaScript(u'show_video("pause");')
def videoStop(self):
"""
Responds to the request to stop a loaded video
"""
log.debug(u'videoStop')
self.frame.evaluateJavaScript(u'show_video("stop");')
if self.phononActive:
self.mediaObject.stop()
else:
self.frame.evaluateJavaScript(u'show_video("stop");')
def videoVolume(self, volume):
"""
Changes the volume of a running video
"""
log.debug(u'videoVolume %d' % volume)
self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
str(float(volume)/float(10)))
vol = float(volume)/float(10)
if self.phononActive:
self.audio.setVolume(vol)
else:
self.frame.evaluateJavaScript(u'show_video(null, null, %s);' %
str(vol))
def video(self, videoPath, volume):
def video(self, videoPath, volume, isBackground=False):
"""
Loads and starts a video to run with the option of sound
"""
log.debug(u'video')
self.loaded = True
js = u'show_video("init", "%s", %s, true); show_video("play");' % \
(videoPath.replace(u'\\', u'\\\\'), str(float(volume)/float(10)))
self.frame.evaluateJavaScript(js)
vol = float(volume)/float(10)
if isBackground or not self.usePhonon:
js = u'show_video("init", "%s", %s, true); show_video("play");' % \
(videoPath.replace(u'\\', u'\\\\'), \
str(vol))
self.frame.evaluateJavaScript(js)
else:
self.phononActive = True
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.mediaObject.setCurrentSource(Phonon.MediaSource(videoPath))
self.mediaObject.play()
self.webView.setVisible(False)
self.videoWidget.setVisible(True)
self.audio.setVolume(vol)
return self.preview()
def isLoaded(self):
@ -336,8 +382,8 @@ class MainDisplay(DisplayWidget):
if self.isLive:
self.setVisible(True)
# if was hidden keep it hidden
if self.hide_mode and self.isLive:
self.hideDisplay(self.hide_mode)
if self.hideMode and self.isLive:
self.hideDisplay(self.hideMode)
preview = QtGui.QImage(self.screen[u'size'].width(),
self.screen[u'size'].height(),
QtGui.QImage.Format_ARGB32_Premultiplied)
@ -356,6 +402,9 @@ class MainDisplay(DisplayWidget):
self.loaded = False
self.initialFrame = False
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,
self.isLive)
log.debug(u'buildHtml - pre setHtml')
@ -364,8 +413,8 @@ class MainDisplay(DisplayWidget):
if serviceItem.foot_text and serviceItem.foot_text:
self.footer(serviceItem.foot_text)
# if was hidden keep it hidden
if self.hide_mode and self.isLive:
self.hideDisplay(self.hide_mode)
if self.hideMode and self.isLive:
self.hideDisplay(self.hideMode)
def footer(self, text):
"""
@ -382,6 +431,8 @@ class MainDisplay(DisplayWidget):
Store the images so they can be replaced when required
"""
log.debug(u'hideDisplay mode = %d', mode)
if self.phononActive:
self.videoPause()
if mode == HideMode.Screen:
self.frame.evaluateJavaScript(u'show_blank("desktop");')
self.setVisible(False)
@ -389,9 +440,12 @@ class MainDisplay(DisplayWidget):
self.frame.evaluateJavaScript(u'show_blank("black");')
else:
self.frame.evaluateJavaScript(u'show_blank("theme");')
if mode != HideMode.Screen and self.isHidden():
self.setVisible(True)
self.hide_mode = mode
if mode != HideMode.Screen:
if self.isHidden():
self.setVisible(True)
if self.phononActive:
self.webView.setVisible(True)
self.hideMode = mode
def showDisplay(self):
"""
@ -403,9 +457,12 @@ class MainDisplay(DisplayWidget):
self.frame.evaluateJavaScript('show_blank("show");')
if self.isHidden():
self.setVisible(True)
if self.phononActive:
self.webView.setVisible(False)
self.videoPlay()
self.hideMode = None
# Trigger actions when display is active again
Receiver.send_message(u'maindisplay_active')
self.hide_mode = None
class AudioPlayer(QtCore.QObject):
"""
@ -484,3 +541,4 @@ class AudioPlayer(QtCore.QObject):
"""
log.debug(u'AudioPlayer Reached end of media playlist')
self.mediaObject.clearQueue()

View File

@ -29,10 +29,12 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
ThemeManager, SlideController, PluginForm, MediaDockManager
ThemeManager, SlideController, PluginForm, MediaDockManager, \
ShortcutListForm
from openlp.core.lib import RenderManager, build_icon, OpenLPDockWidget, \
SettingsManager, PluginManager, Receiver, translate
from openlp.core.utils import AppLocation, add_actions, LanguageManager
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
ActionList
log = logging.getLogger(__name__)
@ -73,6 +75,7 @@ class Ui_MainWindow(object):
MainWindow.setSizePolicy(sizePolicy)
MainIcon = build_icon(u':/icon/openlp-logo-16x16.png')
MainWindow.setWindowIcon(MainIcon)
self.setDockNestingEnabled(True)
# Set up the main container, which contains all the other form widgets
self.MainContent = QtGui.QWidget(MainWindow)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
@ -94,10 +97,16 @@ class Ui_MainWindow(object):
self.ControlSplitter.setObjectName(u'ControlSplitter')
self.MainContentLayout.addWidget(self.ControlSplitter)
# Create slide controllers
self.PreviewController = SlideController(self, self.settingsmanager,
self.previewController = SlideController(self, self.settingsmanager,
self.screens)
self.LiveController = SlideController(self, self.settingsmanager,
self.liveController = SlideController(self, self.settingsmanager,
self.screens, True)
previewVisible = QtCore.QSettings().value(
u'user interface/preview panel', QtCore.QVariant(True)).toBool()
self.previewController.Panel.setVisible(previewVisible)
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
QtCore.QVariant(True)).toBool()
self.liveController.Panel.setVisible(liveVisible)
# Create menu
self.MenuBar = QtGui.QMenuBar(MainWindow)
self.MenuBar.setGeometry(QtCore.QRect(0, 0, 1087, 27))
@ -175,37 +184,36 @@ class Ui_MainWindow(object):
QtCore.Qt.DockWidgetArea(2), self.ThemeManagerDock)
# Create the menu items
self.FileNewItem = QtGui.QAction(MainWindow)
self.FileNewItem.setIcon(
self.ServiceManagerContents.toolbar.getIconFromTitle(
u'New Service'))
self.FileNewItem.setIcon(build_icon(u':/general/general_new.png'))
self.FileNewItem.setObjectName(u'FileNewItem')
MainWindow.actionList.add_action(self.FileNewItem, u'File')
self.FileOpenItem = QtGui.QAction(MainWindow)
self.FileOpenItem.setIcon(
self.ServiceManagerContents.toolbar.getIconFromTitle(
u'Open Service'))
self.FileOpenItem.setIcon(build_icon(u':/general/general_open.png'))
self.FileOpenItem.setObjectName(u'FileOpenItem')
MainWindow.actionList.add_action(self.FileOpenItem, u'File')
self.FileSaveItem = QtGui.QAction(MainWindow)
self.FileSaveItem.setIcon(
self.ServiceManagerContents.toolbar.getIconFromTitle(
u'Save Service'))
self.FileSaveItem.setIcon(build_icon(u':/general/general_save.png'))
self.FileSaveItem.setObjectName(u'FileSaveItem')
MainWindow.actionList.add_action(self.FileSaveItem, u'File')
self.FileSaveAsItem = QtGui.QAction(MainWindow)
self.FileSaveAsItem.setObjectName(u'FileSaveAsItem')
MainWindow.actionList.add_action(self.FileSaveAsItem, u'File')
self.FileExitItem = QtGui.QAction(MainWindow)
self.FileExitItem.setIcon(build_icon(u':/system/system_exit.png'))
self.FileExitItem.setObjectName(u'FileExitItem')
MainWindow.actionList.add_action(self.FileExitItem, u'File')
self.ImportThemeItem = QtGui.QAction(MainWindow)
self.ImportThemeItem.setObjectName(u'ImportThemeItem')
MainWindow.actionList.add_action(self.ImportThemeItem, u'Import')
self.ImportLanguageItem = QtGui.QAction(MainWindow)
self.ImportLanguageItem.setObjectName(u'ImportLanguageItem')
MainWindow.actionList.add_action(self.ImportLanguageItem, u'Import')
self.ExportThemeItem = QtGui.QAction(MainWindow)
self.ExportThemeItem.setObjectName(u'ExportThemeItem')
MainWindow.actionList.add_action(self.ExportThemeItem, u'Export')
self.ExportLanguageItem = QtGui.QAction(MainWindow)
self.ExportLanguageItem.setObjectName(u'ExportLanguageItem')
self.SettingsConfigureItem = QtGui.QAction(MainWindow)
self.SettingsConfigureItem.setIcon(
build_icon(u':/system/system_settings.png'))
self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem')
MainWindow.actionList.add_action(self.ExportLanguageItem, u'Export')
self.ViewMediaManagerItem = QtGui.QAction(MainWindow)
self.ViewMediaManagerItem.setCheckable(True)
self.ViewMediaManagerItem.setChecked(self.MediaManagerDock.isVisible())
@ -218,6 +226,7 @@ class Ui_MainWindow(object):
self.ViewThemeManagerItem.setIcon(
build_icon(u':/system/system_thememanager.png'))
self.ViewThemeManagerItem.setObjectName(u'ViewThemeManagerItem')
MainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View')
self.ViewServiceManagerItem = QtGui.QAction(MainWindow)
self.ViewServiceManagerItem.setCheckable(True)
self.ViewServiceManagerItem.setChecked(
@ -225,28 +234,49 @@ class Ui_MainWindow(object):
self.ViewServiceManagerItem.setIcon(
build_icon(u':/system/system_servicemanager.png'))
self.ViewServiceManagerItem.setObjectName(u'ViewServiceManagerItem')
MainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View')
self.ViewPreviewPanel = QtGui.QAction(MainWindow)
self.ViewPreviewPanel.setCheckable(True)
self.ViewPreviewPanel.setChecked(previewVisible)
self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel')
MainWindow.actionList.add_action(self.ViewPreviewPanel, u'View')
self.ViewLivePanel = QtGui.QAction(MainWindow)
self.ViewLivePanel.setCheckable(True)
self.ViewLivePanel.setChecked(liveVisible)
self.ViewLivePanel.setObjectName(u'ViewLivePanel')
MainWindow.actionList.add_action(self.ViewLivePanel, u'View')
self.ModeDefaultItem = QtGui.QAction(MainWindow)
self.ModeDefaultItem.setCheckable(True)
self.ModeDefaultItem.setObjectName(u'ModeDefaultItem')
MainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode')
self.ModeSetupItem = QtGui.QAction(MainWindow)
self.ModeSetupItem.setCheckable(True)
self.ModeSetupItem.setObjectName(u'ModeLiveItem')
MainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode')
self.ModeLiveItem = QtGui.QAction(MainWindow)
self.ModeLiveItem.setCheckable(True)
self.ModeLiveItem.setObjectName(u'ModeLiveItem')
MainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode')
self.ModeGroup = QtGui.QActionGroup(MainWindow)
self.ModeGroup.addAction(self.ModeDefaultItem)
self.ModeGroup.addAction(self.ModeSetupItem)
self.ModeGroup.addAction(self.ModeLiveItem)
self.ModeDefaultItem.setChecked(True)
self.ToolsAddToolItem = QtGui.QAction(MainWindow)
self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png'))
self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem')
MainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools')
self.SettingsPluginListItem = QtGui.QAction(MainWindow)
self.SettingsPluginListItem.setIcon(
build_icon(u':/system/settings_plugin_list.png'))
self.SettingsPluginListItem.setObjectName(u'SettingsPluginListItem')
self.HelpDocumentationItem = QtGui.QAction(MainWindow)
self.HelpDocumentationItem.setIcon(
build_icon(u':/system/system_help_contents.png'))
self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem')
self.HelpDocumentationItem.setEnabled(False)
self.HelpAboutItem = QtGui.QAction(MainWindow)
self.HelpAboutItem.setIcon(
build_icon(u':/system/system_about.png'))
self.HelpAboutItem.setObjectName(u'HelpAboutItem')
self.HelpOnlineHelpItem = QtGui.QAction(MainWindow)
self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem')
self.HelpOnlineHelpItem.setEnabled(False)
self.HelpWebSiteItem = QtGui.QAction(MainWindow)
self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem')
MainWindow.actionList.add_action(self.SettingsPluginListItem,
u'Settings')
#i18n Language Items
self.AutoLanguageItem = QtGui.QAction(MainWindow)
self.AutoLanguageItem.setObjectName(u'AutoLanguageItem')
self.AutoLanguageItem.setCheckable(True)
MainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings')
self.LanguageGroup = QtGui.QActionGroup(MainWindow)
qmList = LanguageManager.get_qm_list()
savedLanguage = LanguageManager.get_language()
@ -259,37 +289,34 @@ class Ui_MainWindow(object):
languageItem.setChecked(True)
add_actions(self.LanguageGroup, [languageItem])
self.LanguageGroup.setDisabled(LanguageManager.auto_language)
self.ToolsAddToolItem = QtGui.QAction(MainWindow)
self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png'))
self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem')
self.ViewPreviewPanel = QtGui.QAction(MainWindow)
self.ViewPreviewPanel.setCheckable(True)
previewVisible = QtCore.QSettings().value(
u'user interface/preview panel', QtCore.QVariant(True)).toBool()
self.ViewPreviewPanel.setChecked(previewVisible)
self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel')
self.PreviewController.Panel.setVisible(previewVisible)
self.ViewLivePanel = QtGui.QAction(MainWindow)
self.ViewLivePanel.setCheckable(True)
liveVisible = QtCore.QSettings().value(u'user interface/live panel',
QtCore.QVariant(True)).toBool()
self.ViewLivePanel.setChecked(liveVisible)
self.ViewLivePanel.setObjectName(u'ViewLivePanel')
self.LiveController.Panel.setVisible(liveVisible)
self.ModeDefaultItem = QtGui.QAction(MainWindow)
self.ModeDefaultItem.setCheckable(True)
self.ModeDefaultItem.setObjectName(u'ModeDefaultItem')
self.ModeSetupItem = QtGui.QAction(MainWindow)
self.ModeSetupItem.setCheckable(True)
self.ModeSetupItem.setObjectName(u'ModeLiveItem')
self.ModeLiveItem = QtGui.QAction(MainWindow)
self.ModeLiveItem.setCheckable(True)
self.ModeLiveItem.setObjectName(u'ModeLiveItem')
self.ModeGroup = QtGui.QActionGroup(MainWindow)
self.ModeGroup.addAction(self.ModeDefaultItem)
self.ModeGroup.addAction(self.ModeSetupItem)
self.ModeGroup.addAction(self.ModeLiveItem)
self.ModeDefaultItem.setChecked(True)
self.SettingsShortcutsItem = QtGui.QAction(MainWindow)
self.SettingsShortcutsItem.setIcon(
build_icon(u':/system/system_configure_shortcuts.png'))
self.SettingsShortcutsItem.setObjectName(u'SettingsShortcutsItem')
self.SettingsConfigureItem = QtGui.QAction(MainWindow)
self.SettingsConfigureItem.setIcon(
build_icon(u':/system/system_settings.png'))
self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem')
MainWindow.actionList.add_action(self.SettingsShortcutsItem,
u'Settings')
self.HelpDocumentationItem = QtGui.QAction(MainWindow)
self.HelpDocumentationItem.setIcon(
build_icon(u':/system/system_help_contents.png'))
self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem')
self.HelpDocumentationItem.setEnabled(False)
MainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help')
self.HelpAboutItem = QtGui.QAction(MainWindow)
self.HelpAboutItem.setIcon(
build_icon(u':/system/system_about.png'))
self.HelpAboutItem.setObjectName(u'HelpAboutItem')
MainWindow.actionList.add_action(self.HelpAboutItem, u'Help')
self.HelpOnlineHelpItem = QtGui.QAction(MainWindow)
self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem')
self.HelpOnlineHelpItem.setEnabled(False)
MainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help')
self.HelpWebSiteItem = QtGui.QAction(MainWindow)
self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem')
MainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help')
add_actions(self.FileImportMenu,
(self.ImportThemeItem, self.ImportLanguageItem))
add_actions(self.FileExportMenu,
@ -309,7 +336,7 @@ class Ui_MainWindow(object):
add_actions(self.SettingsLanguageMenu, self.LanguageGroup.actions())
add_actions(self.SettingsMenu, (self.SettingsPluginListItem,
self.SettingsLanguageMenu.menuAction(), None,
self.SettingsConfigureItem))
self.SettingsShortcutsItem, self.SettingsConfigureItem))
add_actions(self.ToolsMenu,
(self.ToolsAddToolItem, None))
add_actions(self.HelpMenu,
@ -335,15 +362,14 @@ class Ui_MainWindow(object):
"""
Splitter between the Preview and Live Controllers.
"""
self.LiveController.widthChanged()
self.PreviewController.widthChanged()
self.liveController.widthChanged()
self.previewController.widthChanged()
def retranslateUi(self, MainWindow):
"""
Set up the translation system
"""
MainWindow.mainTitle = translate('OpenLP.MainWindow', 'OpenLP 2.0')
# MainWindow.language = translate('OpenLP.MainWindow', 'English')
MainWindow.setWindowTitle(MainWindow.mainTitle)
self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File'))
self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import'))
@ -401,6 +427,8 @@ class Ui_MainWindow(object):
translate('OpenLP.MainWindow', '&Theme'))
self.ExportLanguageItem.setText(
translate('OpenLP.MainWindow', '&Language'))
self.SettingsShortcutsItem.setText(
translate('OpenLP.MainWindow', 'Configure &Shortcuts...'))
self.SettingsConfigureItem.setText(
translate('OpenLP.MainWindow', '&Configure OpenLP...'))
self.ViewMediaManagerItem.setText(
@ -495,6 +523,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
log.info(u'MainWindow loaded')
actionList = ActionList()
def __init__(self, screens, applicationVersion):
"""
This constructor sets up the interface, the various managers, and the
@ -502,6 +532,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
"""
QtGui.QMainWindow.__init__(self)
self.screens = screens
self.actionList = ActionList()
self.applicationVersion = applicationVersion
# Set up settings sections for the main application
# (not for use by plugins)
@ -513,11 +544,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.settingsmanager = SettingsManager(screens)
self.aboutForm = AboutForm(self, applicationVersion)
self.settingsForm = SettingsForm(self.screens, self, self)
self.shortcutForm = ShortcutListForm(self)
self.recentFiles = QtCore.QStringList()
# Set up the path with plugins
pluginpath = AppLocation.get_directory(AppLocation.PluginsDir)
self.plugin_manager = PluginManager(pluginpath)
self.plugin_helpers = {}
self.pluginManager = PluginManager(pluginpath)
self.pluginHelpers = {}
# Set up the interface
self.setupUi(self)
# Load settings after setupUi so default UI sizes are overwritten
@ -558,7 +590,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.QObject.connect(self.SettingsPluginListItem,
QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked)
QtCore.QObject.connect(self.SettingsConfigureItem,
QtCore.SIGNAL(u'triggered()'), self.onOptionsSettingsItemClicked)
QtCore.SIGNAL(u'triggered()'), self.onSettingsConfigureItemClicked)
QtCore.QObject.connect(self.SettingsShortcutsItem,
QtCore.SIGNAL(u'triggered()'), self.onSettingsShortcutsItemClicked)
QtCore.QObject.connect(self.FileNewItem, QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.onNewService)
QtCore.QObject.connect(self.FileOpenItem,
@ -570,7 +604,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.QObject.connect(self.FileSaveAsItem,
QtCore.SIGNAL(u'triggered()'),
self.ServiceManagerContents.onSaveService)
#i18n set signals for languages
# i18n set signals for languages
QtCore.QObject.connect(self.AutoLanguageItem,
QtCore.SIGNAL(u'toggled(bool)'), self.setAutoLanguage)
self.LanguageGroup.triggered.connect(LanguageManager.set_language)
@ -590,42 +624,42 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'config_screen_changed'), self.screenChanged)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_status_text'), self.showStatusMessage)
#warning cyclic dependency
#RenderManager needs to call ThemeManager and
#ThemeManager needs to call RenderManager
self.RenderManager = RenderManager(
# warning cyclic dependency
# RenderManager needs to call ThemeManager and
# ThemeManager needs to call RenderManager
self.renderManager = RenderManager(
self.ThemeManagerContents, self.screens)
#Define the media Dock Manager
# Define the media Dock Manager
self.mediaDockManager = MediaDockManager(self.MediaToolBox)
log.info(u'Load Plugins')
#make the controllers available to the plugins
self.plugin_helpers[u'preview'] = self.PreviewController
self.plugin_helpers[u'live'] = self.LiveController
self.plugin_helpers[u'render'] = self.RenderManager
self.plugin_helpers[u'service'] = self.ServiceManagerContents
self.plugin_helpers[u'settings form'] = self.settingsForm
self.plugin_helpers[u'toolbox'] = self.mediaDockManager
self.plugin_helpers[u'pluginmanager'] = self.plugin_manager
self.plugin_helpers[u'formparent'] = self
self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers)
# make the controllers available to the plugins
self.pluginHelpers[u'preview'] = self.previewController
self.pluginHelpers[u'live'] = self.liveController
self.pluginHelpers[u'render'] = self.renderManager
self.pluginHelpers[u'service'] = self.ServiceManagerContents
self.pluginHelpers[u'settings form'] = self.settingsForm
self.pluginHelpers[u'toolbox'] = self.mediaDockManager
self.pluginHelpers[u'pluginmanager'] = self.pluginManager
self.pluginHelpers[u'formparent'] = self
self.pluginManager.find_plugins(pluginpath, self.pluginHelpers)
# hook methods have to happen after find_plugins. Find plugins needs
# the controllers hence the hooks have moved from setupUI() to here
# Find and insert settings tabs
log.info(u'hook settings')
self.plugin_manager.hook_settings_tabs(self.settingsForm)
self.pluginManager.hook_settings_tabs(self.settingsForm)
# Find and insert media manager items
log.info(u'hook media')
self.plugin_manager.hook_media_manager(self.mediaDockManager)
self.pluginManager.hook_media_manager(self.mediaDockManager)
# Call the hook method to pull in import menus.
log.info(u'hook menus')
self.plugin_manager.hook_import_menu(self.FileImportMenu)
self.pluginManager.hook_import_menu(self.FileImportMenu)
# Call the hook method to pull in export menus.
self.plugin_manager.hook_export_menu(self.FileExportMenu)
self.pluginManager.hook_export_menu(self.FileExportMenu)
# Call the hook method to pull in tools menus.
self.plugin_manager.hook_tools_menu(self.ToolsMenu)
self.pluginManager.hook_tools_menu(self.ToolsMenu)
# Call the initialise method to setup plugins.
log.info(u'initialise plugins')
self.plugin_manager.initialise_plugins()
self.pluginManager.initialise_plugins()
# Once all components are initialised load the Themes
log.info(u'Load Themes')
self.ThemeManagerContents.loadThemes()
@ -661,10 +695,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
Show the main form, as well as the display form
"""
QtGui.QWidget.show(self)
self.LiveController.display.setup()
self.PreviewController.display.setup()
if self.LiveController.display.isVisible():
self.LiveController.display.setFocus()
self.liveController.display.setup()
self.previewController.display.setup()
if self.liveController.display.isVisible():
self.liveController.display.setFocus()
self.activateWindow()
if QtCore.QSettings().value(
self.generalSettingsSection + u'/auto open',
@ -689,7 +723,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
settings = QtCore.QSettings()
if settings.value(u'%s/screen blank' % self.generalSettingsSection,
QtCore.QVariant(False)).toBool():
self.LiveController.mainDisplaySetBackground()
self.liveController.mainDisplaySetBackground()
if settings.value(u'blank warning',
QtCore.QVariant(False)).toBool():
QtGui.QMessageBox.question(self,
@ -719,12 +753,18 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.pluginForm.load()
self.pluginForm.exec_()
def onOptionsSettingsItemClicked(self):
def onSettingsConfigureItemClicked(self):
"""
Show the Settings dialog
"""
self.settingsForm.exec_()
def onSettingsShortcutsItemClicked(self):
"""
Show the shortcuts dialog
"""
self.shortcutForm.exec_(self.actionList)
def onModeDefaultItemClicked(self):
"""
Put OpenLP into "Default" view mode.
@ -769,7 +809,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
their locations
"""
log.debug(u'screenChanged')
self.RenderManager.update_display()
self.renderManager.update_display()
self.setFocus()
self.activateWindow()
@ -788,7 +828,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtGui.QMessageBox.Save),
QtGui.QMessageBox.Save)
if ret == QtGui.QMessageBox.Save:
self.ServiceManagerContents.onSaveService()
self.ServiceManagerContents.onSaveService(True)
self.cleanUp()
event.accept()
elif ret == QtGui.QMessageBox.Discard:
@ -812,11 +852,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.QVariant(self.MediaToolBox.currentIndex()))
# Call the cleanup method to shutdown plugins.
log.info(u'cleanup plugins')
self.plugin_manager.finalise_plugins()
self.pluginManager.finalise_plugins()
# Save settings
self.saveSettings()
#Close down the display
self.LiveController.display.close()
# Close down the display
self.liveController.display.close()
def serviceChanged(self, reset=False, serviceName=None):
"""
@ -870,7 +910,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
True - Visible
False - Hidden
"""
self.PreviewController.Panel.setVisible(visible)
self.previewController.Panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/preview panel',
QtCore.QVariant(visible))
self.ViewPreviewPanel.setChecked(visible)
@ -885,7 +925,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
True - Visible
False - Hidden
"""
self.LiveController.Panel.setVisible(visible)
self.liveController.Panel.setVisible(visible)
QtCore.QSettings().setValue(u'user interface/live panel',
QtCore.QVariant(visible))
self.ViewLivePanel.setChecked(visible)

View File

@ -26,6 +26,8 @@
import logging
from openlp.core.lib import StringContent
log = logging.getLogger(__name__)
class MediaDockManager(object):
@ -48,8 +50,9 @@ class MediaDockManager(object):
``icon``
An icon for this dock item
"""
log.info(u'Adding %s dock' % media_item.title)
self.media_dock.addItem(media_item, icon, media_item.title)
visible_title = media_item.plugin.getString(StringContent.VisibleName)
log.info(u'Adding %s dock' % visible_title)
self.media_dock.addItem(media_item, icon, visible_title[u'title'])
def insert_dock(self, media_item, icon, weight):
"""
@ -57,27 +60,29 @@ class MediaDockManager(object):
This does not work as it gives a Segmentation error.
For now add at end of stack if not present
"""
log.debug(u'Inserting %s dock' % media_item.title)
visible_title = media_item.plugin.getString(StringContent.VisibleName)
log.debug(u'Inserting %s dock' % visible_title[u'title'])
match = False
for dock_index in range(0, self.media_dock.count()):
if self.media_dock.widget(dock_index).settingsSection == \
media_item.title.lower():
media_item.plugin.name.lower():
match = True
break
if not match:
self.media_dock.addItem(media_item, icon, media_item.title)
self.media_dock.addItem(media_item, icon, visible_title[u'title'])
def remove_dock(self, name):
def remove_dock(self, media_item):
"""
Removes a MediaManagerItem from the dock
``name``
The item to remove
``media_item``
The item to add to the dock
"""
log.debug(u'remove %s dock' % name)
visible_title = media_item.plugin.getString(StringContent.VisibleName)
log.debug(u'remove %s dock' % visible_title[u'title'])
for dock_index in range(0, self.media_dock.count()):
if self.media_dock.widget(dock_index):
if self.media_dock.widget(dock_index).settingsSection == \
name.lower():
media_item.plugin.name.lower():
self.media_dock.widget(dock_index).hide()
self.media_dock.removeItem(dock_index)

View File

@ -28,7 +28,7 @@ import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import PluginStatus, translate
from openlp.core.lib import PluginStatus, StringContent, translate
from plugindialog import Ui_PluginViewDialog
log = logging.getLogger(__name__)
@ -61,7 +61,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
self.programaticChange = True
self._clearDetails()
self.programaticChange = True
for plugin in self.parent.plugin_manager.plugins:
for plugin in self.parent.pluginManager.plugins:
item = QtGui.QListWidgetItem(self.pluginListWidget)
# We do this just to make 100% sure the status is an integer as
# sometimes when it's loaded from the config, it isn't cast to int.
@ -78,7 +78,8 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
elif plugin.status == PluginStatus.Disabled:
status_text = unicode(
translate('OpenLP.PluginForm', '%s (Disabled)'))
item.setText(status_text % plugin.name)
name_string = plugin.getString(StringContent.Name)
item.setText(status_text % name_string[u'plural'])
# If the plugin has an icon, set it!
if plugin.icon:
item.setIcon(plugin.icon)
@ -106,10 +107,12 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
if self.pluginListWidget.currentItem() is None:
self._clearDetails()
return
plugin_name = self.pluginListWidget.currentItem().text().split(u' ')[0]
plugin_name_plural = \
self.pluginListWidget.currentItem().text().split(u' ')[0]
self.activePlugin = None
for plugin in self.parent.plugin_manager.plugins:
if plugin.name == plugin_name:
for plugin in self.parent.pluginManager.plugins:
name_string = plugin.getString(StringContent.Name)
if name_string[u'plural'] == plugin_name_plural:
self.activePlugin = plugin
break
if self.activePlugin:
@ -137,5 +140,6 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
elif self.activePlugin.status == PluginStatus.Disabled:
status_text = unicode(
translate('OpenLP.PluginForm', '%s (Disabled)'))
name_string = self.activePlugin.getString(StringContent.Name)
self.pluginListWidget.currentItem().setText(
status_text % self.activePlugin.name)
status_text % name_string[u'plural'])

View File

@ -25,6 +25,7 @@
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
class Ui_ServiceItemEditDialog(object):
@ -44,16 +45,26 @@ class Ui_ServiceItemEditDialog(object):
self.topLayout.addWidget(self.listWidget)
self.buttonLayout = QtGui.QVBoxLayout()
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.setObjectName(u'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.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.buttonLayout.addWidget(self.downButton)
self.topLayout.addLayout(self.buttonLayout)
@ -70,7 +81,5 @@ class Ui_ServiceItemEditDialog(object):
def retranslateUi(self, serviceItemEditDialog):
serviceItemEditDialog.setWindowTitle(
translate('OpenLP.ServiceItemEditForm', 'Reorder Service Item'))
self.upButton.setText(translate('OpenLP.ServiceItemEditForm', 'Up'))
self.deleteButton.setText(translate('OpenLP.ServiceItemEditForm',
'Delete'))
self.downButton.setText(translate('OpenLP.ServiceItemEditForm', 'Down'))

View File

@ -64,8 +64,7 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
self.item._raw_frames = []
if self.item.is_image():
for item in self.itemList:
self.item.add_from_image(item[u'path'], item[u'title'],
item[u'image'])
self.item.add_from_image(item[u'path'], item[u'title'])
self.item.render()
return self.item

View File

@ -107,6 +107,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceName = u''
self.suffixes = []
self.droppos = 0
self.expandTabs = False
#is a new service and has not been saved
self.isNew = True
self.serviceNoteForm = ServiceNoteForm(self.parent)
@ -115,6 +116,7 @@ class ServiceManager(QtGui.QWidget):
self.layout = QtGui.QVBoxLayout(self)
self.layout.setSpacing(0)
self.layout.setMargin(0)
self.expandTabs = False
# Create the top toolbar
self.toolbar = OpenLPToolbar(self)
self.toolbar.addToolbarButton(
@ -199,6 +201,19 @@ class ServiceManager(QtGui.QWidget):
translate('OpenLP.ServiceManager',
'Delete the selected item from the service.'),
self.onDeleteFromService)
self.orderToolbar.addSeparator()
self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', '&Expand all'),
u':/services/service_expand_all.png',
translate('OpenLP.ServiceManager',
'Expand all the service items.'),
self.onExpandAll)
self.orderToolbar.addToolbarButton(
translate('OpenLP.ServiceManager', '&Collapse all'),
u':/services/service_collapse_all.png',
translate('OpenLP.ServiceManager',
'Collapse all the service items.'),
self.onCollapseAll)
self.layout.addWidget(self.orderToolbar)
# Connect up our signals and slots
QtCore.QObject.connect(self.themeComboBox,
@ -220,9 +235,11 @@ class ServiceManager(QtGui.QWidget):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'config_updated'), self.regenerateServiceItems)
QtCore.SIGNAL(u'config_updated'), self.configUpdated)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_global'), self.themeChange)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'service_item_update'), self.serviceItemUpdate)
# Last little bits of setting up
self.service_theme = unicode(QtCore.QSettings().value(
self.parent.serviceSettingsSection + u'/service theme',
@ -263,6 +280,17 @@ class ServiceManager(QtGui.QWidget):
self.themeMenu = QtGui.QMenu(
translate('OpenLP.ServiceManager', '&Change Item Theme'))
self.menu.addMenu(self.themeMenu)
self.configUpdated(True)
def configUpdated(self, firstTime=False):
"""
Triggered when Config dialog is updated.
"""
self.expandTabs = QtCore.QSettings().value(
u'advanced/expand service item',
QtCore.QVariant(u'False')).toBool()
if not firstTime:
self.regenerateServiceItems()
def supportedSuffixes(self, suffix):
self.suffixes.append(suffix)
@ -279,8 +307,8 @@ class ServiceManager(QtGui.QWidget):
self.editAction.setVisible(False)
self.maintainAction.setVisible(False)
self.notesAction.setVisible(False)
if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit) \
and hasattr(serviceItem[u'service_item'], u'editId'):
if serviceItem[u'service_item'].is_capable(ItemCapabilities.AllowsEdit)\
and serviceItem[u'service_item'].edit_id:
self.editAction.setVisible(True)
if serviceItem[u'service_item']\
.is_capable(ItemCapabilities.AllowsMaintain):
@ -319,7 +347,7 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems[item][u'service_item'])
if self.serviceItemEditForm.exec_():
self.addServiceItem(self.serviceItemEditForm.getServiceItem(),
replace=True)
replace=True, expand=self.serviceItems[item][u'expanded'])
def nextItem(self):
"""
@ -414,13 +442,22 @@ class ServiceManager(QtGui.QWidget):
if setSelected:
setSelected = False
serviceIterator.value().setSelected(True)
elif serviceIterator.value() and serviceIterator.value().isSelected():
elif serviceIterator.value() and \
serviceIterator.value().isSelected():
serviceIterator.value().setSelected(False)
setSelected = True
serviceIterator += 1
if setSelected:
firstItem.setSelected(True)
def onCollapseAll(self):
"""
Collapse all the service items
"""
for item in self.serviceItems:
item[u'expanded'] = False
self.regenerateServiceItems()
def collapsed(self, item):
"""
Record if an item is collapsed
@ -429,6 +466,14 @@ class ServiceManager(QtGui.QWidget):
pos = item.data(0, QtCore.Qt.UserRole).toInt()[0]
self.serviceItems[pos -1 ][u'expanded'] = False
def onExpandAll(self):
"""
Collapse all the service items
"""
for item in self.serviceItems:
item[u'expanded'] = True
self.regenerateServiceItems()
def expanded(self, item):
"""
Record if an item is collapsed
@ -526,12 +571,12 @@ class ServiceManager(QtGui.QWidget):
Used when moving items as the move takes place in supporting array,
and when regenerating all the items due to theme changes
"""
#Correct order of items in array
# Correct order of items in array
count = 1
for item in self.serviceItems:
item[u'order'] = count
count += 1
#Repaint the screen
# Repaint the screen
self.serviceManagerList.clear()
for itemcount, item in enumerate(self.serviceItems):
serviceitem = item[u'service_item']
@ -600,16 +645,23 @@ class ServiceManager(QtGui.QWidget):
zip = None
file = None
try:
write_list = []
zip = zipfile.ZipFile(unicode(filename), 'w')
for item in self.serviceItems:
service.append({u'serviceitem':item[u'service_item']
.get_service_repr()})
if item[u'service_item'].uses_file():
for frame in item[u'service_item'].get_frames():
path_from = unicode(os.path.join(
frame[u'path'],
frame[u'title']))
zip.write(path_from.encode(u'utf-8'))
if item[u'service_item'].is_image():
path_from = frame[u'path']
else:
path_from = unicode(os.path.join(
frame[u'path'],
frame[u'title']))
# On write a file once
if not path_from in write_list:
write_list.append(path_from)
zip.write(path_from.encode(u'utf-8'))
file = open(servicefile, u'wb')
cPickle.dump(service, file)
file.close()
@ -707,10 +759,14 @@ class ServiceManager(QtGui.QWidget):
self.onNewService()
for item in items:
serviceitem = ServiceItem()
serviceitem.render_manager = self.parent.RenderManager
serviceitem.render_manager = self.parent.renderManager
serviceitem.set_from_service(item, self.servicePath)
self.validateItem(serviceitem)
self.addServiceItem(serviceitem)
if serviceitem.is_capable(
ItemCapabilities.OnLoadUpdate):
Receiver.send_message(u'%s_service_load' %
serviceitem.name.lower(), serviceitem)
try:
if os.path.isfile(p_file):
os.remove(p_file)
@ -733,6 +789,8 @@ class ServiceManager(QtGui.QWidget):
self.serviceName = name[len(name) - 1]
self.parent.addRecentFile(filename)
self.parent.serviceChanged(True, self.serviceName)
# Refresh Plugin lists
Receiver.send_message(u'plugin_list_refresh')
def validateItem(self, serviceItem):
"""
@ -762,7 +820,7 @@ class ServiceManager(QtGui.QWidget):
"""
log.debug(u'onThemeComboBoxSelected')
self.service_theme = unicode(self.themeComboBox.currentText())
self.parent.RenderManager.set_service_theme(self.service_theme)
self.parent.renderManager.set_service_theme(self.service_theme)
QtCore.QSettings().setValue(
self.parent.serviceSettingsSection + u'/service theme',
QtCore.QVariant(self.service_theme))
@ -774,7 +832,7 @@ class ServiceManager(QtGui.QWidget):
sure the theme combo box is in the correct state.
"""
log.debug(u'themeChange')
if self.parent.RenderManager.theme_level == ThemeLevel.Global:
if self.parent.renderManager.theme_level == ThemeLevel.Global:
self.toolbar.actions[u'ThemeLabel'].setVisible(False)
self.toolbar.actions[u'ThemeWidget'].setVisible(False)
else:
@ -788,7 +846,7 @@ class ServiceManager(QtGui.QWidget):
"""
log.debug(u'regenerateServiceItems')
# force reset of renderer as theme data has changed
self.parent.RenderManager.themedata = None
self.parent.renderManager.themedata = None
if self.serviceItems:
tempServiceItems = self.serviceItems
self.serviceManagerList.clear()
@ -796,28 +854,57 @@ class ServiceManager(QtGui.QWidget):
self.isNew = True
for item in tempServiceItems:
self.addServiceItem(
item[u'service_item'], False, item[u'expanded'])
item[u'service_item'], False, expand=item[u'expanded'])
# Set to False as items may have changed rendering
# does not impact the saved song so True may also be valid
self.parent.serviceChanged(False, self.serviceName)
def addServiceItem(self, item, rebuild=False, expand=True, replace=False):
def serviceItemUpdate(self, message):
"""
Triggered from plugins to update service items.
"""
editId, uuid = message.split(u':')
for item in self.serviceItems:
if item[u'service_item']._uuid == uuid:
item[u'service_item'].edit_id = editId
def replaceServiceItem(self, newItem):
"""
Using the service item passed replace the one with the same edit id
if found.
"""
newItem.render()
for itemcount, item in enumerate(self.serviceItems):
if item[u'service_item'].edit_id == newItem.edit_id and \
item[u'service_item'].name == newItem.name:
newItem.merge(item[u'service_item'])
item[u'service_item'] = newItem
self.repaintServiceList(itemcount + 1, 0)
self.parent.liveController.replaceServiceManagerItem(newItem)
self.parent.serviceChanged(False, self.serviceName)
def addServiceItem(self, item, rebuild=False, expand=None, replace=False):
"""
Add a Service item to the list
``item``
Service Item to be added
``expand``
Override the default expand settings. (Tristate)
"""
log.debug(u'addServiceItem')
# if not passed set to config value
if expand is None:
expand = self.expandTabs
sitem = self.findServiceItem()[0]
item.render()
if replace:
item.merge(self.serviceItems[sitem][u'service_item'])
self.serviceItems[sitem][u'service_item'] = item
self.repaintServiceList(sitem + 1, 0)
self.parent.LiveController.replaceServiceManagerItem(item)
self.parent.liveController.replaceServiceManagerItem(item)
else:
#nothing selected for dnd
# nothing selected for dnd
if self.droppos == 0:
if isinstance(item, list):
for inditem in item:
@ -834,9 +921,9 @@ class ServiceManager(QtGui.QWidget):
u'order': self.droppos,
u'expanded':expand})
self.repaintServiceList(self.droppos, 0)
#if rebuilding list make sure live is fixed.
# if rebuilding list make sure live is fixed.
if rebuild:
self.parent.LiveController.replaceServiceManagerItem(item)
self.parent.liveController.replaceServiceManagerItem(item)
self.droppos = 0
self.parent.serviceChanged(False, self.serviceName)
@ -846,7 +933,7 @@ class ServiceManager(QtGui.QWidget):
"""
item, count = self.findServiceItem()
if self.serviceItems[item][u'service_item'].is_valid:
self.parent.PreviewController.addServiceManagerItem(
self.parent.previewController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], count)
else:
QtGui.QMessageBox.critical(self,
@ -870,7 +957,7 @@ class ServiceManager(QtGui.QWidget):
"""
item, count = self.findServiceItem()
if self.serviceItems[item][u'service_item'].is_valid:
self.parent.LiveController.addServiceManagerItem(
self.parent.liveController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], count)
if QtCore.QSettings().value(
self.parent.generalSettingsSection + u'/auto preview',
@ -879,9 +966,9 @@ class ServiceManager(QtGui.QWidget):
if self.serviceItems and item < len(self.serviceItems) and \
self.serviceItems[item][u'service_item'].is_capable(
ItemCapabilities.AllowsPreview):
self.parent.PreviewController.addServiceManagerItem(
self.parent.previewController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], 0)
self.parent.LiveController.PreviewListWidget.setFocus()
self.parent.liveController.PreviewListWidget.setFocus()
else:
QtGui.QMessageBox.critical(self,
translate('OpenLP.ServiceManager', 'Missing Display Handler'),
@ -898,7 +985,7 @@ class ServiceManager(QtGui.QWidget):
.is_capable(ItemCapabilities.AllowsEdit):
Receiver.send_message(u'%s_edit' %
self.serviceItems[item][u'service_item'].name.lower(), u'L:%s' %
self.serviceItems[item][u'service_item'].editId )
self.serviceItems[item][u'service_item'].edit_id )
def findServiceItem(self):
"""
@ -914,7 +1001,7 @@ class ServiceManager(QtGui.QWidget):
else:
pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0]
count = item.data(0, QtCore.Qt.UserRole).toInt()[0]
#adjust for zero based arrays
# adjust for zero based arrays
pos = pos - 1
return pos, count
@ -940,9 +1027,12 @@ class ServiceManager(QtGui.QWidget):
if link.hasText():
plugin = event.mimeData().text()
item = self.serviceManagerList.itemAt(event.pos())
#ServiceManager started the drag and drop
# ServiceManager started the drag and drop
if plugin == u'ServiceManager':
startpos, startCount = self.findServiceItem()
# If no items selected
if startpos == -1:
return
if item is None:
endpos = len(self.serviceItems)
else:
@ -952,22 +1042,22 @@ class ServiceManager(QtGui.QWidget):
self.serviceItems.insert(endpos, serviceItem)
self.repaintServiceList(endpos, startCount)
else:
#we are not over anything so drop
# we are not over anything so drop
replace = False
if item is None:
self.droppos = len(self.serviceItems)
else:
#we are over somthing so lets investigate
# we are over somthing so lets investigate
pos = self._getParentItemData(item) - 1
serviceItem = self.serviceItems[pos]
if (plugin == serviceItem[u'service_item'].name and
serviceItem[u'service_item'].is_capable(
ItemCapabilities.AllowsAdditions)):
action = self.dndMenu.exec_(QtGui.QCursor.pos())
#New action required
# New action required
if action == self.newAction:
self.droppos = self._getParentItemData(item)
#Append to existing action
# Append to existing action
if action == self.addToAction:
self.droppos = self._getParentItemData(item)
item.setSelected(True)
@ -998,7 +1088,7 @@ class ServiceManager(QtGui.QWidget):
index = 0
self.service_theme = u''
self.themeComboBox.setCurrentIndex(index)
self.parent.RenderManager.set_service_theme(self.service_theme)
self.parent.renderManager.set_service_theme(self.service_theme)
self.regenerateServiceItems()
def onThemeChangeAction(self):

View File

@ -72,14 +72,15 @@ class SettingsForm(QtGui.QDialog, Ui_SettingsDialog):
self.settingsTabWidget.insertTab(
location + 14, tab, tab.tabTitleVisible)
def removeTab(self, name):
def removeTab(self, tab):
"""
Remove a tab from the form
"""
log.debug(u'remove %s tab' % name)
log.debug(u'remove %s tab' % tab.tabTitleVisible)
for tabIndex in range(0, self.settingsTabWidget.count()):
if self.settingsTabWidget.widget(tabIndex):
if self.settingsTabWidget.widget(tabIndex).tabTitle == name:
if self.settingsTabWidget.widget(tabIndex).tabTitleVisible == \
tab.tabTitleVisible:
self.settingsTabWidget.removeTab(tabIndex)
def accept(self):

View File

@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, build_icon
class Ui_ShortcutListDialog(object):
def setupUi(self, shortcutListDialog):
shortcutListDialog.setObjectName(u'shortcutListDialog')
shortcutListDialog.resize(500, 438)
self.shortcutListLayout = QtGui.QVBoxLayout(shortcutListDialog)
self.shortcutListLayout.setSpacing(8)
self.shortcutListLayout.setMargin(8)
self.shortcutListLayout.setObjectName(u'shortcutListLayout')
self.shortcutListTreeWidget = QtGui.QTreeWidget(shortcutListDialog)
self.shortcutListTreeWidget.setAlternatingRowColors(True)
self.shortcutListTreeWidget.setObjectName(u'shortcutListTreeWidget')
self.shortcutListTreeWidget.setColumnCount(2)
self.shortcutListTreeWidget.setSelectionBehavior(
QtGui.QAbstractItemView.SelectRows)
self.shortcutListLayout.addWidget(self.shortcutListTreeWidget)
self.shortcutLayout = QtGui.QVBoxLayout()
self.shortcutLayout.setSpacing(8)
self.shortcutLayout.setContentsMargins(0, -1, -1, -1)
self.shortcutLayout.setObjectName(u'shortcutLayout')
self.defaultRadioButton = QtGui.QRadioButton(shortcutListDialog)
self.defaultRadioButton.setChecked(True)
self.defaultRadioButton.setObjectName(u'defaultRadioButton')
self.shortcutLayout.addWidget(self.defaultRadioButton)
self.customShortcutLayout = QtGui.QHBoxLayout()
self.customShortcutLayout.setSpacing(8)
self.customShortcutLayout.setObjectName(u'customShortcutLayout')
self.customRadioButton = QtGui.QRadioButton(shortcutListDialog)
self.customRadioButton.setObjectName(u'customRadioButton')
self.customShortcutLayout.addWidget(self.customRadioButton)
self.shortcutPushButton = QtGui.QPushButton(shortcutListDialog)
self.shortcutPushButton.setMinimumSize(QtCore.QSize(84, 0))
self.shortcutPushButton.setIcon(
build_icon(u':/system/system_configure_shortcuts.png'))
self.shortcutPushButton.setCheckable(True)
self.shortcutPushButton.setChecked(False)
self.shortcutPushButton.setObjectName(u'shortcutPushButton')
self.customShortcutLayout.addWidget(self.shortcutPushButton)
self.clearShortcutToolButton = QtGui.QToolButton(shortcutListDialog)
self.clearShortcutToolButton.setMinimumSize(QtCore.QSize(0, 16))
self.clearShortcutToolButton.setText(u'')
self.clearShortcutToolButton.setIcon(
build_icon(u':/system/clear_shortcut.png'))
self.clearShortcutToolButton.setObjectName(u'clearShortcutToolButton')
self.customShortcutLayout.addWidget(self.clearShortcutToolButton)
self.customShortcutSpacer = QtGui.QSpacerItem(40, 20,
QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.customShortcutLayout.addItem(self.customShortcutSpacer)
self.shortcutLayout.addLayout(self.customShortcutLayout)
self.shortcutListLayout.addLayout(self.shortcutLayout)
self.shortcutListButtonBox = QtGui.QDialogButtonBox(shortcutListDialog)
self.shortcutListButtonBox.setOrientation(QtCore.Qt.Horizontal)
self.shortcutListButtonBox.setStandardButtons(
QtGui.QDialogButtonBox.Cancel | QtGui.QDialogButtonBox.Ok |
QtGui.QDialogButtonBox.Reset)
self.shortcutListButtonBox.setObjectName(u'shortcutListButtonBox')
self.shortcutListLayout.addWidget(self.shortcutListButtonBox)
self.retranslateUi(shortcutListDialog)
QtCore.QObject.connect(
self.shortcutListButtonBox,
QtCore.SIGNAL(u'accepted()'),
shortcutListDialog.accept
)
QtCore.QObject.connect(
self.shortcutListButtonBox,
QtCore.SIGNAL(u'rejected()'),
shortcutListDialog.reject
)
QtCore.QMetaObject.connectSlotsByName(shortcutListDialog)
def retranslateUi(self, shortcutListDialog):
shortcutListDialog.setWindowTitle(
translate('OpenLP.ShortcutListDialog', 'Customize Shortcuts'))
self.shortcutListTreeWidget.setHeaderLabels([
translate('OpenLP.ShortcutListDialog', 'Action'),
translate('OpenLP.ShortcutListDialog', 'Shortcut')
])
self.defaultRadioButton.setText(
translate('OpenLP.ShortcutListDialog', 'Default: %s'))
self.customRadioButton.setText(
translate('OpenLP.ShortcutListDialog', 'Custom:'))
self.shortcutPushButton.setText(
translate('OpenLP.ShortcutListDialog', 'None'))

View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2010 Raoul Snyman #
# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian #
# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble, #
# Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import re
from PyQt4 import QtCore, QtGui
from openlp.core.utils import translate
from shortcutlistdialog import Ui_ShortcutListDialog
REMOVE_AMPERSAND = re.compile(r'&{1}')
log = logging.getLogger(__name__)
class ShortcutListForm(QtGui.QDialog, Ui_ShortcutListDialog):
"""
The shortcut list dialog
"""
def __init__(self, parent):
"""
Do some initialisation stuff
"""
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
self.actionList = None
self.captureShortcut = False
QtCore.QObject.connect(
self.shortcutPushButton,
QtCore.SIGNAL(u'toggled(bool)'),
self.onShortcutPushButtonClicked
)
def keyReleaseEvent(self, event):
Qt = QtCore.Qt
if not self.captureShortcut:
return
key = event.key()
if key == Qt.Key_Shift or key == Qt.Key_Control or \
key == Qt.Key_Meta or key == Qt.Key_Alt:
return
key_string = QtGui.QKeySequence(key).toString()
if event.modifiers() & Qt.ControlModifier == Qt.ControlModifier:
key_string = u'Ctrl+' + key_string
if event.modifiers() & Qt.AltModifier == Qt.AltModifier:
key_string = u'Alt+' + key_string
if event.modifiers() & Qt.ShiftModifier == Qt.ShiftModifier:
key_string = u'Shift+' + key_string
key_sequence = QtGui.QKeySequence(key_string)
existing_key = QtGui.QKeySequence("Ctrl+Shift+F8")
if key_sequence == existing_key:
QtGui.QMessageBox.warning(
self,
translate('OpenLP.ShortcutListDialog', 'Duplicate Shortcut'),
unicode(translate('OpenLP.ShortcutListDialog', 'The shortcut '
'"%s" is already assigned to another action, please '
'use a different shortcut.')) % key_sequence.toString(),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok),
QtGui.QMessageBox.Ok
)
else:
self.shortcutPushButton.setText(key_sequence.toString())
self.shortcutPushButton.setChecked(False)
self.captureShortcut = False
def exec_(self, actionList):
self.actionList = actionList
self.refreshActions()
return QtGui.QDialog.exec_(self)
def refreshActions(self):
self.shortcutListTreeWidget.clear()
for category in self.actionList.categories:
item = QtGui.QTreeWidgetItem([category.name])
for action in category.actions:
actionText = REMOVE_AMPERSAND.sub('', unicode(action.text()))
shortcutText = action.shortcut().toString()
actionItem = QtGui.QTreeWidgetItem([actionText, shortcutText])
actionItem.setIcon(0, action.icon())
item.addChild(actionItem)
item.setExpanded(True)
self.shortcutListTreeWidget.addTopLevelItem(item)
def onShortcutPushButtonClicked(self, toggled):
self.captureShortcut = toggled

View File

@ -179,19 +179,24 @@ class SlideController(QtGui.QWidget):
self.HideMenu.setMenu(QtGui.QMenu(
translate('OpenLP.SlideController', 'Hide'), self.Toolbar))
self.BlankScreen = QtGui.QAction(QtGui.QIcon(
u':/slides/slide_blank.png'), u'Blank Screen', self.HideMenu)
u':/slides/slide_blank.png'),
translate('OpenLP.SlideController',
'Blank Screen'), self.HideMenu)
self.BlankScreen.setCheckable(True)
QtCore.QObject.connect(self.BlankScreen,
QtCore.SIGNAL("triggered(bool)"), self.onBlankDisplay)
self.ThemeScreen = QtGui.QAction(QtGui.QIcon(
u':/slides/slide_theme.png'), u'Blank to Theme', self.HideMenu)
u':/slides/slide_theme.png'),
translate('OpenLP.SlideController',
'Blank to Theme'), self.HideMenu)
self.ThemeScreen.setCheckable(True)
QtCore.QObject.connect(self.ThemeScreen,
QtCore.SIGNAL("triggered(bool)"), self.onThemeDisplay)
if self.screens.display_count > 1:
self.DesktopScreen = QtGui.QAction(QtGui.QIcon(
u':/slides/slide_desktop.png'), u'Show Desktop',
self.HideMenu)
u':/slides/slide_desktop.png'),
translate('OpenLP.SlideController',
'Show Desktop'), self.HideMenu)
self.DesktopScreen.setCheckable(True)
QtCore.QObject.connect(self.DesktopScreen,
QtCore.SIGNAL("triggered(bool)"), self.onHideDisplay)
@ -209,7 +214,7 @@ class SlideController(QtGui.QWidget):
self.Toolbar.addToolbarSeparator(u'Close Separator')
self.Toolbar.addToolbarButton(
u'Edit Song', u':/general/general_edit.png',
translate('OpenLP.SlideController',
translate('OpenLP.SlideController',
'Edit and reload song preview'),
self.onEditSong)
if isLive:
@ -326,14 +331,13 @@ class SlideController(QtGui.QWidget):
QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected)
if not self.isLive:
if QtCore.QSettings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool():
QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLive)
QtCore.QObject.connect(self.PreviewListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
self.onGoLiveClick)
if isLive:
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
self.receiveSpinDelay)
self.receiveSpinDelay)
if isLive:
self.Toolbar.makeWidgetsInvisible(self.loopList)
self.Toolbar.actions[u'Stop Loop'].setVisible(False)
@ -386,6 +390,8 @@ class SlideController(QtGui.QWidget):
if self.isLive:
QtCore.QObject.connect(self.volumeSlider,
QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_active'), self.updatePreview)
def screenSizeChanged(self):
"""
@ -395,6 +401,7 @@ class SlideController(QtGui.QWidget):
log.debug(u'screenSizeChanged live = %s' % self.isLive)
# rebuild display as screen size changed
self.display = MainDisplay(self, self.screens, self.isLive)
self.display.imageManager = self.parent.renderManager.image_manager
self.display.alertTab = self.alertTab
self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height())
@ -410,7 +417,7 @@ class SlideController(QtGui.QWidget):
"""
log.debug(u'widthChanged live = %s' % self.isLive)
width = self.parent.ControlSplitter.sizes()[self.split]
height = width * self.parent.RenderManager.screen_ratio
height = width * self.parent.renderManager.screen_ratio
self.PreviewListWidget.setColumnWidth(0, width)
# Sort out image heights (Songs, bibles excluded)
if self.serviceItem and not self.serviceItem.is_text():
@ -427,8 +434,12 @@ class SlideController(QtGui.QWidget):
request = unicode(self.sender().text())
slideno = self.slideList[request]
if slideno > self.PreviewListWidget.rowCount():
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount())
self.PreviewListWidget.selectRow(
self.PreviewListWidget.rowCount() - 1)
else:
if slideno + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(slideno + 1, 0))
self.PreviewListWidget.selectRow(slideno)
self.onSlideSelected()
@ -456,7 +467,7 @@ class SlideController(QtGui.QWidget):
self.Toolbar.actions[u'Stop Loop'].setVisible(False)
if item.is_text():
if QtCore.QSettings().value(
self.parent.songsSettingsSection + u'/show songbar',
self.parent.songsSettingsSection + u'/display songbar',
QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
self.Toolbar.makeWidgetsVisible([u'Song Menu'])
if item.is_capable(ItemCapabilities.AllowsLoop) and \
@ -520,6 +531,9 @@ class SlideController(QtGui.QWidget):
log.debug(u'addServiceManagerItem live = %s' % self.isLive)
# If service item is the same as the current on only change slide
if item.__eq__(self.serviceItem):
if slideno + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(slideno + 1, 0))
self.PreviewListWidget.selectRow(slideno)
self.onSlideSelected()
return
@ -538,7 +552,7 @@ class SlideController(QtGui.QWidget):
Receiver.send_message(u'%s_stop' %
self.serviceItem.name.lower(), [serviceItem, self.isLive])
if self.serviceItem.is_media():
self.onMediaStop()
self.onMediaClose()
if self.isLive:
blanked = self.BlankScreen.isChecked()
else:
@ -547,7 +561,7 @@ class SlideController(QtGui.QWidget):
[serviceItem, self.isLive, blanked, slideno])
self.slideList = {}
width = self.parent.ControlSplitter.sizes()[self.split]
# Set pointing cursor when we have somthing to point at
# Set pointing cursor when we have something to point at
self.PreviewListWidget.setCursor(QtCore.Qt.PointingHandCursor)
self.serviceItem = serviceItem
self.PreviewListWidget.clear()
@ -579,13 +593,17 @@ class SlideController(QtGui.QWidget):
else:
label = QtGui.QLabel()
label.setMargin(4)
pixmap = resize_image(frame[u'image'],
self.parent.RenderManager.width,
self.parent.RenderManager.height)
label.setScaledContents(True)
label.setPixmap(QtGui.QPixmap.fromImage(pixmap))
if self.serviceItem.is_command():
image = resize_image(frame[u'image'],
self.parent.renderManager.width,
self.parent.renderManager.height)
else:
image = self.parent.renderManager.image_manager. \
get_image(frame[u'title'])
label.setPixmap(QtGui.QPixmap.fromImage(image))
self.PreviewListWidget.setCellWidget(framenumber, 0, label)
slideHeight = width * self.parent.RenderManager.screen_ratio
slideHeight = width * self.parent.renderManager.screen_ratio
row += 1
text.append(unicode(row))
self.PreviewListWidget.setItem(framenumber, 0, item)
@ -597,8 +615,12 @@ class SlideController(QtGui.QWidget):
self.PreviewListWidget.setColumnWidth(0,
self.PreviewListWidget.viewport().size().width())
if slideno > self.PreviewListWidget.rowCount():
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount())
self.PreviewListWidget.selectRow(
self.PreviewListWidget.rowCount() - 1)
else:
if slideno + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(slideno + 1, 0))
self.PreviewListWidget.selectRow(slideno)
self.enableToolBar(serviceItem)
# Pass to display for viewing
@ -657,6 +679,9 @@ class SlideController(QtGui.QWidget):
[self.serviceItem, self.isLive, index])
self.updatePreview()
else:
if index + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(index + 1, 0))
self.PreviewListWidget.selectRow(index)
self.onSlideSelected()
@ -769,20 +794,19 @@ class SlideController(QtGui.QWidget):
row = self.PreviewListWidget.currentRow()
self.selectedRow = 0
if row > -1 and row < self.PreviewListWidget.rowCount():
if self.serviceItem.is_command() and self.isLive:
Receiver.send_message(u'%s_slide' % self.serviceItem.name.lower(),
[self.serviceItem, self.isLive, row])
if self.serviceItem.is_command():
if self.isLive:
Receiver.send_message(
u'%s_slide' % self.serviceItem.name.lower(),
[self.serviceItem, self.isLive, row])
self.updatePreview()
else:
frame, raw_html = self.serviceItem.get_rendered_frame(row)
toDisplay = self.serviceItem.get_rendered_frame(row)
if self.serviceItem.is_text():
frame = self.display.text(raw_html)
frame = self.display.text(toDisplay)
else:
self.display.image(frame)
if isinstance(frame, QtGui.QImage):
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
else:
self.SlidePreview.setPixmap(QtGui.QPixmap(frame))
frame = self.display.image(toDisplay)
self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame))
self.selectedRow = row
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
row)
@ -791,22 +815,24 @@ class SlideController(QtGui.QWidget):
"""
The slide has been changed. Update the slidecontroller accordingly
"""
if row + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(row + 1, 0))
self.PreviewListWidget.selectRow(row)
self.updatePreview()
Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix,
row)
def updatePreview(self):
log.debug(u'updatePreview %s ' %self.screens.current[u'primary'])
if not self.screens.current[u'primary']:
# Grab now, but try again in a couple of seconds if slide change
# is slow
QtCore.QTimer.singleShot(0.5, self.grabMainDisplay)
QtCore.QTimer.singleShot(2.5, self.grabMainDisplay)
else:
label = self.PreviewListWidget.cellWidget(
self.PreviewListWidget.currentRow(), 1)
if label:
self.SlidePreview.setPixmap(label.pixmap())
self.SlidePreview.setPixmap(
QtGui.QPixmap.fromImage(self.display.preview()))
def grabMainDisplay(self):
winid = QtGui.QApplication.desktop().winId()
@ -836,6 +862,9 @@ class SlideController(QtGui.QWidget):
else:
Receiver.send_message('servicemanager_next_item')
return
if row + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(row + 1, 0))
self.PreviewListWidget.selectRow(row)
self.onSlideSelected()
@ -859,6 +888,9 @@ class SlideController(QtGui.QWidget):
row = self.PreviewListWidget.rowCount() - 1
else:
row = 0
if row + 1 < self.PreviewListWidget.rowCount():
self.PreviewListWidget.scrollToItem(
self.PreviewListWidget.item(row + 1, 0))
self.PreviewListWidget.selectRow(row)
self.onSlideSelected()
@ -910,7 +942,15 @@ class SlideController(QtGui.QWidget):
"""
self.songEdit = True
Receiver.send_message(u'%s_edit' % self.serviceItem.name.lower(),
u'P:%s' % self.serviceItem.editId)
u'P:%s' % self.serviceItem.edit_id)
def onGoLiveClick(self):
"""
triggered by clicking the Preview slide items
"""
if QtCore.QSettings().value(u'advanced/double click live',
QtCore.QVariant(False)).toBool():
self.onGoLive()
def onGoLive(self):
"""
@ -918,7 +958,7 @@ class SlideController(QtGui.QWidget):
"""
row = self.PreviewListWidget.currentRow()
if row > -1 and row < self.PreviewListWidget.rowCount():
self.parent.LiveController.addServiceManagerItem(
self.parent.liveController.addServiceManagerItem(
self.serviceItem, row)
def onMediaStart(self, item):
@ -926,14 +966,13 @@ class SlideController(QtGui.QWidget):
Respond to the arrival of a media service item
"""
log.debug(u'SlideController onMediaStart')
file = os.path.join(item.get_frame_path(), item.get_frame_title())
if self.isLive:
file = os.path.join(item.get_frame_path(), item.get_frame_title())
self.display.video(file, self.volume)
self.volumeSlider.setValue(self.volume)
else:
self.mediaObject.stop()
self.mediaObject.clearQueue()
file = os.path.join(item.get_frame_path(), item.get_frame_title())
self.mediaObject.setCurrentSource(Phonon.MediaSource(file))
self.seekSlider.setMediaObject(self.mediaObject)
self.seekSlider.show()
@ -981,3 +1020,17 @@ class SlideController(QtGui.QWidget):
self.video.hide()
self.SlidePreview.clear()
self.SlidePreview.show()
def onMediaClose(self):
"""
Respond to a request to close the Video
"""
log.debug(u'SlideController onMediaStop')
if self.isLive:
self.display.resetVideo()
else:
self.mediaObject.stop()
self.mediaObject.clearQueue()
self.video.hide()
self.SlidePreview.clear()
self.SlidePreview.show()

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