r1161
19
OpenLP.spec
@ -1,19 +0,0 @@
|
||||
# -*- mode: python -*-
|
||||
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'openlp.pyw'],
|
||||
pathex=[os.path.abspath('.')])
|
||||
pyz = PYZ(a.pure)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
exclude_binaries=1,
|
||||
name=os.path.join('build\\pyi.win32\\OpenLP', 'OpenLP.exe'),
|
||||
debug=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
console=False , icon='resources\\images\\OpenLP.ico')
|
||||
coll = COLLECT( exe,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
strip=False,
|
||||
upx=True,
|
||||
name=os.path.join('dist', 'OpenLP'))
|
@ -17,7 +17,7 @@ import sys
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.append(os.path.abspath(os.path.join('..', '..')))
|
||||
sys.path.insert(0, os.path.abspath(os.path.join('..', '..', '..')))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
@ -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'),
|
||||
]
|
||||
|
@ -3,9 +3,13 @@
|
||||
:mod:`core` Module
|
||||
==================
|
||||
|
||||
.. automodule:: openlp.core
|
||||
:members:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
lib
|
||||
theme
|
||||
|
||||
ui
|
||||
utils
|
@ -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`
|
||||
--------------------
|
||||
|
27
documentation/api/source/core/ui.rst
Normal 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:
|
7
documentation/api/source/core/utils.rst
Normal file
@ -0,0 +1,7 @@
|
||||
.. _core-utils:
|
||||
|
||||
Utilities
|
||||
=========
|
||||
|
||||
.. automodule:: openlp.core.utils
|
||||
:members:
|
@ -15,7 +15,6 @@ Contents:
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
openlp
|
||||
core/index
|
||||
plugins/index
|
||||
|
31
documentation/api/source/plugins/alerts.rst
Normal 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:
|
55
documentation/api/source/plugins/bibles.rst
Normal 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:
|
34
documentation/api/source/plugins/custom.rst
Normal 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:
|
22
documentation/api/source/plugins/images.rst
Normal 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:
|
20
documentation/api/source/plugins/index.rst
Normal file
@ -0,0 +1,20 @@
|
||||
.. _plugins-index:
|
||||
|
||||
Plugins
|
||||
=======
|
||||
|
||||
.. automodule:: openlp.plugins
|
||||
:members:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
songs
|
||||
bibles
|
||||
presentations
|
||||
media
|
||||
images
|
||||
custom
|
||||
remotes
|
||||
songusage
|
||||
alerts
|
22
documentation/api/source/plugins/media.rst
Normal 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:
|
40
documentation/api/source/plugins/presentations.rst
Normal file
@ -0,0 +1,40 @@
|
||||
.. _plugins-presentations:
|
||||
|
||||
Presentations Plugin
|
||||
====================
|
||||
|
||||
Plugin Class
|
||||
------------
|
||||
|
||||
.. autoclass:: openlp.plugins.presentations.presentationplugin.PresentationPlugin
|
||||
:members:
|
||||
|
||||
Helper Classes & Functions
|
||||
--------------------------
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.mediaitem
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.presentationtab
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.messagelistener
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.presentationcontroller
|
||||
:members:
|
||||
|
||||
Presentation Application Controllers
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.impresscontroller
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.pptviewcontroller
|
||||
:members:
|
||||
|
||||
.. automodule:: openlp.plugins.presentations.lib.powerpointcontroller
|
||||
:members:
|
19
documentation/api/source/plugins/remotes.rst
Normal 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:
|
103
documentation/api/source/plugins/songs.rst
Normal 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:
|
34
documentation/api/source/plugins/songusage.rst
Normal 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:
|
88
documentation/manual/Makefile
Normal 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."
|
112
documentation/manual/make.bat
Normal 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
|
208
documentation/manual/source/conf.py
Normal 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}'
|
||||
}
|
180
documentation/manual/source/dualmonitors.rst
Normal 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.
|
70
documentation/manual/source/glossary.rst
Normal 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
|
26
documentation/manual/source/index.rst
Normal 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`
|
||||
|
46
documentation/manual/source/introduction.rst
Normal file
@ -0,0 +1,46 @@
|
||||
=============
|
||||
Introduction
|
||||
=============
|
||||
|
||||
About
|
||||
-----
|
||||
|
||||
OpenLP is an open source lyrics projection application developed specifically
|
||||
for churches. It is licensed under the GNU Generic Public License, which means
|
||||
that it is free to use and distribute, and it stays free.
|
||||
|
||||
Lyrics Projection
|
||||
-----------------
|
||||
|
||||
OpenLP's purpose is to project the lyrics of songs and Bible verses using a
|
||||
computer and a data projector. OpenLP also has the ability to project videos,
|
||||
images, and also play audio. OpenLP also is highly customizable providing users
|
||||
with the ability to set up a wide variety of themes, including themes with
|
||||
video backgrounds.
|
||||
|
||||
Open Source
|
||||
-----------
|
||||
|
||||
OpenLP is open source software. This means that the source code (the
|
||||
programming instructions the developers write) is open to anyone who wants to
|
||||
look at it. This gives you, the end user, a few freedoms.
|
||||
|
||||
From a developer's perspective, it gives you the freedom to inspect the code
|
||||
and make sure that it is not malicious. Also, it gives you the freedom to
|
||||
change the code and the freedom to "fork" the project and make it your own.
|
||||
|
||||
For end users open source software gives you the freedom to use software as
|
||||
you wish. You are not required to pay for the software and you are free to
|
||||
make copies and distribute it to anyone you want.
|
||||
|
||||
GNU General Public License
|
||||
--------------------------
|
||||
|
||||
The GNU General Public License was specifically chosen because it ensures the
|
||||
above mentioned freedoms. It specifically states that you are not allowed
|
||||
to charge for the software, and that you have to distribute the source code as
|
||||
well.
|
||||
|
||||
You can find a copy of the GNU General Public License from the Help menu
|
||||
selecting about OpenLP or on-line
|
||||
at: http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
26
documentation/manual/source/mediamanager.rst
Normal 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.
|
BIN
documentation/manual/source/pics/dvi.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
documentation/manual/source/pics/finishedimport.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
documentation/manual/source/pics/gnome.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
documentation/manual/source/pics/kdedisplay.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
documentation/manual/source/pics/kdesystemsettings.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
documentation/manual/source/pics/mainwindow.png
Normal file
After Width: | Height: | Size: 123 KiB |
BIN
documentation/manual/source/pics/mediamanager.png
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
documentation/manual/source/pics/nvlinux1.png
Normal file
After Width: | Height: | Size: 140 KiB |
BIN
documentation/manual/source/pics/plugins.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
documentation/manual/source/pics/preview.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
documentation/manual/source/pics/selectsongs.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
documentation/manual/source/pics/servicemanager.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
documentation/manual/source/pics/slidecontroller.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
documentation/manual/source/pics/songimporter.png
Normal file
After Width: | Height: | Size: 138 KiB |
BIN
documentation/manual/source/pics/songimporterchoices.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
documentation/manual/source/pics/songselectlyrics.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
documentation/manual/source/pics/songselectsongsearch.png
Normal file
After Width: | Height: | Size: 160 KiB |
BIN
documentation/manual/source/pics/songusage.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
documentation/manual/source/pics/songusagedelete.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
documentation/manual/source/pics/songusagereport.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
documentation/manual/source/pics/thememanager.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
documentation/manual/source/pics/twinview.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
documentation/manual/source/pics/vga.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
documentation/manual/source/pics/vistadisplaysettings.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
documentation/manual/source/pics/vistapersonalize.png
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
documentation/manual/source/pics/winsevendisplay.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
documentation/manual/source/pics/winsevenresolution.png
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
documentation/manual/source/pics/xorgwrite.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
documentation/manual/source/pics/xpdisplaysettings.png
Normal file
After Width: | Height: | Size: 24 KiB |
100
documentation/manual/source/songs.rst
Normal 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.
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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:
|
@ -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:
|
116
openlp.pyw
@ -30,6 +30,7 @@ import sys
|
||||
import logging
|
||||
from optparse import OptionParser
|
||||
from traceback import format_exception
|
||||
from subprocess import Popen, PIPE
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
@ -71,6 +72,84 @@ class OpenLP(QtGui.QApplication):
|
||||
"""
|
||||
log.info(u'OpenLP Application Loaded')
|
||||
|
||||
def _get_version(self):
|
||||
"""
|
||||
Load and store current Application Version
|
||||
"""
|
||||
if u'--dev-version' in sys.argv:
|
||||
# If we're running the dev version, let's use bzr to get the version
|
||||
try:
|
||||
# If bzrlib is availble, use it
|
||||
from bzrlib.branch import Branch
|
||||
b = Branch.open_containing('.')[0]
|
||||
b.lock_read()
|
||||
try:
|
||||
# Get the branch's latest revision number.
|
||||
revno = b.revno()
|
||||
# Convert said revision number into a bzr revision id.
|
||||
revision_id = b.dotted_revno_to_revision_id((revno,))
|
||||
# Get a dict of tags, with the revision id as the key.
|
||||
tags = b.tags.get_reverse_tag_dict()
|
||||
# Check if the latest
|
||||
if revision_id in tags:
|
||||
full_version = u'%s' % tags[revision_id][0]
|
||||
else:
|
||||
full_version = '%s-bzr%s' % \
|
||||
(sorted(b.tags.get_tag_dict().keys())[-1], revno)
|
||||
finally:
|
||||
b.unlock()
|
||||
except:
|
||||
# Otherwise run the command line bzr client
|
||||
bzr = Popen((u'bzr', u'tags', u'--sort', u'time'), stdout=PIPE)
|
||||
output, error = bzr.communicate()
|
||||
code = bzr.wait()
|
||||
if code != 0:
|
||||
raise Exception(u'Error running bzr tags')
|
||||
lines = output.splitlines()
|
||||
if len(lines) == 0:
|
||||
tag = u'0.0.0'
|
||||
revision = u'0'
|
||||
else:
|
||||
tag, revision = lines[-1].split()
|
||||
bzr = Popen((u'bzr', u'log', u'--line', u'-r', u'-1'),
|
||||
stdout=PIPE)
|
||||
output, error = bzr.communicate()
|
||||
code = bzr.wait()
|
||||
if code != 0:
|
||||
raise Exception(u'Error running bzr log')
|
||||
latest = output.split(u':')[0]
|
||||
full_version = latest == revision and tag or \
|
||||
u'%s-bzr%s' % (tag, latest)
|
||||
else:
|
||||
# We're not running the development version, let's use the file
|
||||
filepath = AppLocation.get_directory(AppLocation.VersionDir)
|
||||
filepath = os.path.join(filepath, u'.version')
|
||||
fversion = None
|
||||
try:
|
||||
fversion = open(filepath, u'r')
|
||||
full_version = unicode(fversion.read()).rstrip()
|
||||
except IOError:
|
||||
log.exception('Error in version file.')
|
||||
full_version = u'0.0.0-bzr000'
|
||||
finally:
|
||||
if fversion:
|
||||
fversion.close()
|
||||
bits = full_version.split(u'-')
|
||||
app_version = {
|
||||
u'full': full_version,
|
||||
u'version': bits[0],
|
||||
u'build': bits[1] if len(bits) > 1 else None
|
||||
}
|
||||
if app_version[u'build']:
|
||||
log.info(
|
||||
u'Openlp version %s build %s',
|
||||
app_version[u'version'],
|
||||
app_version[u'build']
|
||||
)
|
||||
else:
|
||||
log.info(u'Openlp version %s' % app_version[u'version'])
|
||||
return app_version
|
||||
|
||||
def notify(self, obj, evt):
|
||||
#TODO needed for presentation exceptions
|
||||
return QtGui.QApplication.notify(self, obj, evt)
|
||||
@ -79,39 +158,7 @@ class OpenLP(QtGui.QApplication):
|
||||
"""
|
||||
Run the OpenLP application.
|
||||
"""
|
||||
#Load and store current Application Version
|
||||
filepath = AppLocation.get_directory(AppLocation.VersionDir)
|
||||
filepath = os.path.join(filepath, u'.version')
|
||||
fversion = None
|
||||
try:
|
||||
fversion = open(filepath, u'r')
|
||||
for line in fversion:
|
||||
full_version = unicode(line).rstrip() #\
|
||||
#.replace(u'\r', u'').replace(u'\n', u'')
|
||||
bits = full_version.split(u'-')
|
||||
app_version = {
|
||||
u'full': full_version,
|
||||
u'version': bits[0],
|
||||
u'build': bits[1] if len(bits) > 1 else None
|
||||
}
|
||||
if app_version[u'build']:
|
||||
log.info(
|
||||
u'Openlp version %s build %s',
|
||||
app_version[u'version'],
|
||||
app_version[u'build']
|
||||
)
|
||||
else:
|
||||
log.info(u'Openlp version %s' % app_version[u'version'])
|
||||
except IOError:
|
||||
log.exception('Error in version file.')
|
||||
app_version = {
|
||||
u'full': u'1.9.0-bzr000',
|
||||
u'version': u'1.9.0',
|
||||
u'build': u'bzr000'
|
||||
}
|
||||
finally:
|
||||
if fversion:
|
||||
fversion.close()
|
||||
app_version = self._get_version()
|
||||
#provide a listener for widgets to reqest a screen update.
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'openlp_process_events'), self.processEvents)
|
||||
@ -172,6 +219,9 @@ def main():
|
||||
parser.add_option('-p', '--portable', dest='portable',
|
||||
action='store_true', help='Specify if this should be run as a '
|
||||
'portable app, off a USB flash drive (not implemented).')
|
||||
parser.add_option('-d', '--dev-version', dest='dev_version',
|
||||
action='store_true', help='Ignore the version file and pull the '
|
||||
'version directly from Bazaar')
|
||||
parser.add_option('-s', '--style', dest='style',
|
||||
help='Set the Qt4 style (passed directly to Qt4).')
|
||||
# Set up logging
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -193,6 +193,14 @@ class EventReceiver(QtCore.QObject):
|
||||
``{plugin}_add_service_item``
|
||||
Ask the plugin to push the selected items to the service item
|
||||
|
||||
``{plugin}_service_load``
|
||||
Ask the plugin to process an individual service item after it has been
|
||||
loaded
|
||||
|
||||
``service_item_update``
|
||||
Passes back to the service manager the service item after it has been
|
||||
processed by the plugin
|
||||
|
||||
``alerts_text``
|
||||
Displays an alert message
|
||||
|
||||
|
@ -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 */
|
||||
@ -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):
|
||||
|
168
openlp/core/lib/imagemanager.py
Normal 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
|
38
openlp/core/lib/mailto/LICENSE
Normal 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.
|
||||
|
321
openlp/core/lib/mailto/__init__.py
Normal 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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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']
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
@ -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']
|
||||
|
@ -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),
|
||||
|
@ -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):
|
||||
|
@ -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'))
|
@ -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
|
@ -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'))
|
||||
|
@ -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)
|
||||
|
@ -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:'))
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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:
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
import logging
|
||||
|
||||
from openlp.core.lib import StringContent
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class MediaDockManager(object):
|
||||
@ -48,8 +50,9 @@ class MediaDockManager(object):
|
||||
``icon``
|
||||
An icon for this dock item
|
||||
"""
|
||||
log.info(u'Adding %s dock' % media_item.title)
|
||||
self.media_dock.addItem(media_item, icon, media_item.title)
|
||||
visible_title = media_item.plugin.getString(StringContent.VisibleName)
|
||||
log.info(u'Adding %s dock' % visible_title)
|
||||
self.media_dock.addItem(media_item, icon, visible_title[u'title'])
|
||||
|
||||
def insert_dock(self, media_item, icon, weight):
|
||||
"""
|
||||
@ -57,27 +60,29 @@ class MediaDockManager(object):
|
||||
This does not work as it gives a Segmentation error.
|
||||
For now add at end of stack if not present
|
||||
"""
|
||||
log.debug(u'Inserting %s dock' % media_item.title)
|
||||
visible_title = media_item.plugin.getString(StringContent.VisibleName)
|
||||
log.debug(u'Inserting %s dock' % visible_title[u'title'])
|
||||
match = False
|
||||
for dock_index in range(0, self.media_dock.count()):
|
||||
if self.media_dock.widget(dock_index).settingsSection == \
|
||||
media_item.title.lower():
|
||||
media_item.plugin.name.lower():
|
||||
match = True
|
||||
break
|
||||
if not match:
|
||||
self.media_dock.addItem(media_item, icon, media_item.title)
|
||||
self.media_dock.addItem(media_item, icon, visible_title[u'title'])
|
||||
|
||||
def remove_dock(self, name):
|
||||
def remove_dock(self, media_item):
|
||||
"""
|
||||
Removes a MediaManagerItem from the dock
|
||||
|
||||
``name``
|
||||
The item to remove
|
||||
``media_item``
|
||||
The item to add to the dock
|
||||
"""
|
||||
log.debug(u'remove %s dock' % name)
|
||||
visible_title = media_item.plugin.getString(StringContent.VisibleName)
|
||||
log.debug(u'remove %s dock' % visible_title[u'title'])
|
||||
for dock_index in range(0, self.media_dock.count()):
|
||||
if self.media_dock.widget(dock_index):
|
||||
if self.media_dock.widget(dock_index).settingsSection == \
|
||||
name.lower():
|
||||
media_item.plugin.name.lower():
|
||||
self.media_dock.widget(dock_index).hide()
|
||||
self.media_dock.removeItem(dock_index)
|
||||
|
@ -28,7 +28,7 @@ import logging
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
from openlp.core.lib import PluginStatus, translate
|
||||
from openlp.core.lib import PluginStatus, StringContent, translate
|
||||
from plugindialog import Ui_PluginViewDialog
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -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'])
|
||||
|
@ -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'))
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
114
openlp/core/ui/shortcutlistdialog.py
Normal 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'))
|
||||
|
110
openlp/core/ui/shortcutlistform.py
Normal 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
|
||||
|
@ -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)
|
||||
@ -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()
|
||||
|