This commit is contained in:
Wesley Stout 2011-03-28 16:38:04 -05:00
commit 349cdad08f
40 changed files with 769 additions and 471 deletions

View File

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

View File

@ -42,7 +42,7 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = u'OpenLP' project = u'OpenLP'
copyright = u'2010, Raoul Snyman' copyright = u'2004 - 2011, Raoul Snyman'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@ -92,19 +92,30 @@ pygments_style = 'sphinx'
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
html_theme = 'default' if sys.argv[2] == 'qthelp' or sys.argv[2] == 'htmlhelp':
html_theme = 'openlp_qthelp'
else:
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme # 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 # further. For a list of options available for each theme, see the
# documentation. # documentation.
#html_theme_options = {} if sys.argv[2] == 'html':
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. # Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = [] html_theme_path = [os.path.join(os.path.abspath('..'), 'themes')]
# The name for this set of Sphinx documents. If None, it defaults to # The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation". # "<project> v<release> documentation".
#html_title = None html_title = u'OpenLP 2.0 Reference Manual'
# A shorter title for the navigation bar. Default is the same as html_title. # A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None #html_short_title = None
@ -125,7 +136,7 @@ html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format. # using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y' html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to # If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities. # typographically correct entities.
@ -165,7 +176,7 @@ html_static_path = ['_static']
#html_file_suffix = None #html_file_suffix = None
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = 'OpenLPdoc' htmlhelp_basename = 'OpenLP'
# -- Options for LaTeX output -------------------------------------------------- # -- Options for LaTeX output --------------------------------------------------
@ -179,7 +190,7 @@ htmlhelp_basename = 'OpenLPdoc'
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'OpenLP.tex', u'OpenLP Documentation', ('index', 'OpenLP.tex', u'OpenLP Reference Manual',
u'Wesley Stout', 'manual'), u'Wesley Stout', 'manual'),
] ]
@ -212,6 +223,6 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'openlp', u'OpenLP Documentation', ('index', 'openlp', u'OpenLP Reference Manual',
[u'Wesley Stout'], 1) [u'Wesley Stout'], 1)
] ]

View File

@ -27,20 +27,26 @@
import os import os
import sys import sys
import logging import logging
# Import uuid now, to avoid the rare bug described in the support system:
# http://support.openlp.org/issues/102
# If https://bugs.gentoo.org/show_bug.cgi?id=317557 is fixed, the import can be
# removed.
import uuid
from optparse import OptionParser from optparse import OptionParser
from traceback import format_exception from traceback import format_exception
from subprocess import Popen, PIPE
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, check_directory_exists from openlp.core.lib import Receiver, check_directory_exists
from openlp.core.lib.ui import UiStrings
from openlp.core.resources import qInitResources from openlp.core.resources import qInitResources
from openlp.core.ui.mainwindow import MainWindow from openlp.core.ui.mainwindow import MainWindow
from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm from openlp.core.ui.firsttimelanguageform import FirstTimeLanguageForm
from openlp.core.ui.firsttimeform import FirstTimeForm from openlp.core.ui.firsttimeform import FirstTimeForm
from openlp.core.ui.exceptionform import ExceptionForm from openlp.core.ui.exceptionform import ExceptionForm
from openlp.core.ui import SplashScreen, ScreenList from openlp.core.ui import SplashScreen, ScreenList
from openlp.core.utils import AppLocation, LanguageManager, VersionThread from openlp.core.utils import AppLocation, LanguageManager, VersionThread, \
get_application_version
log = logging.getLogger() log = logging.getLogger()
@ -71,87 +77,13 @@ class OpenLP(QtGui.QApplication):
The core application class. This class inherits from Qt's QApplication The core application class. This class inherits from Qt's QApplication
class in order to provide the core of the application. class in order to provide the core of the application.
""" """
app_version = None
def get_version(self): def exec_(self):
""" """
Load and store current Application Version Override exec method to allow the shared memory to be released on exit
""" """
if self.app_version: QtGui.QApplication.exec_()
return self.app_version self.sharedMemory.detach()
if u'--dev-version' in sys.argv or u'-d' in sys.argv:
# If we're running the dev version, let's use bzr to get the version
try:
# If bzrlib is availble, use it
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'-')
self.app_version = {
u'full': full_version,
u'version': bits[0],
u'build': bits[1] if len(bits) > 1 else None
}
if self.app_version[u'build']:
log.info(
u'Openlp version %s build %s',
self.app_version[u'version'],
self.app_version[u'build']
)
else:
log.info(u'Openlp version %s' % self.app_version[u'version'])
return self.app_version
def run(self): def run(self):
""" """
@ -183,8 +115,7 @@ class OpenLP(QtGui.QApplication):
# make sure Qt really display the splash screen # make sure Qt really display the splash screen
self.processEvents() self.processEvents()
# start the main app window # start the main app window
self.mainWindow = MainWindow(screens, self.app_version, self.mainWindow = MainWindow(screens, self)
self.clipboard())
self.mainWindow.show() self.mainWindow.show()
if show_splash: if show_splash:
# now kill the splashscreen # now kill the splashscreen
@ -196,9 +127,27 @@ class OpenLP(QtGui.QApplication):
update_check = QtCore.QSettings().value( update_check = QtCore.QSettings().value(
u'general/update check', QtCore.QVariant(True)).toBool() u'general/update check', QtCore.QVariant(True)).toBool()
if update_check: if update_check:
VersionThread(self.mainWindow, self.app_version).start() VersionThread(self.mainWindow).start()
return self.exec_() return self.exec_()
def isAlreadyRunning(self):
"""
Look to see if OpenLP is already running and ask if a 2nd copy
is to be started.
"""
self.sharedMemory = QtCore.QSharedMemory('OpenLP')
if self.sharedMemory.attach():
status = QtGui.QMessageBox.critical(None,
UiStrings.Error, UiStrings.OpenLPStart,
QtGui.QMessageBox.StandardButtons(
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No))
if status == QtGui.QMessageBox.No:
return True
return False
else:
self.sharedMemory.create(1)
return False
def hookException(self, exctype, value, traceback): def hookException(self, exctype, value, traceback):
if not hasattr(self, u'mainWindow'): if not hasattr(self, u'mainWindow'):
log.exception(''.join(format_exception(exctype, value, traceback))) log.exception(''.join(format_exception(exctype, value, traceback)))
@ -271,10 +220,13 @@ def main():
qInitResources() qInitResources()
# Now create and actually run the application. # Now create and actually run the application.
app = OpenLP(qt_args) app = OpenLP(qt_args)
# Instance check
if app.isAlreadyRunning():
sys.exit()
app.setOrganizationName(u'OpenLP') app.setOrganizationName(u'OpenLP')
app.setOrganizationDomain(u'openlp.org') app.setOrganizationDomain(u'openlp.org')
app.setApplicationName(u'OpenLP') app.setApplicationName(u'OpenLP')
app.setApplicationVersion(app.get_version()[u'version']) app.setApplicationVersion(get_application_version()[u'version'])
# First time checks in settings # First time checks in settings
if not QtCore.QSettings().value(u'general/has run wizard', if not QtCore.QSettings().value(u'general/has run wizard',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():

View File

@ -1 +1 @@
1.9.2-bzr987 1.9.5-bzr1421

View File

@ -316,8 +316,11 @@ def check_directory_exists(dir):
Theme directory to make sure exists Theme directory to make sure exists
""" """
log.debug(u'check_directory_exists %s' % dir) log.debug(u'check_directory_exists %s' % dir)
if not os.path.exists(dir): try:
os.makedirs(dir) if not os.path.exists(dir):
os.makedirs(dir)
except IOError:
pass
from listwidgetwithdnd import ListWidgetWithDnD from listwidgetwithdnd import ListWidgetWithDnD
from displaytags import DisplayTags from displaytags import DisplayTags

View File

@ -101,6 +101,10 @@ class EventReceiver(QtCore.QObject):
``servicemanager_previous_item`` ``servicemanager_previous_item``
Display the previous item in the service Display the previous item in the service
``servicemanager_preview_live``
Requests a Preview item from the Service Manager to update live and
add a new item to the preview panel
``servicemanager_next_item`` ``servicemanager_next_item``
Display the next item in the service Display the next item in the service

View File

@ -32,6 +32,7 @@ from PyQt4 import QtCore
from openlp.core.lib import Receiver from openlp.core.lib import Receiver
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.core.utils import get_application_version
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -145,7 +146,10 @@ class Plugin(QtCore.QObject):
self.textStrings = {} self.textStrings = {}
self.setPluginTextStrings() self.setPluginTextStrings()
self.nameStrings = self.textStrings[StringContent.Name] self.nameStrings = self.textStrings[StringContent.Name]
self.version = version if version else u'1.9.5' if version:
self.version = version
else:
self.version = get_application_version()[u'version']
self.settingsSection = self.name.lower() self.settingsSection = self.name.lower()
self.icon = None self.icon = None
self.mediaItemClass = mediaItemClass self.mediaItemClass = mediaItemClass

View File

@ -145,7 +145,8 @@ class RenderManager(object):
else: else:
self.theme = self.service_theme self.theme = self.service_theme
else: else:
if theme: # Images have a theme of -1
if theme and theme != -1:
self.theme = theme self.theme = theme
elif theme_level == ThemeLevel.Song or \ elif theme_level == ThemeLevel.Song or \
theme_level == ThemeLevel.Service: theme_level == ThemeLevel.Service:

View File

@ -109,7 +109,9 @@ class ServiceItem(object):
self.edit_id = None self.edit_id = None
self.xml_version = None self.xml_version = None
self.start_time = 0 self.start_time = 0
self.end_time = 0
self.media_length = 0 self.media_length = 0
self.from_service = False
self._new_item() self._new_item()
def _new_item(self): def _new_item(self):
@ -261,6 +263,7 @@ class ServiceItem(object):
u'data': self.data_string, u'data': self.data_string,
u'xml_version': self.xml_version, u'xml_version': self.xml_version,
u'start_time': self.start_time, u'start_time': self.start_time,
u'end_time': self.end_time,
u'media_length': self.media_length u'media_length': self.media_length
} }
service_data = [] service_data = []
@ -307,6 +310,8 @@ class ServiceItem(object):
self.xml_version = header[u'xml_version'] self.xml_version = header[u'xml_version']
if u'start_time' in header: if u'start_time' in header:
self.start_time = header[u'start_time'] self.start_time = header[u'start_time']
if u'end_time' in header:
self.end_time = header[u'end_time']
if u'media_length' in header: if u'media_length' in header:
self.media_length = header[u'media_length'] self.media_length = header[u'media_length']
if self.service_item_type == ServiceItemType.Text: if self.service_item_type == ServiceItemType.Text:
@ -449,4 +454,3 @@ class ServiceItem(object):
return end return end
else: else:
return u'%s : %s' % (start, end) return u'%s : %s' % (start, end)

View File

@ -49,6 +49,7 @@ class UiStrings(object):
Cancel = translate('OpenLP.Ui', 'Cancel') Cancel = translate('OpenLP.Ui', 'Cancel')
CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:') CCLINumberLabel = translate('OpenLP.Ui', 'CCLI number:')
CreateService = translate('OpenLP.Ui', 'Create a new service.') CreateService = translate('OpenLP.Ui', 'Create a new service.')
Default = unicode(translate('OpenLP.Ui', 'Default'))
Delete = translate('OpenLP.Ui', '&Delete') Delete = translate('OpenLP.Ui', '&Delete')
Edit = translate('OpenLP.Ui', '&Edit') Edit = translate('OpenLP.Ui', '&Edit')
EmptyField = translate('OpenLP.Ui', 'Empty Field') EmptyField = translate('OpenLP.Ui', 'Empty Field')
@ -56,6 +57,7 @@ class UiStrings(object):
Export = translate('OpenLP.Ui', 'Export') Export = translate('OpenLP.Ui', 'Export')
FontSizePtUnit = translate('OpenLP.Ui', 'pt', FontSizePtUnit = translate('OpenLP.Ui', 'pt',
'Abbreviated font pointsize unit') 'Abbreviated font pointsize unit')
Hours = translate('OpenLP.Ui', 'h', 'The abbreviated unit for hours')
Image = translate('OpenLP.Ui', 'Image') Image = translate('OpenLP.Ui', 'Image')
Import = translate('OpenLP.Ui', 'Import') Import = translate('OpenLP.Ui', 'Import')
LengthTime = unicode(translate('OpenLP.Ui', 'Length %s')) LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
@ -63,6 +65,7 @@ class UiStrings(object):
LiveBGError = translate('OpenLP.Ui', 'Live Background Error') LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
LivePanel = translate('OpenLP.Ui', 'Live Panel') LivePanel = translate('OpenLP.Ui', 'Live Panel')
Load = translate('OpenLP.Ui', 'Load') Load = translate('OpenLP.Ui', 'Load')
Minutes = translate('OpenLP.Ui', 'm', 'The abbreviated unit for minutes')
Middle = translate('OpenLP.Ui', 'Middle') Middle = translate('OpenLP.Ui', 'Middle')
New = translate('OpenLP.Ui', 'New') New = translate('OpenLP.Ui', 'New')
NewService = translate('OpenLP.Ui', 'New Service') NewService = translate('OpenLP.Ui', 'New Service')
@ -73,6 +76,8 @@ class UiStrings(object):
NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural') NISp = translate('OpenLP.Ui', 'No Items Selected', 'Plural')
OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x') OLPV1 = translate('OpenLP.Ui', 'openlp.org 1.x')
OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0') OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0')
OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. Do you '
'wish to continue?')
OpenService = translate('OpenLP.Ui', 'Open Service') OpenService = translate('OpenLP.Ui', 'Open Service')
Preview = translate('OpenLP.Ui', 'Preview') Preview = translate('OpenLP.Ui', 'Preview')
PreviewPanel = translate('OpenLP.Ui', 'Preview Panel') PreviewPanel = translate('OpenLP.Ui', 'Preview Panel')
@ -81,7 +86,7 @@ class UiStrings(object):
ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background') ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background')
ResetBG = translate('OpenLP.Ui', 'Reset Background') ResetBG = translate('OpenLP.Ui', 'Reset Background')
ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background') ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background')
S = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds') Seconds = translate('OpenLP.Ui', 's', 'The abbreviated unit for seconds')
SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview') SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
Search = translate('OpenLP.Ui', 'Search') Search = translate('OpenLP.Ui', 'Search')
SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.') SelectDelete = translate('OpenLP.Ui', 'You must select an item to delete.')

View File

@ -28,25 +28,26 @@ from PyQt4 import QtCore, QtGui
from aboutdialog import Ui_AboutDialog from aboutdialog import Ui_AboutDialog
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.utils import get_application_version
class AboutForm(QtGui.QDialog, Ui_AboutDialog): class AboutForm(QtGui.QDialog, Ui_AboutDialog):
""" """
The About dialog The About dialog
""" """
def __init__(self, parent, applicationVersion): def __init__(self, parent):
""" """
Do some initialisation stuff Do some initialisation stuff
""" """
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, parent)
self.applicationVersion = applicationVersion applicationVersion = get_application_version()
self.setupUi(self) self.setupUi(self)
about_text = self.aboutTextEdit.toPlainText() about_text = self.aboutTextEdit.toPlainText()
about_text = about_text.replace(u'<version>', about_text = about_text.replace(u'<version>',
self.applicationVersion[u'version']) applicationVersion[u'version'])
if self.applicationVersion[u'build']: if applicationVersion[u'build']:
build_text = unicode(translate('OpenLP.AboutForm', ' build %s')) % \ build_text = unicode(translate('OpenLP.AboutForm', ' build %s')) % \
self.applicationVersion[u'build'] applicationVersion[u'build']
else: else:
build_text = u'' build_text = u''
about_text = about_text.replace(u'<revision>', build_text) about_text = about_text.replace(u'<revision>', build_text)

View File

@ -26,6 +26,8 @@
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
import sys
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.core.lib.ui import add_welcome_page from openlp.core.lib.ui import add_welcome_page
@ -77,7 +79,10 @@ class Ui_FirstTimeWizard(object):
self.imageCheckBox.setObjectName(u'imageCheckBox') self.imageCheckBox.setObjectName(u'imageCheckBox')
self.pluginLayout.addWidget(self.imageCheckBox) self.pluginLayout.addWidget(self.imageCheckBox)
self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage) self.presentationCheckBox = QtGui.QCheckBox(self.pluginPage)
self.presentationCheckBox.setChecked(True) if sys.platform == "darwin":
self.presentationCheckBox.setChecked(False)
else:
self.presentationCheckBox.setChecked(True)
self.presentationCheckBox.setObjectName(u'presentationCheckBox') self.presentationCheckBox.setObjectName(u'presentationCheckBox')
self.pluginLayout.addWidget(self.presentationCheckBox) self.pluginLayout.addWidget(self.presentationCheckBox)
self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage) self.mediaCheckBox = QtGui.QCheckBox(self.pluginPage)
@ -210,6 +215,8 @@ class Ui_FirstTimeWizard(object):
'Images')) 'Images'))
self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard', self.presentationCheckBox.setText(translate('OpenLP.FirstTimeWizard',
'Presentations')) 'Presentations'))
if sys.platform == "darwin":
self.presentationCheckBox.setEnabled(False)
self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard', self.mediaCheckBox.setText(translate('OpenLP.FirstTimeWizard',
'Media (Audio and Video)')) 'Media (Audio and Video)'))
self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard', self.remoteCheckBox.setText(translate('OpenLP.FirstTimeWizard',

View File

@ -105,6 +105,9 @@ class GeneralTab(SettingsTab):
self.saveCheckServiceCheckBox = QtGui.QCheckBox(self.settingsGroupBox) self.saveCheckServiceCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.saveCheckServiceCheckBox.setObjectName(u'saveCheckServiceCheckBox') self.saveCheckServiceCheckBox.setObjectName(u'saveCheckServiceCheckBox')
self.settingsLayout.addRow(self.saveCheckServiceCheckBox) self.settingsLayout.addRow(self.saveCheckServiceCheckBox)
self.autoUnblankCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.autoUnblankCheckBox.setObjectName(u'autoUnblankCheckBox')
self.settingsLayout.addRow(self.autoUnblankCheckBox)
self.autoPreviewCheckBox = QtGui.QCheckBox(self.settingsGroupBox) self.autoPreviewCheckBox = QtGui.QCheckBox(self.settingsGroupBox)
self.autoPreviewCheckBox.setObjectName(u'autoPreviewCheckBox') self.autoPreviewCheckBox.setObjectName(u'autoPreviewCheckBox')
self.settingsLayout.addRow(self.autoPreviewCheckBox) self.settingsLayout.addRow(self.autoPreviewCheckBox)
@ -224,6 +227,8 @@ class GeneralTab(SettingsTab):
translate('OpenLP.GeneralTab', 'Application Settings')) translate('OpenLP.GeneralTab', 'Application Settings'))
self.saveCheckServiceCheckBox.setText(translate('OpenLP.GeneralTab', self.saveCheckServiceCheckBox.setText(translate('OpenLP.GeneralTab',
'Prompt to save before starting a new service')) 'Prompt to save before starting a new service'))
self.autoUnblankCheckBox.setText(translate('OpenLP.GeneralTab',
'Unblank display when adding new live item'))
self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab', self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab',
'Automatically preview next item in service')) 'Automatically preview next item in service'))
self.timeoutLabel.setText(translate('OpenLP.GeneralTab', self.timeoutLabel.setText(translate('OpenLP.GeneralTab',
@ -262,6 +267,8 @@ class GeneralTab(SettingsTab):
u'songselect password', QtCore.QVariant(u'')).toString())) u'songselect password', QtCore.QVariant(u'')).toString()))
self.saveCheckServiceCheckBox.setChecked(settings.value(u'save prompt', self.saveCheckServiceCheckBox.setChecked(settings.value(u'save prompt',
QtCore.QVariant(False)).toBool()) QtCore.QVariant(False)).toBool())
self.autoUnblankCheckBox.setChecked(settings.value(u'auto unblank',
QtCore.QVariant(False)).toBool())
self.monitorComboBox.setCurrentIndex(self.monitorNumber) self.monitorComboBox.setCurrentIndex(self.monitorNumber)
self.displayOnMonitorCheck.setChecked(self.screens.display) self.displayOnMonitorCheck.setChecked(self.screens.display)
self.warningCheckBox.setChecked(settings.value(u'blank warning', self.warningCheckBox.setChecked(settings.value(u'blank warning',
@ -312,6 +319,8 @@ class GeneralTab(SettingsTab):
QtCore.QVariant(self.checkForUpdatesCheckBox.isChecked())) QtCore.QVariant(self.checkForUpdatesCheckBox.isChecked()))
settings.setValue(u'save prompt', settings.setValue(u'save prompt',
QtCore.QVariant(self.saveCheckServiceCheckBox.isChecked())) QtCore.QVariant(self.saveCheckServiceCheckBox.isChecked()))
settings.setValue(u'auto unblank',
QtCore.QVariant(self.autoUnblankCheckBox.isChecked()))
settings.setValue(u'auto preview', settings.setValue(u'auto preview',
QtCore.QVariant(self.autoPreviewCheckBox.isChecked())) QtCore.QVariant(self.autoPreviewCheckBox.isChecked()))
settings.setValue(u'loop delay', settings.setValue(u'loop delay',

View File

@ -367,7 +367,7 @@ class MainDisplay(DisplayWidget):
self.mediaObject.setCurrentSource(Phonon.MediaSource(videoPath)) self.mediaObject.setCurrentSource(Phonon.MediaSource(videoPath))
# Need the timer to trigger set the trigger to 200ms # Need the timer to trigger set the trigger to 200ms
# Value taken from web documentation. # Value taken from web documentation.
if self.serviceItem.start_time != 0: if self.serviceItem.end_time != 0:
self.mediaObject.setTickInterval(200) self.mediaObject.setTickInterval(200)
self.mediaObject.play() self.mediaObject.play()
self.webView.setVisible(False) self.webView.setVisible(False)
@ -401,9 +401,9 @@ class MainDisplay(DisplayWidget):
def videoTick(self, tick): def videoTick(self, tick):
""" """
Triggered on video tick every 200 milli seconds Triggered on video tick every 200 milli seconds
Will be used to manage stop time later
""" """
pass if tick > self.serviceItem.end_time * 1000:
self.videoFinished()
def isWebLoaded(self): def isWebLoaded(self):
""" """
@ -489,7 +489,11 @@ class MainDisplay(DisplayWidget):
self.footer(serviceItem.foot_text) self.footer(serviceItem.foot_text)
# if was hidden keep it hidden # if was hidden keep it hidden
if self.hideMode and self.isLive: if self.hideMode and self.isLive:
self.hideDisplay(self.hideMode) if QtCore.QSettings().value(u'general/auto unblank',
QtCore.QVariant(False)).toBool():
Receiver.send_message(u'slidecontroller_live_unblank')
else:
self.hideDisplay(self.hideMode)
# display hidden for video end we have a new item so must be shown # display hidden for video end we have a new item so must be shown
if self.videoHide and self.isLive: if self.videoHide and self.isLive:
self.videoHide = False self.videoHide = False

View File

@ -38,7 +38,7 @@ from openlp.core.ui import AboutForm, SettingsForm, ServiceManager, \
ThemeManager, SlideController, PluginForm, MediaDockManager, \ ThemeManager, SlideController, PluginForm, MediaDockManager, \
ShortcutListForm, DisplayTagForm ShortcutListForm, DisplayTagForm
from openlp.core.utils import AppLocation, add_actions, LanguageManager, \ from openlp.core.utils import AppLocation, add_actions, LanguageManager, \
ActionList ActionList, get_application_version
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -469,15 +469,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
actionList = ActionList() actionList = ActionList()
def __init__(self, screens, applicationVersion, clipboard): def __init__(self, screens, application):
""" """
This constructor sets up the interface, the various managers, and the This constructor sets up the interface, the various managers, and the
plugins. plugins.
""" """
QtGui.QMainWindow.__init__(self) QtGui.QMainWindow.__init__(self)
self.screens = screens self.screens = screens
self.applicationVersion = applicationVersion
self.clipboard = clipboard self.application = application
# Set up settings sections for the main application # Set up settings sections for the main application
# (not for use by plugins) # (not for use by plugins)
self.uiSettingsSection = u'user interface' self.uiSettingsSection = u'user interface'
@ -487,7 +487,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.serviceNotSaved = False self.serviceNotSaved = False
self.actionList = ActionList() self.actionList = ActionList()
self.settingsmanager = SettingsManager(screens) self.settingsmanager = SettingsManager(screens)
self.aboutForm = AboutForm(self, applicationVersion) self.aboutForm = AboutForm(self)
self.settingsForm = SettingsForm(self.screens, self, self) self.settingsForm = SettingsForm(self.screens, self, self)
self.displayTagForm = DisplayTagForm(self) self.displayTagForm = DisplayTagForm(self)
self.shortcutForm = ShortcutListForm(self) self.shortcutForm = ShortcutListForm(self)
@ -622,9 +622,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# Call the initialise method to setup plugins. # Call the initialise method to setup plugins.
log.info(u'initialise plugins') log.info(u'initialise plugins')
self.pluginManager.initialise_plugins() self.pluginManager.initialise_plugins()
# Once all components are initialised load the Themes
log.info(u'Load Themes')
self.themeManagerContents.loadThemes()
log.info(u'Load data from Settings') log.info(u'Load data from Settings')
if QtCore.QSettings().value(u'advanced/save current plugin', if QtCore.QSettings().value(u'advanced/save current plugin',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
@ -633,6 +630,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if savedPlugin != -1: if savedPlugin != -1:
self.MediaToolBox.setCurrentIndex(savedPlugin) self.MediaToolBox.setCurrentIndex(savedPlugin)
self.settingsForm.postSetUp() self.settingsForm.postSetUp()
# Once all components are initialised load the Themes
log.info(u'Load Themes')
self.themeManagerContents.loadThemes(True)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
def setAutoLanguage(self, value): def setAutoLanguage(self, value):
@ -651,7 +651,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
'version from http://openlp.org/.')) 'version from http://openlp.org/.'))
QtGui.QMessageBox.question(self, QtGui.QMessageBox.question(self,
translate('OpenLP.MainWindow', 'OpenLP Version Updated'), translate('OpenLP.MainWindow', 'OpenLP Version Updated'),
version_text % (version, self.applicationVersion[u'full'])) version_text % (version, get_application_version()[u'full']))
def show(self): def show(self):
""" """
@ -661,7 +661,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
if self.liveController.display.isVisible(): if self.liveController.display.isVisible():
self.liveController.display.setFocus() self.liveController.display.setFocus()
self.activateWindow() self.activateWindow()
if QtCore.QSettings().value( if len(self.application.arguments()) > 0:
args = []
for a in self.application.arguments():
args.extend([a])
self.ServiceManagerContents.loadFile(unicode(args[0]))
elif QtCore.QSettings().value(
self.generalSettingsSection + u'/auto open', self.generalSettingsSection + u'/auto open',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
self.ServiceManagerContents.loadLastFile() self.ServiceManagerContents.loadLastFile()
@ -679,7 +684,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def firstTime(self): def firstTime(self):
# Import themes if first time # Import themes if first time
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
self.themeManagerContents.firstTime()
for plugin in self.pluginManager.plugins: for plugin in self.pluginManager.plugins:
if hasattr(plugin, u'firstTime'): if hasattr(plugin, u'firstTime'):
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
@ -734,7 +738,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
""" """
Show the About form Show the About form
""" """
self.aboutForm.applicationVersion = self.applicationVersion
self.aboutForm.exec_() self.aboutForm.exec_()
def onPluginItemClicked(self): def onPluginItemClicked(self):

View File

@ -64,8 +64,7 @@ class Ui_PrintServiceDialog(object):
'Options')) 'Options'))
self.optionsButton.setToolButtonStyle( self.optionsButton.setToolButtonStyle(
QtCore.Qt.ToolButtonTextBesideIcon) QtCore.Qt.ToolButtonTextBesideIcon)
self.optionsButton.setIcon(QtGui.QIcon( self.optionsButton.setIcon(build_icon(u':/system/system_configure.png'))
build_icon(u':/system/system_configure.png')))
self.optionsButton.setCheckable(True) self.optionsButton.setCheckable(True)
self.toolbar.addWidget(self.optionsButton) self.toolbar.addWidget(self.optionsButton)
self.closeButton = self.toolbar.addAction( self.closeButton = self.toolbar.addAction(
@ -80,24 +79,23 @@ class Ui_PrintServiceDialog(object):
translate('OpenLP.PrintServiceForm', 'Copy as HTML')) translate('OpenLP.PrintServiceForm', 'Copy as HTML'))
self.toolbar.addSeparator() self.toolbar.addSeparator()
self.zoomInButton = QtGui.QToolButton(self.toolbar) self.zoomInButton = QtGui.QToolButton(self.toolbar)
self.zoomInButton.setIcon(QtGui.QIcon( self.zoomInButton.setIcon(build_icon(u':/general/general_zoom_in.png'))
build_icon(u':/general/general_zoom_in.png')))
self.zoomInButton.setToolTip(translate('OpenLP.PrintServiceForm', self.zoomInButton.setToolTip(translate('OpenLP.PrintServiceForm',
'Zoom In')) 'Zoom In'))
self.zoomInButton.setObjectName(u'zoomInButton') self.zoomInButton.setObjectName(u'zoomInButton')
self.zoomInButton.setIconSize(QtCore.QSize(22, 22)) self.zoomInButton.setIconSize(QtCore.QSize(22, 22))
self.toolbar.addWidget(self.zoomInButton) self.toolbar.addWidget(self.zoomInButton)
self.zoomOutButton = QtGui.QToolButton(self.toolbar) self.zoomOutButton = QtGui.QToolButton(self.toolbar)
self.zoomOutButton.setIcon(QtGui.QIcon( self.zoomOutButton.setIcon(
build_icon(u':/general/general_zoom_out.png'))) build_icon(u':/general/general_zoom_out.png'))
self.zoomOutButton.setToolTip(translate('OpenLP.PrintServiceForm', self.zoomOutButton.setToolTip(translate('OpenLP.PrintServiceForm',
'Zoom Out')) 'Zoom Out'))
self.zoomOutButton.setObjectName(u'zoomOutButton') self.zoomOutButton.setObjectName(u'zoomOutButton')
self.zoomOutButton.setIconSize(QtCore.QSize(22, 22)) self.zoomOutButton.setIconSize(QtCore.QSize(22, 22))
self.toolbar.addWidget(self.zoomOutButton) self.toolbar.addWidget(self.zoomOutButton)
self.zoomOriginalButton = QtGui.QToolButton(self.toolbar) self.zoomOriginalButton = QtGui.QToolButton(self.toolbar)
self.zoomOriginalButton.setIcon(QtGui.QIcon( self.zoomOriginalButton.setIcon(
build_icon(u':/general/general_zoom_original.png'))) build_icon(u':/general/general_zoom_original.png'))
self.zoomOriginalButton.setToolTip(translate('OpenLP.PrintServiceForm', self.zoomOriginalButton.setToolTip(translate('OpenLP.PrintServiceForm',
'Zoom Original')) 'Zoom Original'))
self.zoomOriginalButton.setObjectName(u'zoomOriginalButton') self.zoomOriginalButton.setObjectName(u'zoomOriginalButton')

View File

@ -33,12 +33,12 @@ from openlp.core.ui.printservicedialog import Ui_PrintServiceDialog, ZoomSize
class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog): class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
def __init__(self, parent, serviceManager): def __init__(self, mainWindow, serviceManager):
""" """
Constructor Constructor
""" """
QtGui.QDialog.__init__(self, parent) QtGui.QDialog.__init__(self, mainWindow)
self.parent = parent self.mainWindow = mainWindow
self.serviceManager = serviceManager self.serviceManager = serviceManager
self.printer = QtGui.QPrinter() self.printer = QtGui.QPrinter()
self.printDialog = QtGui.QPrintDialog(self.printer, self) self.printDialog = QtGui.QPrintDialog(self.printer, self)
@ -134,9 +134,12 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
item.notes.replace(u'\n', u'<br />')) item.notes.replace(u'\n', u'<br />'))
# Add play length of media files. # Add play length of media files.
if item.is_media() and self.metaDataCheckBox.isChecked(): if item.is_media() and self.metaDataCheckBox.isChecked():
tme = item.media_length
if item.end_time > 0:
tme = item.end_time - item.start_time
text += u'<p><strong>%s</strong> %s</p>' % (translate( text += u'<p><strong>%s</strong> %s</p>' % (translate(
'OpenLP.ServiceManager', u'Playing time:'), 'OpenLP.ServiceManager', u'Playing time:'),
unicode(datetime.timedelta(seconds=item.media_length))) unicode(datetime.timedelta(seconds=tme)))
if self.footerTextEdit.toPlainText(): if self.footerTextEdit.toPlainText():
text += u'<h4>%s</h4>%s' % (translate('OpenLP.ServiceManager', text += u'<h4>%s</h4>%s' % (translate('OpenLP.ServiceManager',
u'Custom Service Notes:'), self.footerTextEdit.toPlainText()) u'Custom Service Notes:'), self.footerTextEdit.toPlainText())
@ -181,13 +184,14 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
""" """
Copies the display text to the clipboard as plain text Copies the display text to the clipboard as plain text
""" """
self.parent.clipboard.setText(self.document.toPlainText()) self.mainWindow.application.clipboard.setText(
self.document.toPlainText())
def copyHtmlText(self): def copyHtmlText(self):
""" """
Copies the display text to the clipboard as Html Copies the display text to the clipboard as Html
""" """
self.parent.clipboard.setText(self.document.toHtml()) self.mainWindow.application.clipboard.setText(self.document.toHtml())
def printServiceOrder(self): def printServiceOrder(self):
""" """

View File

@ -141,4 +141,3 @@ class ServiceItemEditForm(QtGui.QDialog, Ui_ServiceItemEditDialog):
else: else:
self.upButton.setEnabled(True) self.upButton.setEnabled(True)
self.deleteButton.setEnabled(True) self.deleteButton.setEnabled(True)

View File

@ -231,13 +231,15 @@ class ServiceManager(QtGui.QWidget):
QtCore.QObject.connect(self.themeComboBox, QtCore.QObject.connect(self.themeComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onThemeComboBoxSelected) QtCore.SIGNAL(u'activated(int)'), self.onThemeComboBoxSelected)
QtCore.QObject.connect(self.serviceManagerList, QtCore.QObject.connect(self.serviceManagerList,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.makeLive) QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onMakeLive)
QtCore.QObject.connect(self.serviceManagerList, QtCore.QObject.connect(self.serviceManagerList,
QtCore.SIGNAL(u'itemCollapsed(QTreeWidgetItem*)'), self.collapsed) QtCore.SIGNAL(u'itemCollapsed(QTreeWidgetItem*)'), self.collapsed)
QtCore.QObject.connect(self.serviceManagerList, QtCore.QObject.connect(self.serviceManagerList,
QtCore.SIGNAL(u'itemExpanded(QTreeWidgetItem*)'), self.expanded) QtCore.SIGNAL(u'itemExpanded(QTreeWidgetItem*)'), self.expanded)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList) QtCore.SIGNAL(u'theme_update_list'), self.updateThemeList)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'servicemanager_preview_live'), self.previewLive)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'servicemanager_next_item'), self.nextItem) QtCore.SIGNAL(u'servicemanager_next_item'), self.nextItem)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
@ -481,28 +483,30 @@ class ServiceManager(QtGui.QWidget):
# Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be # Usual Zip file cannot exceed 2GiB, file with Zip64 cannot be
# extracted using unzip in UNIX. # extracted using unzip in UNIX.
allow_zip_64 = (total_size > 2147483648 + len(service_content)) allow_zip_64 = (total_size > 2147483648 + len(service_content))
log.debug(u'ServiceManager.saveFile - allowZip64 is %s' % log.debug(u'ServiceManager.saveFile - allowZip64 is %s' % allow_zip_64)
allow_zip_64)
zip = None zip = None
success = True
try: try:
zip = zipfile.ZipFile(path_file_name, 'w', zipfile.ZIP_STORED, zip = zipfile.ZipFile(path_file_name, 'w', zipfile.ZIP_STORED,
allow_zip_64) allow_zip_64)
# First we add service contents. # First we add service contents.
# We save ALL filenames into ZIP using UTF-8. # We save ALL filenames into ZIP using UTF-8.
zip.writestr(service_file_name.encode(u'utf-8'), zip.writestr(service_file_name.encode(u'utf-8'), service_content)
service_content)
# Finally add all the listed media files. # Finally add all the listed media files.
for path_from in write_list: for path_from in write_list:
zip.write(path_from, path_from.encode(u'utf-8')) zip.write(path_from, path_from.encode(u'utf-8'))
except IOError: except IOError:
log.exception(u'Failed to save service to disk') log.exception(u'Failed to save service to disk')
return False success = False
finally: finally:
if zip: if zip:
zip.close() zip.close()
self.mainwindow.addRecentFile(path_file_name) if success:
self.setModified(False) self.mainwindow.addRecentFile(path_file_name)
return True self.setModified(False)
else:
delete_file(path_file_name)
return success
def saveFileAs(self): def saveFileAs(self):
""" """
@ -527,8 +531,9 @@ class ServiceManager(QtGui.QWidget):
def loadFile(self, fileName): def loadFile(self, fileName):
if not fileName: if not fileName:
return False return False
else: fileName = unicode(fileName)
fileName = unicode(fileName) if not os.path.exists(fileName):
return False
zip = None zip = None
fileTo = None fileTo = None
try: try:
@ -558,6 +563,7 @@ class ServiceManager(QtGui.QWidget):
self.newFile() self.newFile()
for item in items: for item in items:
serviceItem = ServiceItem() serviceItem = ServiceItem()
serviceItem.from_service = True
serviceItem.render_manager = self.mainwindow.renderManager serviceItem.render_manager = self.mainwindow.renderManager
serviceItem.set_from_service(item, self.servicePath) serviceItem.set_from_service(item, self.servicePath)
self.validateItem(serviceItem) self.validateItem(serviceItem)
@ -566,24 +572,27 @@ class ServiceManager(QtGui.QWidget):
Receiver.send_message(u'%s_service_load' % Receiver.send_message(u'%s_service_load' %
serviceItem.name.lower(), serviceItem) serviceItem.name.lower(), serviceItem)
delete_file(p_file) delete_file(p_file)
self.setFileName(fileName)
self.mainwindow.addRecentFile(fileName)
self.setModified(False)
QtCore.QSettings().setValue(
'service/last file', QtCore.QVariant(fileName))
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
else: else:
critical_error_message_box( critical_error_message_box(
message=translate('OpenLP.ServiceManager', message=translate('OpenLP.ServiceManager',
'File is not a valid service.')) 'File is not a valid service.'))
log.exception(u'File contains no service data') log.exception(u'File contains no service data')
except (IOError, NameError): except (IOError, NameError, zipfile.BadZipfile):
critical_error_message_box(
message=translate('OpenLP.ServiceManager',
'File could not be opened because it is corrupt.'))
log.exception(u'Problem loading service file %s' % fileName) log.exception(u'Problem loading service file %s' % fileName)
finally: finally:
if fileTo: if fileTo:
fileTo.close() fileTo.close()
if zip: if zip:
zip.close() zip.close()
self.setFileName(fileName)
self.mainwindow.addRecentFile(fileName)
self.setModified(False)
QtCore.QSettings(). \
setValue(u'service/last file', QtCore.QVariant(fileName))
def loadLastFile(self): def loadLastFile(self):
""" """
@ -652,10 +661,6 @@ class ServiceManager(QtGui.QWidget):
item = self.findServiceItem()[0] item = self.findServiceItem()[0]
self.startTimeForm.item = self.serviceItems[item] self.startTimeForm.item = self.serviceItems[item]
if self.startTimeForm.exec_(): if self.startTimeForm.exec_():
self.serviceItems[item][u'service_item'].start_time = \
self.startTimeForm.hourSpinBox.value() * 3600 + \
self.startTimeForm.minuteSpinBox.value() * 60 + \
self.startTimeForm.secondSpinBox.value()
self.repaintServiceList(item, -1) self.repaintServiceList(item, -1)
def onServiceItemEditForm(self): def onServiceItemEditForm(self):
@ -666,6 +671,19 @@ class ServiceManager(QtGui.QWidget):
self.addServiceItem(self.serviceItemEditForm.getServiceItem(), self.addServiceItem(self.serviceItemEditForm.getServiceItem(),
replace=True, expand=self.serviceItems[item][u'expanded']) replace=True, expand=self.serviceItems[item][u'expanded'])
def previewLive(self, message):
"""
Called by the SlideController to request a preview item be made live
and allows the next preview to be updated if relevent.
"""
id, row = message.split(u':')
for sitem in self.serviceItems:
if sitem[u'service_item']._uuid == id:
item = self.serviceManagerList.topLevelItem(sitem[u'order'] - 1)
self.serviceManagerList.setCurrentItem(item)
self.makeLive(int(row))
return
def nextItem(self): def nextItem(self):
""" """
Called by the SlideController to select the next service item. Called by the SlideController to select the next service item.
@ -1021,6 +1039,7 @@ class ServiceManager(QtGui.QWidget):
if expand is None: if expand is None:
expand = self.expandTabs expand = self.expandTabs
item.render() item.render()
item.from_service = True
if replace: if replace:
sitem, child = self.findServiceItem() sitem, child = self.findServiceItem()
item.merge(self.serviceItems[sitem][u'service_item']) item.merge(self.serviceItems[sitem][u'service_item'])
@ -1075,11 +1094,24 @@ class ServiceManager(QtGui.QWidget):
else: else:
return self.serviceItems[item][u'service_item'] return self.serviceItems[item][u'service_item']
def makeLive(self): def onMakeLive(self):
"""
Send the current item to the Live slide controller but triggered
by a tablewidget click event.
"""
self.makeLive()
def makeLive(self, row=-1):
""" """
Send the current item to the Live slide controller Send the current item to the Live slide controller
``row``
Row number to be displayed if from preview.
-1 is passed if the value is not set
""" """
item, child = self.findServiceItem() item, child = self.findServiceItem()
if row != -1:
child = row
if self.serviceItems[item][u'service_item'].is_valid: if self.serviceItems[item][u'service_item'].is_valid:
self.mainwindow.liveController.addServiceManagerItem( self.mainwindow.liveController.addServiceManagerItem(
self.serviceItems[item][u'service_item'], child) self.serviceItems[item][u'service_item'], child)

View File

@ -46,6 +46,7 @@ class SlideList(QtGui.QTableWidget):
QtGui.QTableWidget.__init__(self, parent.controller) QtGui.QTableWidget.__init__(self, parent.controller)
self.parent = parent self.parent = parent
class SlideController(QtGui.QWidget): class SlideController(QtGui.QWidget):
""" """
SlideController is the slide controller widget. This widget is what the SlideController is the slide controller widget. This widget is what the
@ -184,7 +185,7 @@ class SlideController(QtGui.QWidget):
self.delaySpinBox.setMinimum(1) self.delaySpinBox.setMinimum(1)
self.delaySpinBox.setMaximum(180) self.delaySpinBox.setMaximum(180)
self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox) self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox)
self.delaySpinBox.setSuffix(UiStrings.S) self.delaySpinBox.setSuffix(UiStrings.Seconds)
self.delaySpinBox.setToolTip(translate('OpenLP.SlideController', self.delaySpinBox.setToolTip(translate('OpenLP.SlideController',
'Delay between slides in seconds')) 'Delay between slides in seconds'))
else: else:
@ -1013,8 +1014,12 @@ class SlideController(QtGui.QWidget):
""" """
row = self.previewListWidget.currentRow() row = self.previewListWidget.currentRow()
if row > -1 and row < self.previewListWidget.rowCount(): if row > -1 and row < self.previewListWidget.rowCount():
self.parent.liveController.addServiceManagerItem( if self.serviceItem.from_service:
self.serviceItem, row) Receiver.send_message('servicemanager_preview_live',
u'%s:%s' % (self.serviceItem._uuid, row))
else:
self.parent.liveController.addServiceManagerItem(
self.serviceItem, row)
def onMediaStart(self, item): def onMediaStart(self, item):
""" """

View File

@ -32,39 +32,90 @@ from openlp.core.lib.ui import UiStrings, create_accept_reject_button_box
class Ui_StartTimeDialog(object): class Ui_StartTimeDialog(object):
def setupUi(self, StartTimeDialog): def setupUi(self, StartTimeDialog):
StartTimeDialog.setObjectName(u'StartTimeDialog') StartTimeDialog.setObjectName(u'StartTimeDialog')
StartTimeDialog.resize(300, 10) StartTimeDialog.resize(350, 10)
self.dialogLayout = QtGui.QGridLayout(StartTimeDialog) self.dialogLayout = QtGui.QGridLayout(StartTimeDialog)
self.dialogLayout.setObjectName(u'dialogLayout') self.dialogLayout.setObjectName(u'dialogLayout')
self.startLabel = QtGui.QLabel(StartTimeDialog)
self.startLabel.setObjectName(u'startLabel')
self.startLabel.setAlignment(QtCore.Qt.AlignHCenter)
self.dialogLayout.addWidget(self.startLabel, 0, 1, 1, 1)
self.finishLabel = QtGui.QLabel(StartTimeDialog)
self.finishLabel.setObjectName(u'finishLabel')
self.finishLabel.setAlignment(QtCore.Qt.AlignHCenter)
self.dialogLayout.addWidget(self.finishLabel, 0, 2, 1, 1)
self.lengthLabel = QtGui.QLabel(StartTimeDialog)
self.lengthLabel.setObjectName(u'startLabel')
self.lengthLabel.setAlignment(QtCore.Qt.AlignHCenter)
self.dialogLayout.addWidget(self.lengthLabel, 0, 3, 1, 1)
self.hourLabel = QtGui.QLabel(StartTimeDialog) self.hourLabel = QtGui.QLabel(StartTimeDialog)
self.hourLabel.setObjectName("hourLabel") self.hourLabel.setObjectName(u'hourLabel')
self.dialogLayout.addWidget(self.hourLabel, 0, 0, 1, 1) self.dialogLayout.addWidget(self.hourLabel, 1, 0, 1, 1)
self.hourSpinBox = QtGui.QSpinBox(StartTimeDialog) self.hourSpinBox = QtGui.QSpinBox(StartTimeDialog)
self.hourSpinBox.setObjectName("hourSpinBox") self.hourSpinBox.setObjectName(u'hourSpinBox')
self.dialogLayout.addWidget(self.hourSpinBox, 0, 1, 1, 1) self.hourSpinBox.setMinimum(0)
self.hourSpinBox.setMaximum(4)
self.dialogLayout.addWidget(self.hourSpinBox, 1, 1, 1, 1)
self.hourFinishSpinBox = QtGui.QSpinBox(StartTimeDialog)
self.hourFinishSpinBox.setObjectName(u'hourFinishSpinBox')
self.hourFinishSpinBox.setMinimum(0)
self.hourFinishSpinBox.setMaximum(4)
self.dialogLayout.addWidget(self.hourFinishSpinBox, 1, 2, 1, 1)
self.hourFinishLabel = QtGui.QLabel(StartTimeDialog)
self.hourFinishLabel.setObjectName(u'hourLabel')
self.hourFinishLabel.setAlignment(QtCore.Qt.AlignRight)
self.dialogLayout.addWidget(self.hourFinishLabel, 1, 3, 1, 1)
self.minuteLabel = QtGui.QLabel(StartTimeDialog) self.minuteLabel = QtGui.QLabel(StartTimeDialog)
self.minuteLabel.setObjectName("minuteLabel") self.minuteLabel.setObjectName(u'minuteLabel')
self.dialogLayout.addWidget(self.minuteLabel, 1, 0, 1, 1) self.dialogLayout.addWidget(self.minuteLabel, 2, 0, 1, 1)
self.minuteSpinBox = QtGui.QSpinBox(StartTimeDialog) self.minuteSpinBox = QtGui.QSpinBox(StartTimeDialog)
self.minuteSpinBox.setObjectName("minuteSpinBox") self.minuteSpinBox.setObjectName(u'minuteSpinBox')
self.dialogLayout.addWidget(self.minuteSpinBox, 1, 1, 1, 1) self.minuteSpinBox.setMinimum(0)
self.minuteSpinBox.setMaximum(59)
self.dialogLayout.addWidget(self.minuteSpinBox, 2, 1, 1, 1)
self.minuteFinishSpinBox = QtGui.QSpinBox(StartTimeDialog)
self.minuteFinishSpinBox.setObjectName(u'minuteFinishSpinBox')
self.minuteFinishSpinBox.setMinimum(0)
self.minuteFinishSpinBox.setMaximum(59)
self.dialogLayout.addWidget(self.minuteFinishSpinBox, 2, 2, 1, 1)
self.minuteFinishLabel = QtGui.QLabel(StartTimeDialog)
self.minuteFinishLabel.setObjectName(u'minuteLabel')
self.minuteFinishLabel.setAlignment(QtCore.Qt.AlignRight)
self.dialogLayout.addWidget(self.minuteFinishLabel, 2, 3, 1, 1)
self.secondLabel = QtGui.QLabel(StartTimeDialog) self.secondLabel = QtGui.QLabel(StartTimeDialog)
self.secondLabel.setObjectName("secondLabel") self.secondLabel.setObjectName(u'secondLabel')
self.dialogLayout.addWidget(self.secondLabel, 2, 0, 1, 1) self.dialogLayout.addWidget(self.secondLabel, 3, 0, 1, 1)
self.secondSpinBox = QtGui.QSpinBox(StartTimeDialog) self.secondSpinBox = QtGui.QSpinBox(StartTimeDialog)
self.secondSpinBox.setObjectName("secondSpinBox") self.secondSpinBox.setObjectName(u'secondSpinBox')
self.dialogLayout.addWidget(self.secondSpinBox, 2, 1, 1, 1) self.secondSpinBox.setMinimum(0)
self.secondSpinBox.setMaximum(59)
self.secondFinishSpinBox = QtGui.QSpinBox(StartTimeDialog)
self.secondFinishSpinBox.setObjectName(u'secondFinishSpinBox')
self.secondFinishSpinBox.setMinimum(0)
self.secondFinishSpinBox.setMaximum(59)
self.dialogLayout.addWidget(self.secondFinishSpinBox, 3, 2, 1, 1)
self.secondFinishLabel = QtGui.QLabel(StartTimeDialog)
self.secondFinishLabel.setObjectName(u'secondLabel')
self.secondFinishLabel.setAlignment(QtCore.Qt.AlignRight)
self.dialogLayout.addWidget(self.secondFinishLabel, 3, 3, 1, 1)
self.dialogLayout.addWidget(self.secondSpinBox, 3, 1, 1, 1)
self.buttonBox = create_accept_reject_button_box(StartTimeDialog, True) self.buttonBox = create_accept_reject_button_box(StartTimeDialog, True)
self.dialogLayout.addWidget(self.buttonBox, 4, 0, 1, 2) self.dialogLayout.addWidget(self.buttonBox, 5, 2, 1, 2)
self.retranslateUi(StartTimeDialog) self.retranslateUi(StartTimeDialog)
self.setMaximumHeight(self.sizeHint().height()) self.setMaximumHeight(self.sizeHint().height())
QtCore.QMetaObject.connectSlotsByName(StartTimeDialog) QtCore.QMetaObject.connectSlotsByName(StartTimeDialog)
def retranslateUi(self, StartTimeDialog): def retranslateUi(self, StartTimeDialog):
self.setWindowTitle(translate('OpenLP.StartTimeForm', self.setWindowTitle(translate('OpenLP.StartTimeForm',
'Item Start Time')) 'Item Start and Finish Time'))
self.hourSpinBox.setSuffix(UiStrings.Hours)
self.minuteSpinBox.setSuffix(UiStrings.Minutes)
self.secondSpinBox.setSuffix(UiStrings.Seconds)
self.hourFinishSpinBox.setSuffix(UiStrings.Hours)
self.minuteFinishSpinBox.setSuffix(UiStrings.Minutes)
self.secondFinishSpinBox.setSuffix(UiStrings.Seconds)
self.hourLabel.setText(translate('OpenLP.StartTimeForm', 'Hours:')) self.hourLabel.setText(translate('OpenLP.StartTimeForm', 'Hours:'))
self.hourSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 'h'))
self.minuteSpinBox.setSuffix(translate('OpenLP.StartTimeForm', 'm'))
self.secondSpinBox.setSuffix(UiStrings.S)
self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:')) self.minuteLabel.setText(translate('OpenLP.StartTimeForm', 'Minutes:'))
self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:')) self.secondLabel.setText(translate('OpenLP.StartTimeForm', 'Seconds:'))
self.startLabel.setText(translate('OpenLP.StartTimeForm', 'Start'))
self.finishLabel.setText(translate('OpenLP.StartTimeForm', 'Finish'))
self.lengthLabel.setText(translate('OpenLP.StartTimeForm', 'Length'))

View File

@ -28,6 +28,9 @@ from PyQt4 import QtGui
from starttimedialog import Ui_StartTimeDialog from starttimedialog import Ui_StartTimeDialog
from openlp.core.lib import translate
from openlp.core.lib.ui import UiStrings, critical_error_message_box
class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog): class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
""" """
The exception dialog The exception dialog
@ -40,13 +43,51 @@ class StartTimeForm(QtGui.QDialog, Ui_StartTimeDialog):
""" """
Run the Dialog with correct heading. Run the Dialog with correct heading.
""" """
seconds = self.item[u'service_item'].start_time hour, minutes, seconds = self._time_split(
self.item[u'service_item'].start_time)
self.hourSpinBox.setValue(hour)
self.minuteSpinBox.setValue(minutes)
self.secondSpinBox.setValue(seconds)
hours, minutes, seconds = self._time_split(
self.item[u'service_item'].media_length)
self.hourFinishSpinBox.setValue(hours)
self.minuteFinishSpinBox.setValue(minutes)
self.secondFinishSpinBox.setValue(seconds)
self.hourFinishLabel.setText(u'%s%s' % (unicode(hour), UiStrings.Hours))
self.minuteFinishLabel.setText(u'%s%s' %
(unicode(minutes), UiStrings.Minutes))
self.secondFinishLabel.setText(u'%s%s' %
(unicode(seconds), UiStrings.Seconds))
return QtGui.QDialog.exec_(self)
def accept(self):
start = self.hourSpinBox.value() * 3600 + \
self.minuteSpinBox.value() * 60 + \
self.secondSpinBox.value()
end = self.hourFinishSpinBox.value() * 3600 + \
self.minuteFinishSpinBox.value() * 60 + \
self.secondFinishSpinBox.value()
if end > self.item[u'service_item'].media_length:
critical_error_message_box(
title=translate('OpenLP.StartTimeForm',
'Time Validation Error'),
message=translate('OpenLP.StartTimeForm',
'End time is set after the end of the media item'))
return
elif start > end:
critical_error_message_box(
title=translate('OpenLP.StartTimeForm',
'Time Validation Error'),
message=translate('OpenLP.StartTimeForm',
'Start time is after the End Time of the media item'))
return
self.item[u'service_item'].start_time = start
self.item[u'service_item'].end_time = end
return QtGui.QDialog.accept(self)
def _time_split(self, seconds):
hours = seconds / 3600 hours = seconds / 3600
seconds -= 3600 * hours seconds -= 3600 * hours
minutes = seconds / 60 minutes = seconds / 60
seconds -= 60 * minutes seconds -= 60 * minutes
self.hourSpinBox.setValue(hours) return hours, minutes, seconds
self.minuteSpinBox.setValue(minutes)
self.secondSpinBox.setValue(seconds)
return QtGui.QDialog.exec_(self)

View File

@ -156,10 +156,9 @@ class ThemeManager(QtGui.QWidget):
file = os.path.join(self.path, file).encode(encoding) file = os.path.join(self.path, file).encode(encoding)
self.unzipTheme(file, self.path) self.unzipTheme(file, self.path)
delete_file(file) delete_file(file)
self.loadThemes()
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
def configUpdated(self, firstTime=False): def configUpdated(self):
""" """
Triggered when Config dialog is updated. Triggered when Config dialog is updated.
""" """
@ -433,7 +432,7 @@ class ThemeManager(QtGui.QWidget):
self.loadThemes() self.loadThemes()
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
def loadThemes(self): def loadThemes(self, firstTime=False):
""" """
Loads the theme lists and triggers updates accross the whole system Loads the theme lists and triggers updates accross the whole system
using direct calls or core functions and events for the plugins. using direct calls or core functions and events for the plugins.
@ -443,31 +442,44 @@ class ThemeManager(QtGui.QWidget):
self.themelist = [] self.themelist = []
self.themeListWidget.clear() self.themeListWidget.clear()
dirList = os.listdir(self.path) dirList = os.listdir(self.path)
dirList.sort() files = SettingsManager.get_files(self.settingsSection, u'.png')
for name in dirList: if firstTime:
if name.endswith(u'.png'): self.firstTime()
# check to see file is in theme root directory # No themes have been found so create one
theme = os.path.join(self.path, name) if len(files) == 0:
if os.path.exists(theme): theme = ThemeXML()
textName = os.path.splitext(name)[0] theme.theme_name = UiStrings.Default
if textName == self.global_theme: self._writeTheme(theme, None, None)
name = unicode(translate('OpenLP.ThemeManager', QtCore.QSettings().setValue(
'%s (default)')) % textName self.settingsSection + u'/global theme',
else: QtCore.QVariant(theme.theme_name))
name = textName self.configUpdated()
thumb = os.path.join(self.thumbPath, u'%s.png' % textName) files = SettingsManager.get_files(self.settingsSection, u'.png')
item_name = QtGui.QListWidgetItem(name) files.sort()
if os.path.exists(thumb): # now process the file list of png files
icon = build_icon(thumb) for name in files:
else: # check to see file is in theme root directory
icon = build_icon(theme) theme = os.path.join(self.path, name)
pixmap = icon.pixmap(QtCore.QSize(88, 50)) if os.path.exists(theme):
pixmap.save(thumb, u'png') textName = os.path.splitext(name)[0]
item_name.setIcon(icon) if textName == self.global_theme:
item_name.setData(QtCore.Qt.UserRole, name = unicode(translate('OpenLP.ThemeManager',
QtCore.QVariant(textName)) '%s (default)')) % textName
self.themeListWidget.addItem(item_name) else:
self.themelist.append(textName) name = textName
thumb = os.path.join(self.thumbPath, u'%s.png' % textName)
item_name = QtGui.QListWidgetItem(name)
if os.path.exists(thumb):
icon = build_icon(thumb)
else:
icon = build_icon(theme)
pixmap = icon.pixmap(QtCore.QSize(88, 50))
pixmap.save(thumb, u'png')
item_name.setIcon(icon)
item_name.setData(QtCore.Qt.UserRole,
QtCore.QVariant(textName))
self.themeListWidget.addItem(item_name)
self.themelist.append(textName)
self._pushThemes() self._pushThemes()
def _pushThemes(self): def _pushThemes(self):

View File

@ -33,6 +33,7 @@ import sys
import time import time
import urllib2 import urllib2
from datetime import datetime from datetime import datetime
from subprocess import Popen, PIPE
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
@ -44,9 +45,10 @@ if sys.platform != u'win32' and sys.platform != u'darwin':
XDG_BASE_AVAILABLE = False XDG_BASE_AVAILABLE = False
import openlp import openlp
from openlp.core.lib import Receiver, translate from openlp.core.lib import Receiver, translate, check_directory_exists
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
APPLICATION_VERSION = {}
IMAGES_FILTER = None IMAGES_FILTER = None
UNO_CONNECTION_TYPE = u'pipe' UNO_CONNECTION_TYPE = u'pipe'
#UNO_CONNECTION_TYPE = u'socket' #UNO_CONNECTION_TYPE = u'socket'
@ -56,9 +58,8 @@ class VersionThread(QtCore.QThread):
A special Qt thread class to fetch the version of OpenLP from the website. A special Qt thread class to fetch the version of OpenLP from the website.
This is threaded so that it doesn't affect the loading time of OpenLP. This is threaded so that it doesn't affect the loading time of OpenLP.
""" """
def __init__(self, parent, app_version): def __init__(self, parent):
QtCore.QThread.__init__(self, parent) QtCore.QThread.__init__(self, parent)
self.app_version = app_version
self.version_splitter = re.compile( self.version_splitter = re.compile(
r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?') r'([0-9]+).([0-9]+).([0-9]+)(?:-bzr([0-9]+))?')
@ -68,7 +69,8 @@ class VersionThread(QtCore.QThread):
""" """
time.sleep(1) time.sleep(1)
Receiver.send_message(u'maindisplay_blank_check') Receiver.send_message(u'maindisplay_blank_check')
version = check_latest_version(self.app_version) app_version = get_application_version()
version = check_latest_version(app_version)
remote_version = {} remote_version = {}
local_version = {} local_version = {}
match = self.version_splitter.match(version) match = self.version_splitter.match(version)
@ -80,7 +82,7 @@ class VersionThread(QtCore.QThread):
remote_version[u'revision'] = int(match.group(4)) remote_version[u'revision'] = int(match.group(4))
else: else:
return return
match = self.version_splitter.match(self.app_version[u'full']) match = self.version_splitter.match(app_version[u'full'])
if match: if match:
local_version[u'major'] = int(match.group(1)) local_version[u'major'] = int(match.group(1))
local_version[u'minor'] = int(match.group(2)) local_version[u'minor'] = int(match.group(2))
@ -146,8 +148,7 @@ class AppLocation(object):
Return the path OpenLP stores all its data under. Return the path OpenLP stores all its data under.
""" """
path = AppLocation.get_directory(AppLocation.DataDir) path = AppLocation.get_directory(AppLocation.DataDir)
if not os.path.exists(path): check_directory_exists(path)
os.makedirs(path)
return path return path
@staticmethod @staticmethod
@ -157,8 +158,7 @@ class AppLocation(object):
""" """
data_path = AppLocation.get_data_path() data_path = AppLocation.get_data_path()
path = os.path.join(data_path, section) path = os.path.join(data_path, section)
if not os.path.exists(path): check_directory_exists(path)
os.makedirs(path)
return path return path
def _get_os_dir_path(dir_type): def _get_os_dir_path(dir_type):
@ -208,6 +208,85 @@ def _get_frozen_path(frozen_option, non_frozen_option):
return frozen_option return frozen_option
return non_frozen_option return non_frozen_option
def get_application_version():
"""
Returns the application version of the running instance of OpenLP::
{u'full': u'1.9.4-bzr1249', u'version': u'1.9.4', u'build': u'bzr1249'}
"""
global APPLICATION_VERSION
if APPLICATION_VERSION:
return APPLICATION_VERSION
if u'--dev-version' in sys.argv or u'-d' in sys.argv:
# If we're running the dev version, let's use bzr to get the version.
try:
# If bzrlib is available, 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'-')
APPLICATION_VERSION = {
u'full': full_version,
u'version': bits[0],
u'build': bits[1] if len(bits) > 1 else None
}
if APPLICATION_VERSION[u'build']:
log.info(u'Openlp version %s build %s',
APPLICATION_VERSION[u'version'], APPLICATION_VERSION[u'build'])
else:
log.info(u'Openlp version %s' % APPLICATION_VERSION[u'version'])
return APPLICATION_VERSION
def check_latest_version(current_version): def check_latest_version(current_version):
""" """
Check the latest version of OpenLP against the version file on the OpenLP Check the latest version of OpenLP against the version file on the OpenLP

View File

@ -91,7 +91,7 @@ class LanguageManager(object):
""" """
Retrieve a saved language to use from settings Retrieve a saved language to use from settings
""" """
settings = QtCore.QSettings(u'OpenLP', u'OpenLP') settings = QtCore.QSettings()
language = unicode(settings.value( language = unicode(settings.value(
u'general/language', QtCore.QVariant(u'[en]')).toString()) u'general/language', QtCore.QVariant(u'[en]')).toString())
log.info(u'Language file: \'%s\' Loaded from conf file' % language) log.info(u'Language file: \'%s\' Loaded from conf file' % language)

View File

@ -112,7 +112,7 @@ class AlertsTab(SettingsTab):
self.FontSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit) self.FontSizeSpinBox.setSuffix(UiStrings.FontSizePtUnit)
self.TimeoutLabel.setText( self.TimeoutLabel.setText(
translate('AlertsPlugin.AlertsTab', 'Alert timeout:')) translate('AlertsPlugin.AlertsTab', 'Alert timeout:'))
self.TimeoutSpinBox.setSuffix(UiStrings.S) self.TimeoutSpinBox.setSuffix(UiStrings.Seconds)
self.PreviewGroupBox.setTitle(UiStrings.Preview) self.PreviewGroupBox.setTitle(UiStrings.Preview)
self.FontPreview.setText(UiStrings.OLPV2) self.FontPreview.setText(UiStrings.OLPV2)

View File

@ -551,64 +551,52 @@ class BibleMediaItem(MediaManagerItem):
further action is saved for/in each row. further action is saved for/in each row.
""" """
verse_separator = get_reference_match(u'sep_v_display') verse_separator = get_reference_match(u'sep_v_display')
version = self.parent.manager.get_meta_data(bible, u'Version') version = self.parent.manager.get_meta_data(bible, u'Version').value
copyright = self.parent.manager.get_meta_data(bible, u'Copyright') copyright = self.parent.manager.get_meta_data(bible, u'Copyright').value
permissions = self.parent.manager.get_meta_data(bible, u'Permissions') permissions = \
self.parent.manager.get_meta_data(bible, u'Permissions').value
second_version = u''
second_copyright = u''
second_permissions = u''
if second_bible: if second_bible:
second_version = self.parent.manager.get_meta_data(second_bible, second_version = self.parent.manager.get_meta_data(
u'Version') second_bible, u'Version').value
second_copyright = self.parent.manager.get_meta_data(second_bible, second_copyright = self.parent.manager.get_meta_data(
u'Copyright') second_bible, u'Copyright').value
second_permissions = self.parent.manager.get_meta_data(second_bible, second_permissions = self.parent.manager.get_meta_data(
u'Permissions') second_bible, u'Permissions').value
if not second_permissions:
second_permissions = u''
for count, verse in enumerate(self.search_results): for count, verse in enumerate(self.search_results):
data = {
'book': QtCore.QVariant(verse.book.name),
'chapter': QtCore.QVariant(verse.chapter),
'verse': QtCore.QVariant(verse.verse),
'bible': QtCore.QVariant(bible),
'version': QtCore.QVariant(version),
'copyright': QtCore.QVariant(copyright),
'permissions': QtCore.QVariant(permissions),
'text': QtCore.QVariant(verse.text),
'second_bible': QtCore.QVariant(second_bible),
'second_version': QtCore.QVariant(second_version),
'second_copyright': QtCore.QVariant(second_copyright),
'second_permissions': QtCore.QVariant(second_permissions),
'second_text': QtCore.QVariant(u'')
}
if second_bible: if second_bible:
try: try:
vdict = { data[u'second_text'] = QtCore.QVariant(
'book': QtCore.QVariant(verse.book.name), self.second_search_results[count].text)
'chapter': QtCore.QVariant(verse.chapter),
'verse': QtCore.QVariant(verse.verse),
'bible': QtCore.QVariant(bible),
'version': QtCore.QVariant(version.value),
'copyright': QtCore.QVariant(copyright.value),
'permissions': QtCore.QVariant(permissions.value),
'text': QtCore.QVariant(verse.text),
'second_bible': QtCore.QVariant(second_bible),
'second_version': QtCore.QVariant(second_version.value),
'second_copyright': QtCore.QVariant(
second_copyright.value),
'second_permissions': QtCore.QVariant(
second_permissions.value),
'second_text': QtCore.QVariant(
self.second_search_results[count].text)
}
except IndexError: except IndexError:
log.exception(u'The second_search_results does not have as '
'many verses as the search_results.')
break break
bible_text = u' %s %d%s%d (%s, %s)' % (verse.book.name, bible_text = u' %s %d%s%d (%s, %s)' % (verse.book.name,
verse.chapter, verse_separator, verse.verse, version.value, verse.chapter, verse_separator, verse.verse, version,
second_version.value) second_version)
else: else:
vdict = {
'book': QtCore.QVariant(verse.book.name),
'chapter': QtCore.QVariant(verse.chapter),
'verse': QtCore.QVariant(verse.verse),
'bible': QtCore.QVariant(bible),
'version': QtCore.QVariant(version.value),
'copyright': QtCore.QVariant(copyright.value),
'permissions': QtCore.QVariant(permissions.value),
'text': QtCore.QVariant(verse.text),
'second_bible': QtCore.QVariant(u''),
'second_version': QtCore.QVariant(u''),
'second_copyright': QtCore.QVariant(u''),
'second_permissions': QtCore.QVariant(u''),
'second_text': QtCore.QVariant(u'')
}
bible_text = u'%s %d%s%d (%s)' % (verse.book.name, bible_text = u'%s %d%s%d (%s)' % (verse.book.name,
verse.chapter, verse_separator, verse.verse, version.value) verse.chapter, verse_separator, verse.verse, version)
bible_verse = QtGui.QListWidgetItem(bible_text) bible_verse = QtGui.QListWidgetItem(bible_text)
bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(vdict)) bible_verse.setData(QtCore.Qt.UserRole, QtCore.QVariant(data))
self.listView.addItem(bible_verse) self.listView.addItem(bible_verse)
self.listView.selectAll() self.listView.selectAll()
self.search_results = {} self.search_results = {}
@ -810,11 +798,9 @@ class BibleMediaItem(MediaManagerItem):
else: else:
verse_text = unicode(verse) verse_text = unicode(verse)
if self.settings.display_style == DisplayStyle.Round: if self.settings.display_style == DisplayStyle.Round:
verse_text = u'{su}(' + verse_text + u'){/su}' return u'{su}(%s){/su}' % verse_text
elif self.settings.display_style == DisplayStyle.Curly: if self.settings.display_style == DisplayStyle.Curly:
verse_text = u'{su}{' + verse_text + u'}{/su}' return u'{su}{%s}{/su}' % verse_text
elif self.settings.display_style == DisplayStyle.Square: if self.settings.display_style == DisplayStyle.Square:
verse_text = u'{su}[' + verse_text + u']{/su}' return u'{su}[%s]{/su}' % verse_text
else: return u'{su}%s{/su}' % verse_text
verse_text = u'{su}' + verse_text + u'{/su}'
return verse_text

View File

@ -45,7 +45,7 @@ class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog):
self.setupUi(self) self.setupUi(self)
# Connecting signals and slots # Connecting signals and slots
QtCore.QObject.connect(self.splitButton, QtCore.QObject.connect(self.splitButton,
QtCore.SIGNAL(u'pressed()'), self.onSplitButtonPressed) QtCore.SIGNAL(u'clicked()'), self.onSplitButtonPressed)
def setText(self, text): def setText(self, text):
""" """

View File

@ -189,7 +189,7 @@ class PresentationMediaItem(MediaManagerItem):
icon = build_icon(u':/general/general_delete.png') icon = build_icon(u':/general/general_delete.png')
else: else:
critical_error_message_box( critical_error_message_box(
self, translate('PresentationPlugin.MediaItem', translate('PresentationPlugin.MediaItem',
'Unsupported File'), 'Unsupported File'),
translate('PresentationPlugin.MediaItem', translate('PresentationPlugin.MediaItem',
'This type of presentation is not supported.')) 'This type of presentation is not supported.'))

View File

@ -93,7 +93,6 @@ window.OpenLP = {
}, },
setSlide: function (event) { setSlide: function (event) {
var slide = OpenLP.getElement(event); var slide = OpenLP.getElement(event);
console.log(slide);
var id = slide.attr("value"); var id = slide.attr("value");
var text = JSON.stringify({"request": {"id": id}}); var text = JSON.stringify({"request": {"id": id}});
$.getJSON( $.getJSON(

View File

@ -30,15 +30,16 @@ import chardet
import codecs import codecs
from openlp.core.lib import translate from openlp.core.lib import translate
from openlp.plugins.songs.lib import VerseType
from songimport import SongImport from songimport import SongImport
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class CCLIFileImport(SongImport): class CCLIFileImport(SongImport):
""" """
The :class:`CCLIFileImport` class provides OpenLP with the ability to The :class:`CCLIFileImport` class provides OpenLP with the ability to import
import CCLI SongSelect song files in both .txt and .usr formats. CCLI SongSelect song files in both .txt and .usr formats. See
See http://www.ccli.com/ for more details. `<http://www.ccli.com/>`_ for more details.
""" """
def __init__(self, manager, **kwargs): def __init__(self, manager, **kwargs):
@ -55,7 +56,7 @@ class CCLIFileImport(SongImport):
def do_import(self): def do_import(self):
""" """
Import either a .usr or a .txt SongSelect file Import either a ``.usr`` or a ``.txt`` SongSelect file.
""" """
log.debug(u'Starting CCLI File Import') log.debug(u'Starting CCLI File Import')
song_total = len(self.import_source) song_total = len(self.import_source)
@ -67,6 +68,7 @@ class CCLIFileImport(SongImport):
(song_count, song_total)) (song_count, song_total))
filename = unicode(filename) filename = unicode(filename)
log.debug(u'Importing CCLI File: %s', filename) log.debug(u'Importing CCLI File: %s', filename)
self.set_defaults()
lines = [] lines = []
if os.path.isfile(filename): if os.path.isfile(filename):
detect_file = open(filename, u'r') detect_file = open(filename, u'r')
@ -81,12 +83,10 @@ class CCLIFileImport(SongImport):
lines = infile.readlines() lines = infile.readlines()
ext = os.path.splitext(filename)[1] ext = os.path.splitext(filename)[1]
if ext.lower() == u'.usr': if ext.lower() == u'.usr':
log.info(u'SongSelect .usr format file found %s: ', log.info(u'SongSelect .usr format file found: %s', filename)
filename)
self.do_import_usr_file(lines) self.do_import_usr_file(lines)
elif ext.lower() == u'.txt': elif ext.lower() == u'.txt':
log.info(u'SongSelect .txt format file found %s: ', log.info(u'SongSelect .txt format file found: %s', filename)
filename)
self.do_import_txt_file(lines) self.do_import_txt_file(lines)
else: else:
log.info(u'Extension %s is not valid', filename) log.info(u'Extension %s is not valid', filename)
@ -97,9 +97,8 @@ class CCLIFileImport(SongImport):
def do_import_usr_file(self, textList): def do_import_usr_file(self, textList):
""" """
The :func:`do_import_usr_file` method provides OpenLP The :func:`do_import_usr_file` method provides OpenLP with the ability
with the ability to import CCLI SongSelect songs in to import CCLI SongSelect songs in *USR* file format.
*USR* file format
``textList`` ``textList``
An array of strings containing the usr file content. An array of strings containing the usr file content.
@ -108,35 +107,46 @@ class CCLIFileImport(SongImport):
``[File]`` ``[File]``
USR file format first line USR file format first line
``Type=`` ``Type=``
Indicates the file type Indicates the file type
e.g. *Type=SongSelect Import File* e.g. *Type=SongSelect Import File*
``Version=3.0`` ``Version=3.0``
File format version File format version
``[S A2672885]`` ``[S A2672885]``
Contains the CCLI Song number e.g. *2672885* Contains the CCLI Song number e.g. *2672885*
``Title=`` ``Title=``
Contains the song title (e.g. *Title=Above All*) Contains the song title (e.g. *Title=Above All*)
``Author=`` ``Author=``
Contains a | delimited list of the song authors Contains a | delimited list of the song authors
e.g. *Author=LeBlanc, Lenny | Baloche, Paul* e.g. *Author=LeBlanc, Lenny | Baloche, Paul*
``Copyright=`` ``Copyright=``
Contains a | delimited list of the song copyrights Contains a | delimited list of the song copyrights
e.g. Copyright=1999 Integrity's Hosanna! Music | e.g. Copyright=1999 Integrity's Hosanna! Music |
LenSongs Publishing (Verwaltet von Gerth Medien LenSongs Publishing (Verwaltet von Gerth Medien
Musikverlag) Musikverlag)
``Admin=`` ``Admin=``
Contains the song administrator Contains the song administrator
e.g. *Admin=Gerth Medien Musikverlag* e.g. *Admin=Gerth Medien Musikverlag*
``Themes=`` ``Themes=``
Contains a /t delimited list of the song themes Contains a /t delimited list of the song themes
e.g. *Themes=Cross/tKingship/tMajesty/tRedeemer* e.g. *Themes=Cross/tKingship/tMajesty/tRedeemer*
``Keys=`` ``Keys=``
Contains the keys in which the music is played?? Contains the keys in which the music is played??
e.g. *Keys=A* e.g. *Keys=A*
``Fields=`` ``Fields=``
Contains a list of the songs fields in order /t delimited Contains a list of the songs fields in order /t delimited
e.g. *Fields=Vers 1/tVers 2/tChorus 1/tAndere 1* e.g. *Fields=Vers 1/tVers 2/tChorus 1/tAndere 1*
``Words=`` ``Words=``
Contains the songs various lyrics in order as shown by the Contains the songs various lyrics in order as shown by the
*Fields* description *Fields* description
@ -144,57 +154,60 @@ class CCLIFileImport(SongImport):
""" """
log.debug(u'USR file text: %s', textList) log.debug(u'USR file text: %s', textList)
self.set_defaults() song_author = u''
song_topics = u''
for line in textList: for line in textList:
if line.startswith(u'Title='): if line.startswith(u'Title='):
song_name = line[6:].strip() self.title = line[6:].strip()
elif line.startswith(u'Author='): elif line.startswith(u'Author='):
song_author = line[7:].strip() song_author = line[7:].strip()
elif line.startswith(u'Copyright='): elif line.startswith(u'Copyright='):
song_copyright = line[10:].strip() self.copyright = line[10:].strip()
elif line.startswith(u'Themes='):
song_topics = line[7:].strip()
elif line.startswith(u'[S A'): elif line.startswith(u'[S A'):
song_ccli = line[4:-3].strip() self.ccli_number = line[4:-3].strip()
elif line.startswith(u'Fields='): elif line.startswith(u'Fields='):
#Fields contain single line indicating verse, chorus, etc, # Fields contain single line indicating verse, chorus, etc,
#/t delimited, same as with words field. store seperately # /t delimited, same as with words field. store seperately
#and process at end. # and process at end.
song_fields = line[7:].strip() song_fields = line[7:].strip()
elif line.startswith(u'Words='): elif line.startswith(u'Words='):
song_words = line[6:].strip() song_words = line[6:].strip()
#Unhandled usr keywords:Type,Version,Admin,Themes,Keys # Unhandled usr keywords: Type, Version, Admin, Keys
#Process Fields and words sections # Process Fields and words sections.
check_first_verse_line = False check_first_verse_line = False
field_list = song_fields.split(u'/t') field_list = song_fields.split(u'/t')
words_list = song_words.split(u'/t') words_list = song_words.split(u'/t')
for counter in range(0, len(field_list)): for counter in range(0, len(field_list)):
if field_list[counter].startswith(u'Ver'): if field_list[counter].startswith(u'Ver'):
verse_type = u'V' verse_type = VerseType.Tags[VerseType.Verse]
elif field_list[counter].startswith(u'Ch'): elif field_list[counter].startswith(u'Ch'):
verse_type = u'C' verse_type = VerseType.Tags[VerseType.Chorus]
elif field_list[counter].startswith(u'Br'): elif field_list[counter].startswith(u'Br'):
verse_type = u'B' verse_type = VerseType.Tags[VerseType.Bridge]
else: #Other else:
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
check_first_verse_line = True check_first_verse_line = True
verse_text = unicode(words_list[counter]) verse_text = unicode(words_list[counter])
verse_text = verse_text.replace(u'/n', u'\n') verse_text = verse_text.replace(u'/n', u'\n')
verse_lines = verse_text.split(u'\n', 1) verse_lines = verse_text.split(u'\n', 1)
if check_first_verse_line: if check_first_verse_line:
if verse_lines[0].startswith(u'(PRE-CHORUS'): if verse_lines[0].startswith(u'(PRE-CHORUS'):
verse_type = u'P' verse_type = VerseType.Tags[VerseType.PreChorus]
log.debug(u'USR verse PRE-CHORUS: %s', verse_lines[0]) log.debug(u'USR verse PRE-CHORUS: %s', verse_lines[0])
verse_text = verse_lines[1] verse_text = verse_lines[1]
elif verse_lines[0].startswith(u'(BRIDGE'): elif verse_lines[0].startswith(u'(BRIDGE'):
verse_type = u'B' verse_type = VerseType.Tags[VerseType.Bridge]
log.debug(u'USR verse BRIDGE') log.debug(u'USR verse BRIDGE')
verse_text = verse_lines[1] verse_text = verse_lines[1]
elif verse_lines[0].startswith(u'('): elif verse_lines[0].startswith(u'('):
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
verse_text = verse_lines[1] verse_text = verse_lines[1]
if len(verse_text) > 0: if len(verse_text) > 0:
self.add_verse(verse_text, verse_type) self.add_verse(verse_text, verse_type)
check_first_verse_line = False check_first_verse_line = False
#Handle multiple authors # Handle multiple authors
author_list = song_author.split(u'/') author_list = song_author.split(u'/')
if len(author_list) < 2: if len(author_list) < 2:
author_list = song_author.split(u'|') author_list = song_author.split(u'|')
@ -204,16 +217,13 @@ class CCLIFileImport(SongImport):
self.add_author(u' '.join(reversed(separated))) self.add_author(u' '.join(reversed(separated)))
else: else:
self.add_author(author) self.add_author(author)
self.title = song_name self.topics = [topic.strip() for topic in song_topics.split(u'/t')]
self.copyright = song_copyright
self.ccli_number = song_ccli
self.finish() self.finish()
def do_import_txt_file(self, textList): def do_import_txt_file(self, textList):
""" """
The :func:`do_import_txt_file` method provides OpenLP The :func:`do_import_txt_file` method provides OpenLP with the ability
with the ability to import CCLI SongSelect songs in to import CCLI SongSelect songs in *TXT* file format.
*TXT* file format
``textList`` ``textList``
An array of strings containing the txt file content. An array of strings containing the txt file content.
@ -243,12 +253,10 @@ class CCLIFileImport(SongImport):
""" """
log.debug(u'TXT file text: %s', textList) log.debug(u'TXT file text: %s', textList)
self.set_defaults()
line_number = 0 line_number = 0
check_first_verse_line = False check_first_verse_line = False
verse_text = u'' verse_text = u''
song_comments = u'' song_author = u''
song_copyright = u''
verse_start = False verse_start = False
for line in textList: for line in textList:
clean_line = line.strip() clean_line = line.strip()
@ -258,12 +266,12 @@ class CCLIFileImport(SongImport):
elif verse_start: elif verse_start:
if verse_text: if verse_text:
self.add_verse(verse_text, verse_type) self.add_verse(verse_text, verse_type)
verse_text = '' verse_text = u''
verse_start = False verse_start = False
else: else:
#line_number=0, song title #line_number=0, song title
if line_number == 0: if line_number == 0:
song_name = clean_line self.title = clean_line
line_number += 1 line_number += 1
#line_number=1, verses #line_number=1, verses
elif line_number == 1: elif line_number == 1:
@ -271,37 +279,37 @@ class CCLIFileImport(SongImport):
if clean_line.startswith(u'CCLI'): if clean_line.startswith(u'CCLI'):
line_number += 1 line_number += 1
ccli_parts = clean_line.split(' ') ccli_parts = clean_line.split(' ')
song_ccli = ccli_parts[len(ccli_parts)-1] self.ccli_number = ccli_parts[len(ccli_parts) - 1]
elif not verse_start: elif not verse_start:
# We have the verse descriptor # We have the verse descriptor
verse_desc_parts = clean_line.split(' ') verse_desc_parts = clean_line.split(u' ')
if len(verse_desc_parts) == 2: if len(verse_desc_parts) == 2:
if verse_desc_parts[0].startswith(u'Ver'): if verse_desc_parts[0].startswith(u'Ver'):
verse_type = u'V' verse_type = VerseType.Tags[VerseType.Verse]
elif verse_desc_parts[0].startswith(u'Ch'): elif verse_desc_parts[0].startswith(u'Ch'):
verse_type = u'C' verse_type = VerseType.Tags[VerseType.Chorus]
elif verse_desc_parts[0].startswith(u'Br'): elif verse_desc_parts[0].startswith(u'Br'):
verse_type = u'B' verse_type = VerseType.Tags[VerseType.Bridge]
else: else:
#we need to analyse the next line for # we need to analyse the next line for
#verse type, so set flag # verse type, so set flag
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
check_first_verse_line = True check_first_verse_line = True
verse_number = verse_desc_parts[1] verse_number = verse_desc_parts[1]
else: else:
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
verse_number = 1 verse_number = 1
verse_start = True verse_start = True
else: else:
#check first line for verse type # check first line for verse type
if check_first_verse_line: if check_first_verse_line:
if line.startswith(u'(PRE-CHORUS'): if line.startswith(u'(PRE-CHORUS'):
verse_type = u'P' verse_type = VerseType.Tags[VerseType.PreChorus]
elif line.startswith(u'(BRIDGE'): elif line.startswith(u'(BRIDGE'):
verse_type = u'B' verse_type = VerseType.Tags[VerseType.Bridge]
# Handle all other misc types # Handle all other misc types
elif line.startswith(u'('): elif line.startswith(u'('):
verse_type = u'O' verse_type = VerseType.Tags[VerseType.Other]
else: else:
verse_text = verse_text + line verse_text = verse_text + line
check_first_verse_line = False check_first_verse_line = False
@ -313,24 +321,19 @@ class CCLIFileImport(SongImport):
#line_number=2, copyright #line_number=2, copyright
if line_number == 2: if line_number == 2:
line_number += 1 line_number += 1
song_copyright = clean_line self.copyright = clean_line
#n=3, authors #n=3, authors
elif line_number == 3: elif line_number == 3:
line_number += 1 line_number += 1
song_author = clean_line song_author = clean_line
#line_number=4, comments lines before last line #line_number=4, comments lines before last line
elif (line_number == 4) and \ elif line_number == 4 and not clean_line.startswith(u'CCL'):
(not clean_line.startswith(u'CCL')): self.comments += clean_line
song_comments = song_comments + clean_line
# split on known separators # split on known separators
author_list = song_author.split(u'/') author_list = song_author.split(u'/')
if len(author_list) < 2: if len(author_list) < 2:
author_list = song_author.split(u'|') author_list = song_author.split(u'|')
#Clean spaces before and after author names # Clean spaces before and after author names.
for author_name in author_list: for author_name in author_list:
self.add_author(author_name.strip()) self.add_author(author_name.strip())
self.title = song_name
self.copyright = song_copyright
self.ccli_number = song_ccli
self.comments = song_comments
self.finish() self.finish()

View File

@ -68,6 +68,7 @@ from lxml import etree, objectify
from openlp.plugins.songs.lib import clean_song, VerseType from openlp.plugins.songs.lib import clean_song, VerseType
from openlp.plugins.songs.lib.db import Author, Book, Song, Topic from openlp.plugins.songs.lib.db import Author, Book, Song, Topic
from openlp.core.utils import get_application_version
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -230,8 +231,8 @@ class OpenLyrics(object):
# Append the necessary meta data to the song. # Append the necessary meta data to the song.
song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song') song_xml.set(u'xmlns', u'http://openlyrics.info/namespace/2009/song')
song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION) song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION)
song_xml.set(u'createdIn', u'OpenLP 1.9.5') # Use variable song_xml.set(u'createdIn', get_application_version()[u'version'])
song_xml.set(u'modifiedIn', u'OpenLP 1.9.5') # Use variable song_xml.set(u'modifiedIn', get_application_version()[u'version'])
song_xml.set(u'modifiedDate', song_xml.set(u'modifiedDate',
datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S')) datetime.datetime.now().strftime(u'%Y-%m-%dT%H:%M:%S'))
properties = etree.SubElement(song_xml, u'properties') properties = etree.SubElement(song_xml, u'properties')

View File

@ -3,11 +3,11 @@ Categories=AudioVideo;
Comment[de]= Comment[de]=
Comment= Comment=
Encoding=UTF-8 Encoding=UTF-8
Exec=openlp Exec=openlp %F
GenericName[de]=Church lyrics projection GenericName[de]=Church lyrics projection
GenericName=Church lyrics projection GenericName=Church lyrics projection
Icon=openlp Icon=openlp
MimeType= MimeType=application/x-openlp-service;
Name[de]=OpenLP Name[de]=OpenLP
Name=OpenLP Name=OpenLP
Path= Path=

26
resources/openlp.xml Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
It comes with ABSOLUTELY NO WARRANTY, to the extent permitted by law. You may
redistribute copies of update-mime-database under the terms of the GNU General
Public License. For more information about these matters, see the file named
COPYING.
-->
<!--
Notes:
- the mime types in this file are valid with the version 0.30 of the
shared-mime-info package.
- the "fdo #xxxxx" are the wish in the freedesktop.org bug database to include
the mime type there.
-->
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-openlp-service">
<sub-class-of type="application/zip"/>
<comment>OpenLP Service File</comment>
<glob pattern="*.osz"/>
</mime-type>
<mime-type type="application/x-openlp-theme">
<sub-class-of type="application/zip"/>
<comment>OpenLP Theme File</comment>
<glob pattern="*.otz"/>
</mime-type>
</mime-info>

View File

@ -18,9 +18,9 @@
<string>MacOS/openlp</string> <string>MacOS/openlp</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>%(openlp_appname)s</string> <string>%(openlp_appname)s</string>
<key>CFBundleGetInfoString</string> <key>CFBundleGetInfoString</key>
<string>%(openlp_appname)s %(openlp_version)s</string> <string>%(openlp_appname)s %(openlp_version)s</string>
<key>LSHasLocalizedDisplayName</string> <key>LSHasLocalizedDisplayName</key>
<false/> <false/>
<key>NSAppleScriptEnabled</key> <key>NSAppleScriptEnabled</key>
<false/> <false/>

View File

@ -25,4 +25,4 @@ clean:
rm -rf OpenLP.app rm -rf OpenLP.app
rm -f warnopenlp.txt rm -f warnopenlp.txt
rm -f *dmg rm -f *dmg

View File

@ -82,6 +82,7 @@ import ConfigParser
import logging import logging
import optparse import optparse
import sys import sys
import glob
import platform import platform
import re import re
import subprocess as subp import subprocess as subp
@ -122,6 +123,15 @@ def build_application(settings, app_name_lower, app_dir):
script_name) script_name)
sys.exit(1) sys.exit(1)
logging.info('[%s] removing the presentations plugin...', script_name)
result = os.system('rm -rf \
%(application_directory)s/Contents/MacOS/plugins/presentations' \
% { 'application_directory' : app_dir })
if (result != 0):
logging.error('[%s] could not remove presentations plugins, dmg \
creation failed!', script_name)
sys.exit(1)
logging.info('[%s] copying the icons to the resource directory...', logging.info('[%s] copying the icons to the resource directory...',
script_name) script_name)
result = os.system('cp %(icon_file)s \ result = os.system('cp %(icon_file)s \
@ -151,6 +161,19 @@ def build_application(settings, app_name_lower, app_dir):
failed!', script_name) failed!', script_name)
sys.exit(1) sys.exit(1)
logging.info('[%s] copying the translations...', script_name)
os.mkdir(app_dir + '/Contents/MacOS/i18n')
for ts_file in glob.glob(os.path.join(settings['openlp_basedir']
+ '/resources/i18n/', '*ts')):
result = os.system('lconvert -i %(ts_file)s \
-o %(target_directory)s/Contents/MacOS/i18n/%(base)s.qm' \
% { 'ts_file' : ts_file, 'target_directory' : app_dir,
'base': os.path.splitext(os.path.basename(ts_file))[0] })
if (result != 0):
logging.error('[%s] could not copy the translations, dmg \
creation failed!', script_name)
sys.exit(1)
def deploy_qt(settings): def deploy_qt(settings):
logging.info('[%s] running mac deploy qt on %s.app...', script_name, logging.info('[%s] running mac deploy qt on %s.app...', script_name,
settings['openlp_appname']); settings['openlp_appname']);
@ -371,10 +394,7 @@ if __name__ == '__main__':
--template Info.plist.master \ --template Info.plist.master \
--expandto %(target_directory)s/Info.plist' \ --expandto %(target_directory)s/Info.plist' \
% { 'config_file' : options.config, 'target_directory' : os.getcwd() }) % { 'config_file' : options.config, 'target_directory' : os.getcwd() })
os.system('python expander.py --config %(config_file)s \ os.system('python get_version.py > .version')
--template version.master \
--expandto %(target_directory)s/.version' \
% { 'config_file' : options.config, 'target_directory' : os.getcwd() })
# prepare variables # prepare variables
app_name_lower = settings['openlp_appname'].lower() app_name_lower = settings['openlp_appname'].lower()

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
from bzrlib.branch import Branch
def get_version(path):
b = Branch.open_containing(path)[0]
b.lock_read()
result = '0.0.0'
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:
result = tags[revision_id][0]
else:
result = '%s-bzr%s' % (sorted(b.tags.get_tag_dict().keys())[-1], revno)
finally:
b.unlock()
return result
def get_path():
if len(sys.argv) > 1:
return os.path.abspath(sys.argv[1])
else:
return os.path.abspath('.')
if __name__ == u'__main__':
path = get_path()
print get_version(path)

View File

@ -2,7 +2,6 @@
openlp_appname = OpenLP openlp_appname = OpenLP
openlp_dmgname = OpenLP-1.9.4-bzrXXXX openlp_dmgname = OpenLP-1.9.4-bzrXXXX
openlp_version = XXXX openlp_version = XXXX
openlp_full_version = 1.9.4-latest
openlp_basedir = /Users/openlp/trunk openlp_basedir = /Users/openlp/trunk
openlp_icon_file = openlp-logo-with-text.icns openlp_icon_file = openlp-logo-with-text.icns
openlp_dmg_icon_file = openlp-logo-420x420.png openlp_dmg_icon_file = openlp-logo-420x420.png

View File

@ -1 +0,0 @@
%(openlp_full_version)s