Head 2074

This commit is contained in:
Tim Bentley 2012-10-06 10:21:46 +01:00
commit 0c214cbf6c
36 changed files with 22352 additions and 19165 deletions

View File

@ -674,6 +674,7 @@ class AdvancedTab(SettingsTab):
options = QtGui.QFileDialog.ShowDirsOnly)) options = QtGui.QFileDialog.ShowDirsOnly))
# Set the new data path. # Set the new data path.
if new_data_path: if new_data_path:
new_data_path = os.path.normpath(new_data_path)
if self.currentDataPath.lower() == new_data_path.lower(): if self.currentDataPath.lower() == new_data_path.lower():
self.onDataDirectoryCancelButtonClicked() self.onDataDirectoryCancelButtonClicked()
return return

View File

@ -971,6 +971,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
setting_sections.extend([self.themesSettingsSection]) setting_sections.extend([self.themesSettingsSection])
setting_sections.extend([self.displayTagsSection]) setting_sections.extend([self.displayTagsSection])
setting_sections.extend([self.headerSection]) setting_sections.extend([self.headerSection])
setting_sections.extend([u'crashreport'])
# Add plugin sections. # Add plugin sections.
for plugin in self.pluginManager.plugins: for plugin in self.pluginManager.plugins:
setting_sections.extend([plugin.name]) setting_sections.extend([plugin.name])

View File

@ -28,6 +28,7 @@
import logging import logging
import os import os
import sys
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, Receiver, translate from openlp.core.lib import OpenLPToolbar, Receiver, translate
@ -105,8 +106,12 @@ class MediaController(object):
AppLocation.get_directory(AppLocation.AppDir), AppLocation.get_directory(AppLocation.AppDir),
u'core', u'ui', u'media') u'core', u'ui', u'media')
for filename in os.listdir(controller_dir): for filename in os.listdir(controller_dir):
if filename.endswith(u'player.py') and not \ # TODO vlc backend is not yet working on Mac OS X.
filename == 'media_player.py': # For now just ignore vlc backend on Mac OS X.
if sys.platform == 'darwin' and filename == 'vlcplayer.py':
log.warn(u'Disabling vlc media player')
continue
if filename.endswith(u'player.py'):
path = os.path.join(controller_dir, filename) path = os.path.join(controller_dir, filename)
if os.path.isfile(path): if os.path.isfile(path):
modulename = u'openlp.core.ui.media.' + \ modulename = u'openlp.core.ui.media.' + \
@ -114,7 +119,9 @@ class MediaController(object):
log.debug(u'Importing controller %s', modulename) log.debug(u'Importing controller %s', modulename)
try: try:
__import__(modulename, globals(), locals(), []) __import__(modulename, globals(), locals(), [])
except ImportError: # On some platforms importing vlc.py might cause
# also OSError exceptions. (e.g. Mac OS X)
except (ImportError, OSError):
log.warn(u'Failed to import %s on path %s', log.warn(u'Failed to import %s on path %s',
modulename, path) modulename, path)
controller_classes = MediaPlayer.__subclasses__() controller_classes = MediaPlayer.__subclasses__()

View File

@ -48,7 +48,48 @@ import sys
from inspect import getargspec from inspect import getargspec
__version__ = "N/A" __version__ = "N/A"
build_date = "Thu Jun 14 15:22:46 2012" build_date = "Fri Sep 28 22:48:50 2012"
if sys.version_info[0] > 2:
str = str
unicode = str
bytes = bytes
basestring = (str, bytes)
PYTHON3 = True
def str_to_bytes(s):
"""Translate string or bytes to bytes.
"""
if isinstance(s, str):
return bytes(s, sys.getfilesystemencoding())
else:
return s
def bytes_to_str(b):
"""Translate bytes to string.
"""
if isinstance(b, bytes):
return b.decode(sys.getfilesystemencoding())
else:
return b
else:
str = str
unicode = unicode
bytes = str
basestring = basestring
PYTHON3 = False
def str_to_bytes(s):
"""Translate string or bytes to bytes.
"""
if isinstance(s, unicode):
return s.encode(sys.getfilesystemencoding())
else:
return s
def bytes_to_str(b):
"""Translate bytes to unicode string.
"""
if isinstance(b, str):
return unicode(b, sys.getfilesystemencoding())
# Internal guard to prevent internal classes to be directly # Internal guard to prevent internal classes to be directly
# instanciated. # instanciated.
@ -220,7 +261,7 @@ def string_result(result, func, arguments):
""" """
if result: if result:
# make a python string copy # make a python string copy
s = ctypes.string_at(result) s = bytes_to_str(ctypes.string_at(result))
# free original string ptr # free original string ptr
libvlc_free(result) libvlc_free(result)
return s return s
@ -241,16 +282,32 @@ class FILE(ctypes.Structure):
pass pass
FILE_ptr = ctypes.POINTER(FILE) FILE_ptr = ctypes.POINTER(FILE)
PyFile_FromFile = ctypes.pythonapi.PyFile_FromFile if PYTHON3:
PyFile_FromFile.restype = ctypes.py_object PyFile_FromFd = ctypes.pythonapi.PyFile_FromFd
PyFile_FromFile.argtypes = [FILE_ptr, PyFile_FromFd.restype = ctypes.py_object
ctypes.c_char_p, PyFile_FromFd.argtypes = [ctypes.c_int,
ctypes.c_char_p, ctypes.c_char_p,
ctypes.CFUNCTYPE(ctypes.c_int, FILE_ptr)] ctypes.c_char_p,
ctypes.c_int,
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.c_int ]
PyFile_AsFile = ctypes.pythonapi.PyFile_AsFile PyFile_AsFd = ctypes.pythonapi.PyObject_AsFileDescriptor
PyFile_AsFile.restype = FILE_ptr PyFile_AsFd.restype = ctypes.c_int
PyFile_AsFile.argtypes = [ctypes.py_object] PyFile_AsFd.argtypes = [ctypes.py_object]
else:
PyFile_FromFile = ctypes.pythonapi.PyFile_FromFile
PyFile_FromFile.restype = ctypes.py_object
PyFile_FromFile.argtypes = [FILE_ptr,
ctypes.c_char_p,
ctypes.c_char_p,
ctypes.CFUNCTYPE(ctypes.c_int, FILE_ptr)]
PyFile_AsFile = ctypes.pythonapi.PyFile_AsFile
PyFile_AsFile.restype = FILE_ptr
PyFile_AsFile.argtypes = [ctypes.py_object]
# Generated enum types # # Generated enum types #
@ -1155,6 +1212,8 @@ class Instance(_Ctype):
# no parameters passed, for win32 and MacOS, # no parameters passed, for win32 and MacOS,
# specify the plugin_path if detected earlier # specify the plugin_path if detected earlier
args = ['vlc', '--plugin-path=' + plugin_path] args = ['vlc', '--plugin-path=' + plugin_path]
if PYTHON3:
args = [ str_to_bytes(a) for a in args ]
return libvlc_new(len(args), args) return libvlc_new(len(args), args)
def media_player_new(self, uri=None): def media_player_new(self, uri=None):
@ -1195,12 +1254,12 @@ class Instance(_Ctype):
""" """
if ':' in mrl and mrl.index(':') > 1: if ':' in mrl and mrl.index(':') > 1:
# Assume it is a URL # Assume it is a URL
m = libvlc_media_new_location(self, mrl) m = libvlc_media_new_location(self, str_to_bytes(mrl))
else: else:
# Else it should be a local path. # Else it should be a local path.
m = libvlc_media_new_path(self, mrl) m = libvlc_media_new_path(self, str_to_bytes(mrl))
for o in options: for o in options:
libvlc_media_add_option(m, o) libvlc_media_add_option(m, str_to_bytes(o))
m._instance = self m._instance = self
return m return m
@ -1664,6 +1723,9 @@ class LogIterator(_Ctype):
return i.contents return i.contents
raise StopIteration raise StopIteration
def __next__(self):
return self.next()
def free(self): def free(self):
'''Frees memory allocated by L{log_get_iterator}(). '''Frees memory allocated by L{log_get_iterator}().
@ -3125,18 +3187,6 @@ def libvlc_vprinterr(fmt, ap):
ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p) ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p)
return f(fmt, ap) return f(fmt, ap)
def libvlc_printerr(fmt, args):
'''Sets the LibVLC error status and message for the current thread.
Any previous error is overridden.
@param fmt: the format string.
@param args: the arguments.
@return: a nul terminated string in any case.
'''
f = _Cfunctions.get('libvlc_printerr', None) or \
_Cfunction('libvlc_printerr', ((1,), (1,),), None,
ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p)
return f(fmt, args)
def libvlc_new(argc, argv): def libvlc_new(argc, argv):
'''Create and initialize a libvlc instance. '''Create and initialize a libvlc instance.
This functions accept a list of "command line" arguments similar to the This functions accept a list of "command line" arguments similar to the
@ -5828,11 +5878,12 @@ def libvlc_vlm_get_event_manager(p_instance):
return f(p_instance) return f(p_instance)
# 2 function(s) blacklisted: # 3 function(s) blacklisted:
# libvlc_printerr
# libvlc_set_exit_handler # libvlc_set_exit_handler
# libvlc_video_set_callbacks # libvlc_video_set_callbacks
# 18 function(s) not wrapped as methods: # 17 function(s) not wrapped as methods:
# libvlc_audio_output_list_release # libvlc_audio_output_list_release
# libvlc_clearerr # libvlc_clearerr
# libvlc_clock # libvlc_clock
@ -5847,7 +5898,6 @@ def libvlc_vlm_get_event_manager(p_instance):
# libvlc_log_unsubscribe # libvlc_log_unsubscribe
# libvlc_module_description_list_release # libvlc_module_description_list_release
# libvlc_new # libvlc_new
# libvlc_printerr
# libvlc_track_description_list_release # libvlc_track_description_list_release
# libvlc_track_description_release # libvlc_track_description_release
# libvlc_vprinterr # libvlc_vprinterr
@ -5908,7 +5958,7 @@ def libvlc_hex_version():
"""Return the libvlc version in hex or 0 if unavailable. """Return the libvlc version in hex or 0 if unavailable.
""" """
try: try:
return _dot2int(libvlc_get_version().split()[0]) return _dot2int(bytes_to_str(libvlc_get_version()).split()[0])
except ValueError: except ValueError:
return 0 return 0
@ -5957,8 +6007,8 @@ if __name__ == '__main__':
"""Print libvlc version""" """Print libvlc version"""
try: try:
print('Build date: %s (%#x)' % (build_date, hex_version())) print('Build date: %s (%#x)' % (build_date, hex_version()))
print('LibVLC version: %s (%#x)' % (libvlc_get_version(), libvlc_hex_version())) print('LibVLC version: %s (%#x)' % (bytes_to_str(libvlc_get_version()), libvlc_hex_version()))
print('LibVLC compiler: %s' % libvlc_get_compiler()) print('LibVLC compiler: %s' % bytes_to_str(libvlc_get_compiler()))
if plugin_path: if plugin_path:
print('Plugin path: %s' % plugin_path) print('Plugin path: %s' % plugin_path)
except: except:
@ -5997,7 +6047,7 @@ if __name__ == '__main__':
player.video_set_marquee_int(VideoMarqueeOption.Refresh, 1000) # millisec (or sec?) player.video_set_marquee_int(VideoMarqueeOption.Refresh, 1000) # millisec (or sec?)
##t = '$L / $D or $P at $T' ##t = '$L / $D or $P at $T'
t = '%Y-%m-%d %H:%M:%S' t = '%Y-%m-%d %H:%M:%S'
player.video_set_marquee_string(VideoMarqueeOption.Text, t) player.video_set_marquee_string(VideoMarqueeOption.Text, str_to_bytes(t))
# Some event manager examples. Note, the callback can be any Python # Some event manager examples. Note, the callback can be any Python
# callable and does not need to be decorated. Optionally, specify # callable and does not need to be decorated. Optionally, specify
@ -6017,7 +6067,7 @@ if __name__ == '__main__':
print_version() print_version()
media = player.get_media() media = player.get_media()
print('State: %s' % player.get_state()) print('State: %s' % player.get_state())
print('Media: %s' % media.get_mrl()) print('Media: %s' % bytes_to_str(media.get_mrl()))
print('Track: %s/%s' % (player.video_get_track(), player.video_get_track_count())) print('Track: %s/%s' % (player.video_get_track(), player.video_get_track_count()))
print('Current time: %s/%s' % (player.get_time(), media.get_duration())) print('Current time: %s/%s' % (player.get_time(), media.get_duration()))
print('Position: %s' % player.get_position()) print('Position: %s' % player.get_position())
@ -6078,7 +6128,7 @@ if __name__ == '__main__':
print('Press q to quit, ? to get help.%s' % os.linesep) print('Press q to quit, ? to get help.%s' % os.linesep)
while True: while True:
k = getch().decode('utf8') # Python 3+ k = getch()
print('> %s' % k) print('> %s' % k)
if k in keybindings: if k in keybindings:
keybindings[k]() keybindings[k]()

View File

@ -157,7 +157,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
u'outlineColorButton', self.outlineColorButton) u'outlineColorButton', self.outlineColorButton)
self.mainAreaPage.registerField( self.mainAreaPage.registerField(
u'outlineSizeSpinBox', self.outlineSizeSpinBox) u'outlineSizeSpinBox', self.outlineSizeSpinBox)
self.mainAreaPage.registerField(u'shadowCheckBox', self.shadowCheckBox) self.mainAreaPage.registerField(
u'shadowCheckBox', self.shadowCheckBox)
self.mainAreaPage.registerField( self.mainAreaPage.registerField(
u'mainBoldCheckBox', self.mainBoldCheckBox) u'mainBoldCheckBox', self.mainBoldCheckBox)
self.mainAreaPage.registerField( self.mainAreaPage.registerField(
@ -168,8 +169,10 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
u'shadowSizeSpinBox', self.shadowSizeSpinBox) u'shadowSizeSpinBox', self.shadowSizeSpinBox)
self.mainAreaPage.registerField( self.mainAreaPage.registerField(
u'footerSizeSpinBox', self.footerSizeSpinBox) u'footerSizeSpinBox', self.footerSizeSpinBox)
self.areaPositionPage.registerField(u'mainPositionX', self.mainXSpinBox) self.areaPositionPage.registerField(
self.areaPositionPage.registerField(u'mainPositionY', self.mainYSpinBox) u'mainPositionX', self.mainXSpinBox)
self.areaPositionPage.registerField(
u'mainPositionY', self.mainYSpinBox)
self.areaPositionPage.registerField( self.areaPositionPage.registerField(
u'mainPositionWidth', self.mainWidthSpinBox) u'mainPositionWidth', self.mainWidthSpinBox)
self.areaPositionPage.registerField( self.areaPositionPage.registerField(
@ -202,7 +205,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
""" """
Updates the lines on a page on the wizard Updates the lines on a page on the wizard
""" """
self.mainLineCountLabel.setText(unicode(translate('OpenLP.ThemeForm', self.mainLineCountLabel.setText(unicode(translate(
'OpenLP.ThemeWizard',
'(approximately %d lines per slide)')) % int(lines)) '(approximately %d lines per slide)')) % int(lines))
def resizeEvent(self, event=None): def resizeEvent(self, event=None):
@ -224,6 +228,19 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.previewBoxLabel.setFixedSize(pixmapWidth + 2 * frameWidth, self.previewBoxLabel.setFixedSize(pixmapWidth + 2 * frameWidth,
pixmapHeight + 2 * frameWidth) pixmapHeight + 2 * frameWidth)
def validateCurrentPage(self):
background_image = BackgroundType.to_string(BackgroundType.Image)
if self.page(self.currentId()) == self.backgroundPage and \
self.theme.background_type == background_image and \
self.imageFileEdit.text().isEmpty():
QtGui.QMessageBox.critical(self,
translate('OpenLP.ThemeWizard', 'Background Image Empty'),
translate('OpenLP.ThemeWizard', 'You have not selected a '
'background image. Please select one before continuing.'))
return False
else:
return True
def onCurrentIdChanged(self, pageId): def onCurrentIdChanged(self, pageId):
""" """
Detects Page changes and updates as appropriate. Detects Page changes and updates as appropriate.
@ -521,7 +538,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
images_filter = u'%s;;%s (*.*) (*)' % ( images_filter = u'%s;;%s (*.*) (*)' % (
images_filter, UiStrings().AllFiles) images_filter, UiStrings().AllFiles)
filename = QtGui.QFileDialog.getOpenFileName(self, filename = QtGui.QFileDialog.getOpenFileName(self,
translate('OpenLP.ThemeForm', 'Select Image'), u'', translate('OpenLP.ThemeWizard', 'Select Image'), u'',
images_filter) images_filter)
if filename: if filename:
self.theme.background_filename = unicode(filename) self.theme.background_filename = unicode(filename)
@ -603,14 +620,14 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
self.theme.theme_name = unicode(self.field(u'name').toString()) self.theme.theme_name = unicode(self.field(u'name').toString())
if not self.theme.theme_name: if not self.theme.theme_name:
critical_error_message_box( critical_error_message_box(
translate('OpenLP.ThemeForm', 'Theme Name Missing'), translate('OpenLP.ThemeWizard', 'Theme Name Missing'),
translate('OpenLP.ThemeForm', translate('OpenLP.ThemeWizard',
'There is no name for this theme. Please enter one.')) 'There is no name for this theme. Please enter one.'))
return return
if self.theme.theme_name == u'-1' or self.theme.theme_name == u'None': if self.theme.theme_name == u'-1' or self.theme.theme_name == u'None':
critical_error_message_box( critical_error_message_box(
translate('OpenLP.ThemeForm', 'Theme Name Invalid'), translate('OpenLP.ThemeWizard', 'Theme Name Invalid'),
translate('OpenLP.ThemeForm', translate('OpenLP.ThemeWizard',
'Invalid theme name. Please enter one.')) 'Invalid theme name. Please enter one.'))
return return
saveFrom = None saveFrom = None

View File

@ -257,6 +257,7 @@ class ThemeManager(QtGui.QWidget):
theme.set_default_header_footer() theme.set_default_header_footer()
self.themeForm.theme = theme self.themeForm.theme = theme
self.themeForm.exec_() self.themeForm.exec_()
self.loadThemes()
def onRenameTheme(self): def onRenameTheme(self):
""" """
@ -283,7 +284,6 @@ class ThemeManager(QtGui.QWidget):
plugin.renameTheme(old_theme_name, new_theme_name) plugin.renameTheme(old_theme_name, new_theme_name)
self.mainwindow.renderer.update_theme( self.mainwindow.renderer.update_theme(
new_theme_name, old_theme_name) new_theme_name, old_theme_name)
self.loadThemes()
def onCopyTheme(self): def onCopyTheme(self):
""" """

View File

@ -136,7 +136,7 @@ class AppLocation(object):
else: else:
path = AppLocation.get_directory(AppLocation.DataDir) path = AppLocation.get_directory(AppLocation.DataDir)
check_directory_exists(path) check_directory_exists(path)
return path return os.path.normpath(path)
@staticmethod @staticmethod
def get_section_data_path(section): def get_section_data_path(section):

View File

@ -160,10 +160,12 @@ class BGExtract(object):
verse = verse.strip() verse = verse.strip()
try: try:
verse = int(verse) verse = int(verse)
except (TypeError, ValueError): except ValueError:
verse_parts = verse.split(u'-') verse_parts = verse.split(u'-')
if len(verse_parts) > 1: if len(verse_parts) > 1:
verse = int(verse_parts[0]) verse = int(verse_parts[0])
except TypeError:
log.warn(u'Illegal verse number: %s', unicode(raw_verse_num))
verses.append((verse, text)) verses.append((verse, text))
verse_list = {} verse_list = {}
for verse, text in verses[::-1]: for verse, text in verses[::-1]:
@ -194,6 +196,10 @@ class BGExtract(object):
try: try:
clean_verse_num = int(str(raw_verse_num)) clean_verse_num = int(str(raw_verse_num))
except ValueError: except ValueError:
verse_parts = str(raw_verse_num).split(u'-')
if len(verse_parts) > 1:
clean_verse_num = int(verse_parts[0])
except TypeError:
log.warn(u'Illegal verse number: %s', unicode(raw_verse_num)) log.warn(u'Illegal verse number: %s', unicode(raw_verse_num))
if clean_verse_num: if clean_verse_num:
verse_text = raw_verse_num.next verse_text = raw_verse_num.next

View File

@ -366,15 +366,20 @@ class BibleManager(object):
""" """
log.debug(u'BibleManager.get_language_selection("%s")', bible) log.debug(u'BibleManager.get_language_selection("%s")', bible)
language_selection = self.get_meta_data(bible, u'book_name_language') language_selection = self.get_meta_data(bible, u'book_name_language')
if language_selection: if not language_selection or \
try: language_selection.value == "None" or \
language_selection = int(language_selection.value) language_selection.value == "-1":
except (ValueError, TypeError): # If None is returned, it's not the singleton object but a
language_selection = LanguageSelection.Application # BibleMeta object with the value "None"
if language_selection is None or language_selection == -1:
language_selection = Settings().value( language_selection = Settings().value(
self.settingsSection + u'/bookname language', self.settingsSection + u'/book name language',
QtCore.QVariant(0)).toInt()[0] QtCore.QVariant(0)).toInt()[0]
else:
language_selection = language_selection.value
try:
language_selection = int(language_selection)
except (ValueError, TypeError):
language_selection = LanguageSelection.Application
return language_selection return language_selection
def verse_search(self, bible, second_bible, text): def verse_search(self, bible, second_bible, text):

View File

@ -103,10 +103,20 @@ class OpenSongBible(BibleDB):
for verse in chapter.v: for verse in chapter.v:
if self.stop_import_flag: if self.stop_import_flag:
break break
verse_number = 0
try:
verse_number = int(verse.attrib[u'n'])
except ValueError:
verse_parts = verse.attrib[u'n'].split(u'-')
if len(verse_parts) > 1:
verse_number = int(verse_parts[0])
except TypeError:
log.warn(u'Illegal verse number: %s',
unicode(verse.attrib[u'n']))
self.create_verse( self.create_verse(
db_book.id, db_book.id,
int(chapter.attrib[u'n'].split()[-1]), int(chapter.attrib[u'n'].split()[-1]),
int(verse.attrib[u'n']), verse_number,
unicode(self.get_text(verse))) unicode(self.get_text(verse)))
self.wizard.incrementProgressBar(unicode(translate( self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.Opensong', 'Importing %s %s...', 'BiblesPlugin.Opensong', 'Importing %s %s...',

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff