This commit is contained in:
rimach 2010-12-08 22:06:00 +01:00
commit 79bb7457d3
5 changed files with 202 additions and 57 deletions

View File

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

View File

@ -536,7 +536,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
return False
if self.song.verse_order:
order = []
order_names = self.song.verse_order.split(u' ')
order_names = self.song.verse_order.split()
for item in order_names:
if len(item) == 1:
order.append(item.lower() + u'1')

46
openlp/plugins/songs/lib/cclifileimport.py Executable file → Normal file
View File

@ -76,7 +76,12 @@ class CCLIFileImport(SongImport):
lines = []
if os.path.isfile(filename):
detect_file = open(filename, u'r')
details = chardet.detect(detect_file.read(2048))
detect_content = detect_file.read(2048)
try:
unicode(detect_content, u'utf-8')
details = {'confidence': 1, 'encoding': 'utf-8'}
except UnicodeDecodeError:
details = chardet.detect(detect_content)
detect_file.close()
infile = codecs.open(filename, u'r', details['encoding'])
lines = infile.readlines()
@ -165,6 +170,7 @@ class CCLIFileImport(SongImport):
song_words = line[6:].strip()
#Unhandled usr keywords:Type,Version,Admin,Themes,Keys
#Process Fields and words sections
check_first_verse_line = False
field_list = song_fields.split(u'/t')
words_list = song_words.split(u'/t')
for counter in range(0, len(field_list)):
@ -176,10 +182,25 @@ class CCLIFileImport(SongImport):
verse_type = u'B'
else: #Other
verse_type = u'O'
check_first_verse_line = True
verse_text = unicode(words_list[counter])
verse_text = verse_text.replace("/n", "\n")
verse_lines = verse_text.split(u'\n', 1)
if check_first_verse_line:
if verse_lines[0].startswith(u'(PRE-CHORUS'):
verse_type = u'P'
log.debug(u'USR verse PRE-CHORUS: %s', verse_lines[0] )
verse_text = verse_lines[1]
elif verse_lines[0].startswith(u'(BRIDGE'):
verse_type = u'B'
log.debug(u'USR verse BRIDGE')
verse_text = verse_lines[1]
elif verse_lines[0].startswith(u'('):
verse_type = u'O'
verse_text = verse_lines[1]
if len(verse_text) > 0:
self.add_verse(verse_text, verse_type)
check_first_verse_line = False
#Handle multiple authors
author_list = song_author.split(u'/')
if len(author_list) < 2:
@ -228,6 +249,7 @@ class CCLIFileImport(SongImport):
log.debug(u'TXT file text: %s', textList)
self.set_defaults()
line_number = 0
check_first_verse_line = False
verse_text = u''
song_comments = u''
song_copyright = u''
@ -265,16 +287,32 @@ class CCLIFileImport(SongImport):
elif verse_desc_parts[0].startswith(u'Br'):
verse_type = u'B'
else:
#we need to analyse the next line for
#verse type, so set flag
verse_type = u'O'
check_first_verse_line = True
verse_number = verse_desc_parts[1]
else:
verse_type = u'O'
verse_number = 1
verse_start = True
else:
# We have verse content or the start of the
# last part. Add l so as to keep the CRLF
verse_text = verse_text + line
#check first line for verse type
if check_first_verse_line:
if line.startswith(u'(PRE-CHORUS'):
verse_type = u'P'
elif line.startswith(u'(BRIDGE'):
verse_type = u'B'
# Handle all other misc types
elif line.startswith(u'('):
verse_type = u'O'
else:
verse_text = verse_text + line
check_first_verse_line = False
else:
# We have verse content or the start of the
# last part. Add l so as to keep the CRLF
verse_text = verse_text + line
else:
#line_number=2, copyright
if line_number == 2:

View File

@ -366,7 +366,7 @@ class SongMediaItem(MediaManagerItem):
verse[1][:30], unicode(verse[1]), verseTag)
else:
# Loop through the verse list and expand the song accordingly.
for order in song.verse_order.upper().split(u' '):
for order in song.verse_order.upper().split():
if len(order) == 0:
break
for verse in verseList:
@ -390,7 +390,7 @@ class SongMediaItem(MediaManagerItem):
raw_footer.append(author_list)
raw_footer.append(song.copyright )
raw_footer.append(unicode(
translate('SongsPlugin.MediaItem', 'CCLI Licence: ') +
translate('SongsPlugin.MediaItem', 'CCLI License: ') +
QtCore.QSettings().value(u'general/ccli number',
QtCore.QVariant(u'')).toString()))
service_item.raw_footer = raw_footer

View File

@ -27,8 +27,11 @@
The :mod:`olp1import` module provides the functionality for importing
openlp.org 1.x song databases into the current installation database.
"""
from PyQt4 import QtGui
import logging
import chardet
from chardet.universaldetector import UniversalDetector
import sqlite
from openlp.core.lib import translate
@ -56,60 +59,38 @@ class OpenLP1SongImport(SongImport):
SongImport.__init__(self, manager)
self.import_source = kwargs[u'filename']
def decode_string(self, raw, guess):
"""
Use chardet to detect the encoding of the raw string, and convert it
to unicode.
``raw``
The raw bytestring to decode.
``guess``
What chardet guessed the encoding to be.
"""
if guess[u'confidence'] < 0.8:
codec = u'windows-1252'
else:
codec = guess[u'encoding']
try:
decoded = unicode(raw, codec)
self.last_encoding = codec
except UnicodeDecodeError:
log.exception(
u'Error in detecting openlp.org 1.x database encoding.')
try:
decoded = unicode(raw, self.last_encoding)
except UnicodeDecodeError:
# possibly show an error form
#self.import_wizard.showError(u'There was a problem '
# u'detecting the encoding of a string')
decoded = raw
return decoded
def do_import(self):
"""
Run the import for an openlp.org 1.x song database.
"""
# Connect to the database
connection = sqlite.connect(self.import_source)
encoding = self.get_encoding()
if not encoding:
return False
connection = sqlite.connect(self.import_source, mode=0444,
encoding=(encoding, 'replace'))
cursor = connection.cursor()
# Determine if we're using a new or an old DB
cursor.execute(u'SELECT name FROM sqlite_master '
u'WHERE type = \'table\' AND name = \'tracks\'')
table_list = cursor.fetchall()
new_db = len(table_list) > 0
new_db = len(cursor.fetchall()) > 0
# Count the number of records we need to import, for the progress bar
cursor.execute(u'-- types int')
cursor.execute(u'SELECT COUNT(songid) FROM songs')
count = int(cursor.fetchone()[0])
count = cursor.fetchone()[0]
success = True
self.import_wizard.importProgressBar.setMaximum(count)
# "cache" our list of authors
cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT authorid, authorname FROM authors')
authors = cursor.fetchall()
if new_db:
# "cache" our list of tracks
cursor.execute(u'-- types int, unicode')
cursor.execute(u'SELECT trackid, fulltrackname FROM tracks')
tracks = cursor.fetchall()
# Import the songs
cursor.execute(u'-- types int, unicode, unicode, unicode')
cursor.execute(u'SELECT songid, songtitle, lyrics || \'\' AS lyrics, '
u'copyrightinfo FROM songs')
songs = cursor.fetchall()
@ -119,16 +100,19 @@ class OpenLP1SongImport(SongImport):
success = False
break
song_id = song[0]
guess = chardet.detect(song[2])
title = self.decode_string(song[1], guess)
lyrics = self.decode_string(song[2], guess).replace(u'\r', u'')
copyright = self.decode_string(song[3], guess)
title = song[1]
lyrics = song[2].replace(u'\r\n', u'\n')
copyright = song[3]
self.import_wizard.incrementProgressBar(
unicode(translate('SongsPlugin.ImportWizardForm',
'Importing "%s"...')) % title)
self.title = title
self.process_song_text(lyrics)
verses = lyrics.split(u'\n\n')
for verse in verses:
if verse.strip() != u'':
self.add_verse(verse.strip())
self.add_copyright(copyright)
cursor.execute(u'-- types int')
cursor.execute(u'SELECT authorid FROM songauthors '
u'WHERE songid = %s' % song_id)
author_ids = cursor.fetchall()
@ -138,12 +122,13 @@ class OpenLP1SongImport(SongImport):
break
for author in authors:
if author[0] == author_id[0]:
self.parse_author(self.decode_string(author[1], guess))
self.parse_author(author[1])
break
if self.stop_import_flag:
success = False
break
if new_db:
cursor.execute(u'-- types int')
cursor.execute(u'SELECT trackid FROM songtracks '
u'WHERE songid = %s ORDER BY listindex' % song_id)
track_ids = cursor.fetchall()
@ -153,8 +138,7 @@ class OpenLP1SongImport(SongImport):
break
for track in tracks:
if track[0] == track_id[0]:
self.add_media_file(self.decode_string(track[1],
guess))
self.add_media_file(track[1])
break
if self.stop_import_flag:
success = False
@ -162,3 +146,103 @@ class OpenLP1SongImport(SongImport):
self.finish()
return success
def get_encoding(self):
"""
Detect character encoding of an openlp.org 1.x song database.
"""
# Connect to the database
connection = sqlite.connect(self.import_source, mode=0444)
cursor = connection.cursor()
detector = UniversalDetector()
# detect charset by authors
cursor.execute(u'SELECT authorname FROM authors')
authors = cursor.fetchall()
for author in authors:
detector.feed(author[0])
if detector.done:
detector.close()
return detector.result[u'encoding']
# detect charset by songs
cursor.execute(u'SELECT songtitle, copyrightinfo, '
u'lyrics || \'\' AS lyrics FROM songs')
songs = cursor.fetchall()
for index in [0, 1, 2]:
for song in songs:
detector.feed(song[index])
if detector.done:
detector.close()
return detector.result[u'encoding']
# detect charset by songs
cursor.execute(u'SELECT name FROM sqlite_master '
u'WHERE type = \'table\' AND name = \'tracks\'')
if len(cursor.fetchall()) > 0:
cursor.execute(u'SELECT fulltrackname FROM tracks')
tracks = cursor.fetchall()
for track in tracks:
detector.feed(track[0])
if detector.done:
detector.close()
return detector.result[u'encoding']
detector.close()
guess = detector.result[u'encoding']
# map chardet result to compatible windows standard code page
codepage_mapping = {'IBM866': u'cp866', 'TIS-620': u'cp874',
'SHIFT_JIS': u'cp932', 'GB2312': u'cp936', 'HZ-GB-2312': u'cp936',
'EUC-KR': u'cp949', 'Big5': u'cp950', 'ISO-8859-2': u'cp1250',
'windows-1250': u'cp1250', 'windows-1251': u'cp1251',
'windows-1252': u'cp1252', 'ISO-8859-7': u'cp1253',
'windows-1253': u'cp1253', 'ISO-8859-8': u'cp1255',
'windows-1255': u'cp1255'}
if guess in codepage_mapping:
guess = codepage_mapping[guess]
else:
guess = u'cp1252'
# Show dialog for encoding selection
encodings = [(u'cp1256', translate('SongsPlugin.OpenLP1SongImport',
'Arabic (CP-1256)')),
(u'cp1257', translate('SongsPlugin.OpenLP1SongImport',
'Baltic (CP-1257)')),
(u'cp1250', translate('SongsPlugin.OpenLP1SongImport',
'Central European (CP-1250)')),
(u'cp1251', translate('SongsPlugin.OpenLP1SongImport',
'Cyrillic (CP-1251)')),
(u'cp1253', translate('SongsPlugin.OpenLP1SongImport',
'Greek (CP-1253)')),
(u'cp1255', translate('SongsPlugin.OpenLP1SongImport',
'Hebrew (CP-1255)')),
(u'cp932', translate('SongsPlugin.OpenLP1SongImport',
'Japanese (CP-932)')),
(u'cp949', translate('SongsPlugin.OpenLP1SongImport',
'Korean (CP-949)')),
(u'cp936', translate('SongsPlugin.OpenLP1SongImport',
'Simplified Chinese (CP-936)')),
(u'cp874', translate('SongsPlugin.OpenLP1SongImport',
'Thai (CP-874)')),
(u'cp950', translate('SongsPlugin.OpenLP1SongImport',
'Traditional Chinese (CP-950)')),
(u'cp1254', translate('SongsPlugin.OpenLP1SongImport',
'Turkish (CP-1254)')),
(u'cp1258', translate('SongsPlugin.OpenLP1SongImport',
'Vietnam (CP-1258)')),
(u'cp1252', translate('SongsPlugin.OpenLP1SongImport',
'Western European (CP-1252)'))]
encoding_index = 0
for index in range(len(encodings)):
if guess == encodings[index][0]:
encoding_index = index
break
chosen_encoding = QtGui.QInputDialog.getItem(None,
translate('SongsPlugin.OpenLP1SongImport',
'Database Character Encoding'),
translate('SongsPlugin.OpenLP1SongImport',
'The codepage setting is responsible\n'
'for the correct character representation.\n'
'Usually you are fine with the preselected choise.'),
[pair[1] for pair in encodings], encoding_index, False)
if not chosen_encoding[1]:
return None
return filter(lambda item: item[1] == chosen_encoding[0],
encodings)[0][0]