This commit is contained in:
Samuel Findlay 2012-06-04 01:13:23 +10:00
commit 6dba01ea23
10 changed files with 519 additions and 768 deletions

View File

@ -109,6 +109,7 @@ class Renderer(object):
self.global_theme_data = \
self.themeManager.getThemeData(self.global_theme)
self.theme_data = None
self._cache_background_image(self.global_theme_data)
def set_service_theme(self, service_theme):
"""
@ -119,6 +120,21 @@ class Renderer(object):
"""
self.service_theme = service_theme
self.theme_data = None
self._cache_background_image(self.themeManager.getThemeData
(service_theme))
def _cache_background_image(self, temp_theme):
"""
Adds a background image to the image cache if necessary.
``temp_theme``
The theme object containing the theme data.
"""
# if No file do not update cache
if temp_theme.background_filename:
self.imageManager.add_image(temp_theme.theme_name,
temp_theme.background_filename, u'theme',
QtGui.QColor(temp_theme.background_border_color))
def set_override_theme(self, override_theme, override_levels=False):
"""
@ -163,11 +179,7 @@ class Renderer(object):
self.theme_data = self.themeManager.getThemeData(theme)
self._calculate_default()
self._build_text_rectangle(self.theme_data)
# if No file do not update cache
if self.theme_data.background_filename:
self.imageManager.add_image(self.theme_data.theme_name,
self.theme_data.background_filename, u'theme',
QtGui.QColor(self.theme_data.background_border_color))
self._cache_background_image(self.theme_data)
return self._rect, self._rect_footer
def generate_preview(self, theme_data, force_page=False):

View File

@ -80,6 +80,10 @@ class UiStrings(object):
self.Help = translate('OpenLP.Ui', 'Help')
self.Hours = translate('OpenLP.Ui', 'h',
'The abbreviated unit for hours')
self.IFdSs = translate('OpenLP.Ui', 'Invalid Folder Selected',
'Singular')
self.IFSs = translate('OpenLP.Ui', 'Invalid File Selected', 'Singular')
self.IFSp = translate('OpenLP.Ui', 'Invalid Files Selected', 'Plural')
self.Image = translate('OpenLP.Ui', 'Image')
self.Import = translate('OpenLP.Ui', 'Import')
self.LayoutStyle = translate('OpenLP.Ui', 'Layout style:')

View File

@ -56,6 +56,9 @@ class ThemeScreenshotThread(QtCore.QThread):
themes = themes.split(u',')
config = self.parent().config
for theme in themes:
# Stop if the wizard has been cancelled.
if self.parent().downloadCancelled:
return
title = config.get(u'theme_%s' % theme, u'title')
filename = config.get(u'theme_%s' % theme, u'filename')
screenshot = config.get(u'theme_%s' % theme, u'screenshot')
@ -86,7 +89,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
files = self.webAccess.read()
self.config.readfp(io.BytesIO(files))
self.updateScreenListCombo()
self.downloadCanceled = False
self.downloadCancelled = False
self.downloading = unicode(translate('OpenLP.FirstTimeWizard',
'Downloading %s...'))
QtCore.QObject.connect(self.cancelButton, QtCore.SIGNAL('clicked()'),
@ -242,11 +245,12 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
Process the triggering of the cancel button.
"""
if self.lastId == FirstTimePage.NoInternet or \
(self.lastId <= FirstTimePage.Plugins and \
not self.hasRunWizard):
(self.lastId <= FirstTimePage.Plugins and not self.hasRunWizard):
QtCore.QCoreApplication.exit()
sys.exit()
self.downloadCanceled = True
self.downloadCancelled = True
while self.themeScreenshotThread.isRunning():
time.sleep(0.1)
Receiver.send_message(u'cursor_normal')
def onNoInternetFinishButtonClicked(self):
@ -272,7 +276,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
filesize = urlfile.headers["Content-Length"]
filename = open(fpath, "wb")
# Download until finished or canceled.
while not self.downloadCanceled:
while not self.downloadCancelled:
data = urlfile.read(block_size)
if not data:
break
@ -280,8 +284,8 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
block_count += 1
self._downloadProgress(block_count, block_size, filesize)
filename.close()
# Delete file if canceled, it may be a partial file.
if self.downloadCanceled:
# Delete file if cancelled, it may be a partial file.
if self.downloadCancelled:
os.remove(fpath)
def _buildThemeScreenshots(self):

View File

@ -44,20 +44,9 @@ class WizardStrings(object):
# Applications/Formats we import from or export to. These get used in
# multiple places but do not need translating unless you find evidence of
# the writers translating their own product name.
CCLI = u'CCLI/SongSelect'
CSV = u'CSV'
DB = u'DreamBeam'
EW = u'EasyWorship'
ES = u'EasySlides'
FP = u'Foilpresenter'
OL = u'OpenLyrics'
OS = u'OpenSong'
OSIS = u'OSIS'
PS = u'PowerSong 1.0'
SB = u'SongBeamer'
SoF = u'Songs of Fellowship'
SSP = u'SongShow Plus'
WoW = u'Words of Worship'
# These strings should need a good reason to be retranslated elsewhere.
FinishedImport = translate('OpenLP.Ui', 'Finished import.')
FormatLabel = translate('OpenLP.Ui', 'Format:')
@ -76,10 +65,12 @@ class WizardStrings(object):
PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%'))
Ready = translate('OpenLP.Ui', 'Ready.')
StartingImport = translate('OpenLP.Ui', 'Starting import...')
YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify at '
YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify one '
'%s file to import from.', 'A file type e.g. OpenSong'))
YouSpecifyFiles = unicode(translate('OpenLP.Ui', 'You need to specify at '
'least one %s file to import from.', 'A file type e.g. OpenSong'))
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify a '
'%s folder to import from.', 'A file type e.g. OpenSong'))
YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify one '
'%s folder to import from.', 'A song format e.g. PowerSong'))
class OpenLPWizard(QtGui.QWizard):

View File

@ -164,7 +164,7 @@
<input type="search" name="search-text" id="search-text" value="" />
</div>
<a href="#" id="search-submit" data-role="button">${search}</a>
<ul data-role="listview" data-inset="true">
<ul data-role="listview" data-inset="true"/>
</div>
</div>
<div data-role="page" id="options">

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,9 @@ The :mod:`importer` modules provides the general song import functionality.
"""
import logging
from openlp.core.lib import translate
from openlp.core.lib.ui import UiStrings
from openlp.core.ui.wizard import WizardStrings
from opensongimport import OpenSongImport
from easyslidesimport import EasySlidesImport
from olpimport import OpenLPSongImport
@ -64,11 +67,9 @@ except ImportError:
class SongFormat(object):
"""
This is a special enumeration class that holds the various types of songs,
plus a few helper functions to facilitate generic handling of song types
for importing.
This is a special enumeration class that holds the various types of song
importers and some helper functions to facilitate access.
"""
_format_availability = {}
Unknown = -1
OpenLyrics = 0
OpenLP2 = 1
@ -88,47 +89,7 @@ class SongFormat(object):
#CSV = 15
@staticmethod
def get_class(format):
"""
Return the appropriate implementation class.
``format``
The song format.
"""
if format == SongFormat.OpenLP2:
return OpenLPSongImport
elif format == SongFormat.OpenLP1:
return OpenLP1SongImport
elif format == SongFormat.OpenLyrics:
return OpenLyricsImport
elif format == SongFormat.OpenSong:
return OpenSongImport
elif format == SongFormat.SongsOfFellowship:
return SofImport
elif format == SongFormat.WordsOfWorship:
return WowImport
elif format == SongFormat.Generic:
return OooImport
elif format == SongFormat.CCLI:
return CCLIFileImport
elif format == SongFormat.DreamBeam:
return DreamBeamImport
elif format == SongFormat.PowerSong:
return PowerSongImport
elif format == SongFormat.EasySlides:
return EasySlidesImport
elif format == SongFormat.EasyWorship:
return EasyWorshipSongImport
elif format == SongFormat.SongBeamer:
return SongBeamerImport
elif format == SongFormat.SongShowPlus:
return SongShowPlusImport
elif format == SongFormat.FoilPresenter:
return FoilPresenterImport
return None
@staticmethod
def get_formats_list():
def get_format_list():
"""
Return a list of the supported song formats.
"""
@ -138,7 +99,7 @@ class SongFormat(object):
SongFormat.OpenLP1,
SongFormat.Generic,
SongFormat.CCLI,
SongFormat.DreamBeam,
SongFormat.DreamBeam,
SongFormat.EasySlides,
SongFormat.EasyWorship,
SongFormat.FoilPresenter,
@ -150,23 +111,246 @@ class SongFormat(object):
SongFormat.WordsOfWorship
]
@staticmethod
def set_availability(format, available):
"""
Set the availability for a given song format.
"""
SongFormat._format_availability[format] = available
class SongFormatSelect(object):
"""
This is a special enumeration class listing available file selection modes.
"""
SingleFile = 0
MultipleFiles = 1
SingleFolder = 2
class SongFormatAttr(object):
"""
This is a special static class that holds the attributes of each song format
to aid the importing of each song type.
The various definable attributes are enumerated as follows:
Required attributes for each song format:
* ``class_`` Import class, e.g. OpenLyricsImport
* ``name`` Name of this format, e.g. u'OpenLyrics'
* ``prefix`` Prefix for objects. Use camelCase, e.g. u'openLyrics'
See ``SongImportForm.addFileSelectItem()``.
Optional attributes for each song format:
* ``can_disable`` Whether song format is disablable.
* ``availability`` Whether song format is available.
* ``select_mode`` Whether format accepts single file, multiple files, or
single folder.
* ``filter`` File extension filter for QFileDialog.
Optional/custom text values for SongImportForm widgets:
* ``combo_box_text`` Combo box selector (default is format name).
* ``disabled_label_text`` Required for disablable song formats.
* ``get_files_title`` Title for QFileDialog (default includes format
name).
* ``invalid_source_msg`` Message shown when source does not validate with
class_.isValidSource().
"""
# Required attributes
class_ = 0
name = 1
prefix = 2
# Optional attributes
can_disable = 10
availability = 11
select_mode = 12
filter = 13
# Optional/custom text values
combo_box_text = 20
disabled_label_text = 21
get_files_title = 22
invalid_source_msg = 23
# Set optional attribute defaults
_defaults = {
can_disable: False,
availability: True,
select_mode: SongFormatSelect.MultipleFiles,
filter: u'',
combo_box_text: None,
disabled_label_text: u'',
get_files_title: None,
invalid_source_msg: None
}
# Set attribute values
_attributes = {
SongFormat.OpenLyrics: {
class_: OpenLyricsImport,
name: u'OpenLyrics',
prefix: u'openLyrics',
filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
'OpenLyrics Files'),
combo_box_text: translate('SongsPlugin.ImportWizardForm',
'OpenLyrics or OpenLP 2.0 Exported Song')
},
SongFormat.OpenLP2: {
class_: OpenLPSongImport,
name: UiStrings().OLPV2,
prefix: u'openLP2',
select_mode: SongFormatSelect.SingleFile,
filter: u'%s (*.sqlite)' % (translate(
'SongsPlugin.ImportWizardForm', 'OpenLP 2.0 Databases'))
},
SongFormat.OpenLP1: {
name: UiStrings().OLPV1,
prefix: u'openLP1',
can_disable: True,
select_mode: SongFormatSelect.SingleFile,
filter: u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm',
'openlp.org v1.x Databases'),
disabled_label_text: WizardStrings.NoSqlite
},
SongFormat.Generic: {
name: translate('SongsPlugin.ImportWizardForm',
'Generic Document/Presentation'),
prefix: u'generic',
can_disable: True,
disabled_label_text: translate('SongsPlugin.ImportWizardForm',
'The generic document/presentation importer has been disabled '
'because OpenLP cannot access OpenOffice or LibreOffice.'),
get_files_title: translate('SongsPlugin.ImportWizardForm',
'Select Document/Presentation Files')
},
SongFormat.CCLI: {
class_: CCLIFileImport,
name: u'CCLI/SongSelect',
prefix: u'ccli',
filter: u'%s (*.usr *.txt)' % translate(
'SongsPlugin.ImportWizardForm', 'CCLI SongSelect Files')
},
SongFormat.DreamBeam: {
class_: DreamBeamImport,
name: u'DreamBeam',
prefix: u'dreamBeam',
filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
'DreamBeam Song Files')
},
SongFormat.EasySlides: {
class_: EasySlidesImport,
name: u'EasySlides',
prefix: u'easySlides',
select_mode: SongFormatSelect.SingleFile,
filter: u'%s (*.xml)' % translate('SongsPlugin.ImportWizardForm',
'EasySlides XML File')
},
SongFormat.EasyWorship: {
class_: EasyWorshipSongImport,
name: u'EasyWorship',
prefix: u'ew',
select_mode: SongFormatSelect.SingleFile,
filter: u'%s (*.db)' % translate('SongsPlugin.ImportWizardForm',
'EasyWorship Song Database')
},
SongFormat.FoilPresenter: {
class_: FoilPresenterImport,
name: u'Foilpresenter',
prefix: u'foilPresenter',
filter: u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm',
'Foilpresenter Song Files')
},
SongFormat.OpenSong: {
class_: OpenSongImport,
name: WizardStrings.OS,
prefix: u'openSong'
},
SongFormat.PowerSong: {
class_: PowerSongImport,
name: u'PowerSong 1.0',
prefix: u'powerSong',
select_mode: SongFormatSelect.SingleFolder,
invalid_source_msg: translate('SongsPlugin.ImportWizardForm',
'You need to specify a valid PowerSong 1.0 database folder.')
},
SongFormat.SongBeamer: {
class_: SongBeamerImport,
name: u'SongBeamer',
prefix: u'songBeamer',
filter: u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
'SongBeamer Files')
},
SongFormat.SongShowPlus: {
class_: SongShowPlusImport,
name: u'SongShow Plus',
prefix: u'songShowPlus',
filter: u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm',
'SongShow Plus Song Files')
},
SongFormat.SongsOfFellowship: {
name: u'Songs of Fellowship',
prefix: u'songsOfFellowship',
can_disable: True,
filter: u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm',
'Songs Of Fellowship Song Files'),
disabled_label_text: translate('SongsPlugin.ImportWizardForm',
'The Songs of Fellowship importer has been disabled because '
'OpenLP cannot access OpenOffice or LibreOffice.')
},
SongFormat.WordsOfWorship: {
class_: WowImport,
name: u'Words of Worship',
prefix: u'wordsOfWorship',
filter: u'%s (*.wsg *.wow-song)' % translate(
'SongsPlugin.ImportWizardForm', 'Words Of Worship Song Files')
# },
# SongFormat.CSV: {
# class_: CSVImport,
# name: WizardStrings.CSV,
# prefix: u'csv',
# select_mode: SongFormatSelect.SingleFile
}
}
@staticmethod
def get_availability(format):
def get(format, *attributes):
"""
Return the availability of a given song format.
Return requested song format attribute(s).
``format``
A song format from SongFormat.
``*attributes``
Zero or more song format attributes from SongFormatAttr.
Return type depends on number of supplied attributes:
* 0 : Return dict containing all defined attributes for the format.
* 1 : Return the attribute value.
* >1 : Return tuple of requested attribute values.
"""
return SongFormat._format_availability.get(format, True)
if not attributes:
return SongFormatAttr._attributes.get(format)
elif len(attributes) == 1:
default = SongFormatAttr._defaults.get(attributes[0])
return SongFormatAttr._attributes[format].get(attributes[0],
default)
else:
values = []
for attr in attributes:
default = SongFormatAttr._defaults.get(attr)
values.append(SongFormatAttr._attributes[format].get(attr,
default))
return tuple(values)
SongFormat.set_availability(SongFormat.OpenLP1, HAS_OPENLP1)
SongFormat.set_availability(SongFormat.SongsOfFellowship, HAS_SOF)
SongFormat.set_availability(SongFormat.Generic, HAS_OOO)
@staticmethod
def set(format, attribute, value):
"""
Set specified song format attribute to the supplied value.
"""
SongFormatAttr._attributes[format][attribute] = value
__all__ = [u'SongFormat']
SongFormatAttr.set(SongFormat.OpenLP1, SongFormatAttr.availability, HAS_OPENLP1)
if HAS_OPENLP1:
SongFormatAttr.set(SongFormat.OpenLP1, SongFormatAttr.class_,
OpenLP1SongImport)
SongFormatAttr.set(SongFormat.SongsOfFellowship, SongFormatAttr.availability,
HAS_SOF)
if HAS_SOF:
SongFormatAttr.set(SongFormat.SongsOfFellowship, SongFormatAttr.class_,
SofImport)
SongFormatAttr.set(SongFormat.Generic, SongFormatAttr.availability, HAS_OOO)
if HAS_OOO:
SongFormatAttr.set(SongFormat.Generic, SongFormatAttr.class_,
OooImport)
__all__ = [u'SongFormat', u'SongFormatSelect', u'SongFormatAttr']

View File

@ -33,7 +33,6 @@ import fnmatch
import os
from openlp.core.lib import translate
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
@ -71,26 +70,26 @@ class PowerSongImport(SongImport):
* .song
"""
@staticmethod
def isValidSource(**kwargs):
def isValidSource(import_source):
"""
Checks if source is a PowerSong 1.0 folder:
* is a directory
* contains at least one *.song file
"""
if u'folder' in kwargs:
dir = kwargs[u'folder']
if os.path.isdir(dir):
for file in os.listdir(dir):
if fnmatch.fnmatch(file, u'*.song'):
return True
if os.path.isdir(import_source):
for file in os.listdir(import_source):
if fnmatch.fnmatch(file, u'*.song'):
return True
return False
def doImport(self):
"""
Receive either a list of files or a folder (unicode) to import.
"""
from importer import SongFormat, SongFormatAttr
PS_string = SongFormatAttr.get(SongFormat.PowerSong,
SongFormatAttr.name)
if isinstance(self.importSource, unicode):
if os.path.isdir(self.importSource):
dir = self.importSource
@ -104,7 +103,7 @@ class PowerSongImport(SongImport):
self.logError(unicode(translate('SongsPlugin.PowerSongImport',
'No songs to import.')),
unicode(translate('SongsPlugin.PowerSongImport',
'No %s files found.' % WizardStrings.PS)))
'No %s files found.' % PS_string)))
return
self.importWizard.progressBar.setMaximum(len(self.importSource))
for file in self.importSource:
@ -124,7 +123,7 @@ class PowerSongImport(SongImport):
self.logError(os.path.basename(file), unicode(
translate('SongsPlugin.PowerSongImport',
'Invalid %s file. Unexpected byte value.'
% WizardStrings.PS)))
% PS_string)))
break
else:
if label == u'TITLE':
@ -142,15 +141,14 @@ class PowerSongImport(SongImport):
if not self.title:
self.logError(os.path.basename(file), unicode(
translate('SongsPlugin.PowerSongImport',
'Invalid %s file. Missing "TITLE" header.'
% WizardStrings.PS)))
'Invalid %s file. Missing "TITLE" header.' % PS_string)))
continue
# Check that file had COPYRIGHTLINE label
if not found_copyright:
self.logError(self.title, unicode(
translate('SongsPlugin.PowerSongImport',
'Invalid %s file. Missing "COPYRIGHTLINE" '
'header.' % WizardStrings.PS)))
'header.' % PS_string)))
continue
# Check that file had at least one verse
if not self.verses:

View File

@ -51,11 +51,11 @@ class SongImport(QtCore.QObject):
as necessary
"""
@staticmethod
def isValidSource(**kwargs):
def isValidSource(import_source):
"""
Override this method to validate the source prior to import.
"""
pass
return True
def __init__(self, manager, **kwargs):
"""

View File

@ -39,7 +39,7 @@ from openlp.core.utils.actions import ActionList
from openlp.plugins.songs.lib import clean_song, upgrade, SongMediaItem, \
SongsTab
from openlp.plugins.songs.lib.db import init_schema, Song
from openlp.plugins.songs.lib.importer import SongFormat
from openlp.plugins.songs.lib.importer import SongFormatAttr
from openlp.plugins.songs.lib.olpimport import OpenLPSongImport
log = logging.getLogger(__name__)
@ -194,7 +194,7 @@ class SongsPlugin(Plugin):
self.manager.save_object(song)
def importSongs(self, format, **kwargs):
class_ = SongFormat.get_class(format)
class_ = SongFormatAttr.get(format, SongFormatAttr.class_)
importer = class_(self.manager, **kwargs)
importer.register(self.mediaItem.importWizard)
return importer