This commit is contained in:
Andreas Preikschat 2012-07-12 17:38:20 +02:00
commit a0012b794d
15 changed files with 429 additions and 49 deletions

View File

@ -208,6 +208,20 @@ class OpenLP(QtGui.QApplication):
return QtGui.QApplication.event(self, event)
def set_up_logging(log_path):
"""
Setup our logging using log_path
"""
check_directory_exists(log_path)
filename = os.path.join(log_path, u'openlp.log')
logfile = logging.FileHandler(filename, u'w')
logfile.setFormatter(logging.Formatter(
u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
log.addHandler(logfile)
if log.isEnabledFor(logging.DEBUG):
print 'Logging to:', filename
def main(args=None):
"""
The main function which parses command line options and then runs
@ -231,21 +245,12 @@ def main(args=None):
help='Set the Qt4 style (passed directly to Qt4).')
parser.add_option('--testing', dest='testing',
action='store_true', help='Run by testing framework')
# Set up logging
log_path = AppLocation.get_directory(AppLocation.CacheDir)
check_directory_exists(log_path)
filename = os.path.join(log_path, u'openlp.log')
logfile = logging.FileHandler(filename, u'w')
logfile.setFormatter(logging.Formatter(
u'%(asctime)s %(name)-55s %(levelname)-8s %(message)s'))
log.addHandler(logfile)
# Parse command line options and deal with them.
# Use args supplied programatically if possible.
(options, args) = parser.parse_args(args) if args else parser.parse_args()
qt_args = []
if options.loglevel.lower() in ['d', 'debug']:
log.setLevel(logging.DEBUG)
print 'Logging to:', filename
elif options.loglevel.lower() in ['w', 'warning']:
log.setLevel(logging.WARNING)
else:
@ -261,11 +266,13 @@ def main(args=None):
app.setOrganizationName(u'OpenLP')
app.setOrganizationDomain(u'openlp.org')
if options.portable:
log.info(u'Running portable')
app.setApplicationName(u'OpenLPPortable')
Settings.setDefaultFormat(Settings.IniFormat)
# Get location OpenLPPortable.ini
app_path = AppLocation.get_directory(AppLocation.AppDir)
set_up_logging(os.path.abspath(os.path.join(app_path, u'..',
u'..', u'Other')))
log.info(u'Running portable')
portable_settings_file = os.path.abspath(os.path.join(app_path, u'..',
u'..', u'Data', u'OpenLP.ini'))
# Make this our settings file
@ -282,6 +289,7 @@ def main(args=None):
portable_settings.sync()
else:
app.setApplicationName(u'OpenLP')
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
app.setApplicationVersion(get_application_version()[u'version'])
# Instance check
if not options.testing:

View File

@ -130,15 +130,15 @@ class Ui_FormattingTagDialog(object):
translate('OpenLP.FormattingTagDialog', 'Description'))
self.tagLabel.setText(translate('OpenLP.FormattingTagDialog', 'Tag'))
self.startTagLabel.setText(
translate('OpenLP.FormattingTagDialog', 'Start tag'))
translate('OpenLP.FormattingTagDialog', 'Start HTML'))
self.endTagLabel.setText(
translate('OpenLP.FormattingTagDialog', 'End tag'))
translate('OpenLP.FormattingTagDialog', 'End HTML'))
self.deletePushButton.setText(UiStrings().Delete)
self.newPushButton.setText(UiStrings().New)
self.tagTableWidget.horizontalHeaderItem(0).setText(
translate('OpenLP.FormattingTagDialog', 'Description'))
self.tagTableWidget.horizontalHeaderItem(1).setText(
translate('OpenLP.FormattingTagDialog', 'Tag Id'))
translate('OpenLP.FormattingTagDialog', 'Tag'))
self.tagTableWidget.horizontalHeaderItem(2).setText(
translate('OpenLP.FormattingTagDialog', 'Start HTML'))
self.tagTableWidget.horizontalHeaderItem(3).setText(

View File

@ -49,7 +49,7 @@ class FormattingTagForm(QtGui.QDialog, Ui_FormattingTagDialog):
QtGui.QDialog.__init__(self, parent)
self.setupUi(self)
QtCore.QObject.connect(self.tagTableWidget,
QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onRowSelected)
QtCore.SIGNAL(u'itemSelectionChanged()'),self.onRowSelected)
QtCore.QObject.connect(self.newPushButton,
QtCore.SIGNAL(u'clicked()'), self.onNewClicked)
QtCore.QObject.connect(self.savePushButton,

View File

@ -226,7 +226,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
def onCurrentIdChanged(self, pageId):
"""
Detects Page changes and updates as approprate.
Detects Page changes and updates as appropriate.
"""
enabled = self.page(pageId) == self.areaPositionPage
self.setOption(QtGui.QWizard.HaveCustomButton1, enabled)

View File

@ -172,6 +172,11 @@ def _get_os_dir_path(dir_type):
u'Library', u'Application Support', u'openlp')
else:
if dir_type == AppLocation.LanguageDir:
prefixes = [u'/usr/local', u'/usr']
for prefix in prefixes:
directory = os.path.join(prefix, u'share', u'openlp')
if os.path.exists(directory):
return directory
return os.path.join(u'/usr', u'share', u'openlp')
if XDG_BASE_AVAILABLE:
if dir_type == AppLocation.ConfigDir:

View File

@ -569,7 +569,9 @@ class BibleMediaItem(MediaManagerItem):
if bible:
if QtGui.QMessageBox.question(self, UiStrings().ConfirmDelete,
unicode(translate('BiblesPlugin.MediaItem',
'Are you sure you want to delete "%s"?')) % bible,
'Are you sure you want to completely delete "%s" Bible from '
'OpenLP?\n\nYou will need to re-import this Bible to use it '
'again.'))% bible,
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No),
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.No:

View File

@ -61,14 +61,14 @@ class AuthorsForm(QtGui.QDialog, Ui_AuthorsDialog):
def onFirstNameEditTextEdited(self, display_name):
if not self._autoDisplayName:
return
if not self.lastNameEdit.text():
if self.lastNameEdit.text():
display_name = display_name + u' ' + self.lastNameEdit.text()
self.displayEdit.setText(display_name)
def onLastNameEditTextEdited(self, display_name):
if not self._autoDisplayName:
return
if not self.firstNameEdit.text():
if self.firstNameEdit.text():
display_name = self.firstNameEdit.text() + u' ' + display_name
self.displayEdit.setText(display_name)

View File

@ -476,7 +476,7 @@ def get_encoding(font, font_table, default_encoding, failed=False):
Dictionary of fonts and respective encodings.
``default_encoding``
The defaul encoding to use when font_table is empty or no font is used.
The default encoding to use when font_table is empty or no font is used.
``failed``
A boolean indicating whether the previous encoding didn't work.

View File

@ -48,15 +48,8 @@ class EasySlidesImport(SongImport):
Initialise the class.
"""
SongImport.__init__(self, manager, **kwargs)
self.commit = True
def doImport(self):
"""
Import either each of the files in self.importSources - each element of
which can be either a single opensong file, or a zipfile containing
multiple opensong files. If `self.commit` is set False, the
import will not be committed to the database (useful for test scripts).
"""
log.info(u'Importing EasySlides XML file %s', self.importSource)
parser = etree.XMLParser(remove_blank_text=True)
parsed_file = etree.parse(self.importSource, parser)

View File

@ -28,6 +28,7 @@
"""
The :mod:`importer` modules provides the general song import functionality.
"""
import os
import logging
from openlp.core.lib import translate
@ -44,6 +45,7 @@ from powersongimport import PowerSongImport
from ewimport import EasyWorshipSongImport
from songbeamerimport import SongBeamerImport
from songshowplusimport import SongShowPlusImport
from songproimport import SongProImport
from sundayplusimport import SundayPlusImport
from foilpresenterimport import FoilPresenterImport
from zionworximport import ZionWorxImport
@ -67,6 +69,13 @@ try:
except ImportError:
log.exception('Error importing %s', 'OooImport')
HAS_OOO = False
HAS_MEDIASHOUT = False
if os.name == u'nt':
try:
from mediashoutimport import MediaShoutImport
HAS_MEDIASHOUT = True
except ImportError:
log.exception('Error importing %s', 'MediaShoutImport')
class SongFormatSelect(object):
@ -100,6 +109,7 @@ class SongFormat(object):
``u'canDisable'``
Whether song format importer is disablable.
If ``True``, then ``u'disabledLabelText'`` must also be defined.
``u'availability'``
Whether song format importer is available.
@ -141,15 +151,16 @@ class SongFormat(object):
EasySlides = 6
EasyWorship = 7
FoilPresenter = 8
OpenSong = 9
PowerSong = 10
SongBeamer = 11
SongShowPlus = 12
SongsOfFellowship = 13
SundayPlus = 14
WordsOfWorship = 15
ZionWorx = 16
#CSV = 17
MediaShout = 9
OpenSong = 10
PowerSong = 11
SongBeamer = 12
SongPro = 13
SongShowPlus = 14
SongsOfFellowship = 15
SundayPlus = 16
WordsOfWorship = 17
ZionWorx = 18
# Set optional attribute defaults
__defaults__ = {
@ -158,7 +169,8 @@ class SongFormat(object):
u'selectMode': SongFormatSelect.MultipleFiles,
u'filter': u'',
u'comboBoxText': None,
u'disabledLabelText': u'',
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
'This importer has been disabled.'),
u'getFilesTitle': None,
u'invalidSourceMsg': None,
u'descriptionText': None
@ -240,6 +252,19 @@ class SongFormat(object):
u'filter': u'%s (*.foil)' % translate(
'SongsPlugin.ImportWizardForm', 'Foilpresenter Song Files')
},
MediaShout: {
u'name': u'MediaShout',
u'prefix': u'mediaShout',
u'canDisable': True,
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.mdb)' % translate('SongsPlugin.ImportWizardForm',
'MediaShout Database'),
u'disabledLabelText': translate('SongsPlugin.ImportWizardForm',
'The MediaShout importer is only supported on Windows. It has '
'been disabled due to a missing Python module. If you want to '
'use this importer, you will need to install the "pyodbc" '
'module.')
},
OpenSong: {
u'class': OpenSongImport,
u'name': WizardStrings.OS,
@ -260,6 +285,18 @@ class SongFormat(object):
u'filter': u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
'SongBeamer Files')
},
SongPro: {
u'class': SongProImport,
u'name': u'SongPro',
u'prefix': u'songPro',
u'selectMode': SongFormatSelect.SingleFile,
u'filter': u'%s (*.txt)' % translate('SongsPlugin.ImportWizardForm',
'SongPro Text Files'),
u'comboBoxText': translate('SongsPlugin.ImportWizardForm',
'SongPro (Export File)'),
u'descriptionText': translate('SongsPlugin.ImportWizardForm',
'In SongPro, export your songs using the File -> Export menu')
},
SongShowPlus: {
u'class': SongShowPlusImport,
u'name': u'SongShow Plus',
@ -302,12 +339,6 @@ class SongFormat(object):
'First convert your ZionWorx database to a CSV text file, as '
'explained in the <a href="http://manual.openlp.org/songs.html'
'#importing-from-zionworx">User Manual</a>.')
# },
# CSV: {
# u'class': CSVImport,
# u'name': WizardStrings.CSV,
# u'prefix': u'csv',
# u'selectMode': SongFormatSelect.SingleFile
}
}
@ -326,9 +357,11 @@ class SongFormat(object):
SongFormat.EasySlides,
SongFormat.EasyWorship,
SongFormat.FoilPresenter,
SongFormat.MediaShout,
SongFormat.OpenSong,
SongFormat.PowerSong,
SongFormat.SongBeamer,
SongFormat.SongPro,
SongFormat.SongShowPlus,
SongFormat.SongsOfFellowship,
SongFormat.SundayPlus,
@ -383,5 +416,8 @@ if HAS_SOF:
SongFormat.set(SongFormat.Generic, u'availability', HAS_OOO)
if HAS_OOO:
SongFormat.set(SongFormat.Generic, u'class', OooImport)
SongFormat.set(SongFormat.MediaShout, u'availability', HAS_MEDIASHOUT)
if HAS_MEDIASHOUT:
SongFormat.set(SongFormat.MediaShout, u'class', MediaShoutImport)
__all__ = [u'SongFormat', u'SongFormatSelect']

View File

@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Dave Warnock, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`mediashoutimport` module provides the functionality for importing
a MediaShout database into the OpenLP database.
"""
import re
import os
import pyodbc
from openlp.core.lib import translate
from openlp.plugins.songs.lib.songimport import SongImport
VERSE_TAGS = [u'V', u'C', u'B', u'O', u'P', u'I', u'E']
class MediaShoutImport(SongImport):
"""
The :class:`MediaShoutImport` class provides the ability to import the
MediaShout Access Database
"""
def __init__(self, manager, **kwargs):
"""
Initialise the MediaShout importer.
"""
SongImport.__init__(self, manager, **kwargs)
def doImport(self):
"""
Receive a single file to import.
"""
try:
conn = pyodbc.connect(u'DRIVER={Microsoft Access Driver (*.mdb)};'
u'DBQ=%s;PWD=6NOZ4eHK7k' % self.importSource)
except:
# Unfortunately no specific exception type
self.logError(self.importSource,
translate('SongsPlugin.MediaShoutImport',
'Unable to open the MediaShout database.'))
return
cursor = conn.cursor()
cursor.execute(u'SELECT Record, Title, Author, Copyright, '
u'SongID, CCLI, Notes FROM Songs ORDER BY Title')
songs = cursor.fetchall()
self.importWizard.progressBar.setMaximum(len(songs))
for song in songs:
if self.stopImportFlag:
break
cursor.execute(u'SELECT Type, Number, Text FROM Verses '
u'WHERE Record = %s ORDER BY Type, Number' % song.Record)
verses = cursor.fetchall()
cursor.execute(u'SELECT Type, Number, POrder FROM PlayOrder '
u'WHERE Record = %s ORDER BY POrder' % song.Record)
verse_order = cursor.fetchall()
cursor.execute(u'SELECT Name FROM Themes INNER JOIN SongThemes '
u'ON SongThemes.ThemeId = Themes.ThemeId '
u'WHERE SongThemes.Record = %s' % song.Record)
topics = cursor.fetchall()
cursor.execute(u'SELECT Name FROM Groups INNER JOIN SongGroups '
u'ON SongGroups.GroupId = Groups.GroupId '
u'WHERE SongGroups.Record = %s' % song.Record)
topics += cursor.fetchall()
self.processSong(song, verses, verse_order, topics)
def processSong(self, song, verses, verse_order, topics):
"""
Create the song, i.e. title, verse etc.
"""
self.setDefaults()
self.title = song.Title
self.parseAuthor(song.Author)
self.addCopyright(song.Copyright)
self.comments = song.Notes
for topic in topics:
self.topics.append(topic.Name)
if u'-' in song.SongID:
self.songBookName, self.songNumber = song.SongID.split(u'-', 1)
else:
self.songBookName = song.SongID
for verse in verses:
tag = VERSE_TAGS[verse.Type] + unicode(verse.Number) \
if verse.Type < len(VERSE_TAGS) else u'O'
self.addVerse(verse.Text, tag)
for order in verse_order:
if order.Type < len(VERSE_TAGS):
self.verseOrderList.append(VERSE_TAGS[order.Type]
+ unicode(order.Number))
self.finish()

View File

@ -0,0 +1,143 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Dave Warnock, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`songproimport` module provides the functionality for importing SongPro
songs into the OpenLP database.
"""
import re
import os
from openlp.core.lib import translate
from openlp.plugins.songs.lib import strip_rtf
from openlp.plugins.songs.lib.songimport import SongImport
class SongProImport(SongImport):
"""
The :class:`SongProImport` class provides the ability to import song files
from SongPro export files.
**SongPro Song File Format:**
SongPro has the option to export under its File menu
This produces files containing single or multiple songs
The file is text with lines tagged with # followed by an identifier.
This is documented here: http://creationsoftware.com/ImportIdentifiers.php
An example here: http://creationsoftware.com/ExampleImportingManySongs.txt
#A - next line is the Song Author
#B - the lines following until next tagged line are the "Bridge" words
(can be in rtf or plain text) which we map as B1
#C - the lines following until next tagged line are the chorus words
(can be in rtf or plain text)
which we map as C1
#D - the lines following until next tagged line are the "Ending" words
(can be in rtf or plain text) which we map as E1
#E - this song ends here, so we process the song -
and start again at the next line
#G - next line is the Group
#M - next line is the Song Number
#N - next line are Notes
#R - next line is the SongCopyright
#O - next line is the Verse Sequence
#T - next line is the Song Title
#1 - #7 the lines following until next tagged line are the verse x words
(can be in rtf or plain text)
"""
def __init__(self, manager, **kwargs):
"""
Initialise the SongPro importer.
"""
SongImport.__init__(self, manager, **kwargs)
def doImport(self):
"""
Receive a single file or a list of files to import.
"""
self.encoding = None
with open(self.importSource, 'r') as songs_file:
self.importWizard.progressBar.setMaximum(0)
tag = u''
text = u''
for file_line in songs_file:
if self.stopImportFlag:
break
file_line = unicode(file_line, u'cp1252')
file_text = file_line.rstrip()
if file_text and file_text[0] == u'#':
self.processSection(tag, text.rstrip())
tag = file_text[1:]
text = u''
else:
text += file_line
def processSection(self, tag, text):
"""
Process a section of the song, i.e. title, verse etc.
"""
if tag == u'T':
self.setDefaults()
if text:
self.title = text
return
elif tag == u'E':
self.finish()
return
if u'rtf1' in text:
text, self.encoding = strip_rtf(text, self.encoding)
text = text.rstrip()
if not text:
return
if tag == u'A':
self.parseAuthor(text)
elif tag in [u'B', u'C']:
self.addVerse(text, tag)
elif tag == u'D':
self.addVerse(text, u'E')
elif tag == u'G':
self.topics.append(text)
elif tag == u'M':
matches = re.findall(r'\d+', text)
if matches:
self.songNumber = matches[-1]
self.songBookName = text[:text.rfind(self.songNumber)]
elif tag == u'N':
self.comments = text
elif tag == u'O':
for char in text:
if char == u'C':
self.verseOrderList.append(u'C1')
elif char == u'B':
self.verseOrderList.append(u'B1')
elif char == u'D':
self.verseOrderList.append(u'E1')
elif u'1' <= char <= u'7':
self.verseOrderList.append(u'V' + char)
elif tag == u'R':
self.addCopyright(text)
elif u'1' <= tag <= u'7':
self.addVerse(text, u'V' + tag[1:])

View File

@ -37,6 +37,9 @@ from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
# Used to strip control chars (except 10=LF, 13=CR)
CONTROL_CHARS_MAP = dict.fromkeys(range(10) + [11, 12] + range(14,32) + [127])
class ZionWorxImport(SongImport):
"""
The :class:`ZionWorxImport` class provides the ability to import songs
@ -78,13 +81,10 @@ class ZionWorxImport(SongImport):
"""
Receive a CSV file (from a ZionWorx database dump) to import.
"""
# Used to strip control chars (10=LF, 13=CR, 127=DEL)
self.control_chars_map = dict.fromkeys(
range(10) + [11, 12] + range(14,32) + [127])
with open(self.importSource, 'rb') as songs_file:
fieldnames = [u'SongNum', u'Title1', u'Title2', u'Lyrics',
field_names = [u'SongNum', u'Title1', u'Title2', u'Lyrics',
u'Writer', u'Copyright', u'Keywords', u'DefaultStyle']
songs_reader = csv.DictReader(songs_file, fieldnames)
songs_reader = csv.DictReader(songs_file, field_names)
try:
records = list(songs_reader)
except csv.Error, e:
@ -140,4 +140,4 @@ class ZionWorxImport(SongImport):
"""
# This encoding choice seems OK. ZionWorx has no option for setting the
# encoding for its songs, so we assume encoding is always the same.
return unicode(str, u'cp1252').translate(self.control_chars_map)
return unicode(str, u'cp1252').translate(CONTROL_CHARS_MAP)

34
resources/__init__.py Normal file
View File

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2012 Raoul Snyman #
# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Edwin Lunando, Joshua Miller, Stevan Pettit, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Simon Scudder, Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Dave Warnock, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The :mod:`resources` module contains a bunch of resources for OpenLP.
DO NOT REMOVE THIS FILE, IT IS REQUIRED FOR INCLUDING THE RESOURCES ON SOME
PLATFORMS!
"""

View File

@ -28,10 +28,56 @@
###############################################################################
from setuptools import setup, find_packages
import re
VERSION_FILE = 'openlp/.version'
SPLIT_ALPHA_DIGITS = re.compile(r'(\d+|\D+)')
def try_int(s):
"""
Convert string s to an integer if possible. Fail silently and return
the string as-is if it isn't an integer.
``s``
The string to try to convert.
"""
try:
return int(s)
except Exception:
return s
def natural_sort_key(s):
"""
Return a tuple by which s is sorted.
``s``
A string value from the list we want to sort.
"""
return map(try_int, SPLIT_ALPHA_DIGITS.findall(s))
def natural_compare(a, b):
"""
Compare two strings naturally and return the result.
``a``
A string to compare.
``b``
A string to compare.
"""
return cmp(natural_sort_key(a), natural_sort_key(b))
def natural_sort(seq, compare=natural_compare):
"""
Returns a copy of seq, sorted by natural string sort.
"""
import copy
temp = copy.copy(seq)
temp.sort(compare)
return temp
try:
# Try to import Bazaar
from bzrlib.branch import Branch
b = Branch.open_containing('.')[0]
b.lock_read()
@ -46,7 +92,8 @@ try:
if revision_id in tags:
version = u'%s' % tags[revision_id][0]
else:
version = '%s-bzr%s' % (sorted(b.tags.get_tag_dict().keys())[-1], revno)
version = '%s-bzr%s' % \
(natural_sort(b.tags.get_tag_dict().keys())[-1], revno)
ver_file = open(VERSION_FILE, u'w')
ver_file.write(version)
ver_file.close()