merging changes from trunk

This commit is contained in:
Gerald Britton 2011-06-10 15:25:38 -04:00
commit f5980ecfc1
32 changed files with 338 additions and 194 deletions

View File

@ -133,6 +133,7 @@ class OpenLP(QtGui.QApplication):
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).start() VersionThread(self.mainWindow).start()
Receiver.send_message(u'maindisplay_blank_check')
self.mainWindow.appStartup() self.mainWindow.appStartup()
DelayStartThread(self.mainWindow).start() DelayStartThread(self.mainWindow).start()
return self.exec_() return self.exec_()

View File

@ -137,13 +137,12 @@ def image_to_byte(image):
# convert to base64 encoding so does not get missed! # convert to base64 encoding so does not get missed!
return byte_array.toBase64() return byte_array.toBase64()
def resize_image(image, width, height, background=QtCore.Qt.black): def resize_image(image_path, width, height, background=QtCore.Qt.black):
""" """
Resize an image to fit on the current screen. Resize an image to fit on the current screen.
``image`` ``image_path``
The image to resize. It has to be either a ``QImage`` instance or the The path to the image to resize.
path to the image.
``width`` ``width``
The new image width. The new image width.
@ -155,16 +154,24 @@ def resize_image(image, width, height, background=QtCore.Qt.black):
The background colour defaults to black. The background colour defaults to black.
""" """
log.debug(u'resize_image - start') log.debug(u'resize_image - start')
if isinstance(image, QtGui.QImage): reader = QtGui.QImageReader(image_path)
preview = image # The image's ratio.
image_ratio = float(reader.size().width()) / float(reader.size().height())
resize_ratio = float(width) / float(height)
# Figure out the size we want to resize the image to (keep aspect ratio).
if image_ratio == resize_ratio:
size = QtCore.QSize(width, height)
elif image_ratio < resize_ratio:
# Use the image's height as reference for the new size.
size = QtCore.QSize(image_ratio * height, height)
else: else:
preview = QtGui.QImage(image) # Use the image's width as reference for the new size.
if not preview.isNull(): size = QtCore.QSize(width, 1 / (image_ratio / width))
# Only resize if different size reader.setScaledSize(size)
if preview.width() == width and preview.height == height: preview = reader.read()
return preview if image_ratio == resize_ratio:
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio, # We neither need to centre the image nor add "bars" to the image.
QtCore.Qt.SmoothTransformation) return preview
realw = preview.width() realw = preview.width()
realh = preview.height() realh = preview.height()
# and move it to the centre of the preview space # and move it to the centre of the preview space

View File

@ -91,7 +91,8 @@ class MediaManagerItem(QtGui.QWidget):
Constructor to create the media manager item. Constructor to create the media manager item.
""" """
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.whitespace = re.compile(r'\W+', re.UNICODE) self.hide()
self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
self.plugin = plugin self.plugin = plugin
visible_title = self.plugin.getString(StringContent.VisibleName) visible_title = self.plugin.getString(StringContent.VisibleName)
self.title = unicode(visible_title[u'title']) self.title = unicode(visible_title[u'title'])
@ -390,21 +391,26 @@ class MediaManagerItem(QtGui.QWidget):
self.iconFromFile(image, thumb) self.iconFromFile(image, thumb)
return True return True
def iconFromFile(self, image, thumb): def iconFromFile(self, image_path, thumb_path):
""" """
Create a thumbnail icon from a given image. Create a thumbnail icon from a given image.
``image`` ``image_path``
The image file to create the icon from. The image file to create the icon from.
``thumb`` ``thumb_path``
The filename to save the thumbnail to The filename to save the thumbnail to.
""" """
icon = build_icon(unicode(image)) ext = os.path.splitext(thumb_path)[1].lower()
pixmap = icon.pixmap(QtCore.QSize(88, 50)) reader = QtGui.QImageReader(image_path)
ext = os.path.splitext(thumb)[1].lower() ratio = float(reader.size().width()) / float(reader.size().height())
pixmap.save(thumb, ext[1:]) reader.setScaledSize(QtCore.QSize(int(ratio * 88), 88))
return icon thumb = reader.read()
thumb.save(thumb_path, ext[1:])
if os.path.exists(thumb_path):
return build_icon(unicode(thumb_path))
# Fallback for files with animation support.
return build_icon(unicode(image_path))
def loadList(self, list): def loadList(self, list):
raise NotImplementedError(u'MediaManagerItem.loadList needs to be ' raise NotImplementedError(u'MediaManagerItem.loadList needs to be '
@ -453,7 +459,8 @@ class MediaManagerItem(QtGui.QWidget):
""" """
if QtCore.QSettings().value(u'advanced/single click preview', if QtCore.QSettings().value(u'advanced/single click preview',
QtCore.QVariant(False)).toBool() and self.quickPreviewAllowed \ QtCore.QVariant(False)).toBool() and self.quickPreviewAllowed \
and self.listView.selectedIndexes(): and self.listView.selectedIndexes() \
and self.auto_select_id == -1:
self.onPreviewClick(True) self.onPreviewClick(True)
def onPreviewClick(self, keepFocus=False): def onPreviewClick(self, keepFocus=False):

View File

@ -300,6 +300,12 @@ class Plugin(QtCore.QObject):
if self.mediaItem: if self.mediaItem:
self.mediadock.remove_dock(self.mediaItem) self.mediadock.remove_dock(self.mediaItem)
def appStartup(self):
"""
Perform tasks on application starup
"""
pass
def usesTheme(self, theme): def usesTheme(self, theme):
""" """
Called to find out if a plugin is currently using a theme. Called to find out if a plugin is currently using a theme.

View File

@ -67,7 +67,7 @@ class Renderer(object):
``theme_manager`` ``theme_manager``
The ThemeManager instance, used to get the current theme details. The ThemeManager instance, used to get the current theme details.
""" """
log.debug(u'Initilisation started') log.debug(u'Initialisation started')
self.theme_manager = theme_manager self.theme_manager = theme_manager
self.image_manager = image_manager self.image_manager = image_manager
self.screens = ScreenList.get_instance() self.screens = ScreenList.get_instance()
@ -86,6 +86,8 @@ class Renderer(object):
""" """
log.debug(u'Update Display') log.debug(u'Update Display')
self._calculate_default(self.screens.current[u'size']) self._calculate_default(self.screens.current[u'size'])
if self.display:
self.display.close()
self.display = MainDisplay(None, self.image_manager, False) self.display = MainDisplay(None, self.image_manager, False)
self.display.setup() self.display.setup()
self.bg_frame = None self.bg_frame = None
@ -241,7 +243,7 @@ class Renderer(object):
``screen`` ``screen``
The QSize of the screen. The QSize of the screen.
""" """
log.debug(u'calculate default %s', screen) log.debug(u'_calculate default %s', screen)
self.width = screen.width() self.width = screen.width()
self.height = screen.height() self.height = screen.height()
self.screen_ratio = float(self.height) / float(self.width) self.screen_ratio = float(self.height) / float(self.width)
@ -286,7 +288,7 @@ class Renderer(object):
``rect_footer`` ``rect_footer``
The footer text block. The footer text block.
""" """
log.debug(u'set_text_rectangle %s , %s' % (rect_main, rect_footer)) log.debug(u'_set_text_rectangle %s , %s' % (rect_main, rect_footer))
self._rect = rect_main self._rect = rect_main
self._rect_footer = rect_footer self._rect_footer = rect_footer
self.page_width = self._rect.width() self.page_width = self._rect.width()
@ -339,7 +341,7 @@ class Renderer(object):
# Text too long so go to next page. # Text too long so go to next page.
if self.web_frame.contentsSize().height() > self.page_height: if self.web_frame.contentsSize().height() > self.page_height:
if force_page and line_count > 0: if force_page and line_count > 0:
Receiver.send_message(u'theme_line_count', line_count) Receiver.send_message(u'theme_line_count', line_count - 1)
line_count = -1 line_count = -1
while html_text.endswith(u'<br>'): while html_text.endswith(u'<br>'):
html_text = html_text[:-4] html_text = html_text[:-4]

View File

@ -106,7 +106,7 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
""" """
Saving exception log and system informations to a file. Saving exception log and system informations to a file.
""" """
report = unicode(translate('OpenLP.ExceptionForm', report_text = unicode(translate('OpenLP.ExceptionForm',
'**OpenLP Bug Report**\n' '**OpenLP Bug Report**\n'
'Version: %s\n\n' 'Version: %s\n\n'
'--- Details of the Exception. ---\n\n%s\n\n ' '--- Details of the Exception. ---\n\n%s\n\n '
@ -122,21 +122,21 @@ class ExceptionForm(QtGui.QDialog, Ui_ExceptionDialog):
filename = unicode(QtCore.QDir.toNativeSeparators(filename)) filename = unicode(QtCore.QDir.toNativeSeparators(filename))
SettingsManager.set_last_dir(self.settingsSection, os.path.dirname( SettingsManager.set_last_dir(self.settingsSection, os.path.dirname(
filename)) filename))
report = report % self._createReport() report_text = report_text % self._createReport()
try: try:
file = open(filename, u'w') report_file = open(filename, u'w')
try: try:
file.write(report) report_file.write(report_text)
except UnicodeError: except UnicodeError:
file.close() report_file.close()
file = open(filename, u'wb') report_file = open(filename, u'wb')
file.write(report.encode(u'utf-8')) report_file.write(report_text.encode(u'utf-8'))
finally: finally:
file.close() report_file.close()
except IOError: except IOError:
log.exception(u'Failed to write crash report') log.exception(u'Failed to write crash report')
finally: finally:
file.close() report_file.close()
def onSendReportButtonPressed(self): def onSendReportButtonPressed(self):
""" """

View File

@ -63,6 +63,7 @@ class MainDisplay(QtGui.QGraphicsView):
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;') self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool |
QtCore.Qt.WindowStaysOnTopHint) QtCore.Qt.WindowStaysOnTopHint)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
if self.isLive: if self.isLive:
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay) QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
@ -148,7 +149,6 @@ class MainDisplay(QtGui.QGraphicsView):
self.__hideMouse() self.__hideMouse()
# To display or not to display? # To display or not to display?
if not self.screen[u'primary']: if not self.screen[u'primary']:
self.show()
self.primary = False self.primary = False
else: else:
self.primary = True self.primary = True

View File

@ -655,7 +655,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
# Give all the plugins a chance to perform some tasks at startup # Give all the plugins a chance to perform some tasks at startup
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
for plugin in self.pluginManager.plugins: for plugin in self.pluginManager.plugins:
if hasattr(plugin, u'appStartup'): if plugin.isActive():
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
plugin.appStartup() plugin.appStartup()
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
@ -678,13 +678,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def blankCheck(self): def blankCheck(self):
""" """
Check and display message if screen blank on setup. Check and display message if screen blank on setup.
Triggered by delay thread.
""" """
settings = QtCore.QSettings() settings = QtCore.QSettings()
self.liveController.mainDisplaySetBackground()
if settings.value(u'%s/screen blank' % self.generalSettingsSection, if settings.value(u'%s/screen blank' % self.generalSettingsSection,
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
self.liveController.mainDisplaySetBackground() if settings.value(u'%s/blank warning' % self.generalSettingsSection,
if settings.value(u'blank warning',
QtCore.QVariant(False)).toBool(): QtCore.QVariant(False)).toBool():
QtGui.QMessageBox.question(self, QtGui.QMessageBox.question(self,
translate('OpenLP.MainWindow', translate('OpenLP.MainWindow',

View File

@ -132,6 +132,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
Receiver.send_message(u'cursor_busy') Receiver.send_message(u'cursor_busy')
self.activePlugin.toggleStatus(PluginStatus.Active) self.activePlugin.toggleStatus(PluginStatus.Active)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
self.activePlugin.appStartup()
else: else:
self.activePlugin.toggleStatus(PluginStatus.Inactive) self.activePlugin.toggleStatus(PluginStatus.Inactive)
status_text = unicode( status_text = unicode(

View File

@ -79,7 +79,7 @@ class ScreenList(object):
``number`` ``number``
The number of the screen, which size has changed. The number of the screen, which size has changed.
""" """
log.info(u'screenResolutionChanged %d' % number) log.info(u'screen_resolution_changed %d' % number)
for screen in self.screen_list: for screen in self.screen_list:
if number == screen[u'number']: if number == screen[u'number']:
newScreen = { newScreen = {
@ -104,6 +104,9 @@ class ScreenList(object):
``changed_screen`` ``changed_screen``
The screen's number which has been (un)plugged. The screen's number which has been (un)plugged.
""" """
# Do not log at start up.
if changed_screen != -1:
log.info(u'screen_count_changed %d' % self.desktop.numScreens())
# Remove unplugged screens. # Remove unplugged screens.
for screen in copy.deepcopy(self.screen_list): for screen in copy.deepcopy(self.screen_list):
if screen[u'number'] == self.desktop.numScreens(): if screen[u'number'] == self.desktop.numScreens():
@ -116,8 +119,7 @@ class ScreenList(object):
u'size': self.desktop.screenGeometry(number), u'size': self.desktop.screenGeometry(number),
u'primary': (self.desktop.primaryScreen() == number) u'primary': (self.desktop.primaryScreen() == number)
}) })
# We do not want to send this message, when the method is called the # We do not want to send this message at start up.
# first time.
if changed_screen != -1: if changed_screen != -1:
# Reload setting tabs to apply possible changes. # Reload setting tabs to apply possible changes.
Receiver.send_message(u'config_screen_changed') Receiver.send_message(u'config_screen_changed')
@ -241,6 +243,7 @@ class ScreenList(object):
height = settings.value(u'height', height = settings.value(u'height',
QtCore.QVariant(self.current[u'size'].height())).toInt()[0] QtCore.QVariant(self.current[u'size'].height())).toInt()[0]
self.override[u'size'] = QtCore.QRect(x, y, width, height) self.override[u'size'] = QtCore.QRect(x, y, width, height)
self.override[u'primary'] = False
settings.endGroup() settings.endGroup()
if override_display: if override_display:
self.set_override_display() self.set_override_display()

View File

@ -959,6 +959,7 @@ class ServiceManager(QtGui.QWidget):
treewidgetitem.setToolTip(0, serviceitem.notes) treewidgetitem.setToolTip(0, serviceitem.notes)
treewidgetitem.setData(0, QtCore.Qt.UserRole, treewidgetitem.setData(0, QtCore.Qt.UserRole,
QtCore.QVariant(item[u'order'])) QtCore.QVariant(item[u'order']))
treewidgetitem.setSelected(item[u'selected'])
# Add the children to their parent treewidgetitem. # Add the children to their parent treewidgetitem.
for count, frame in enumerate(serviceitem.get_frames()): for count, frame in enumerate(serviceitem.get_frames()):
child = QtGui.QTreeWidgetItem(treewidgetitem) child = QtGui.QTreeWidgetItem(treewidgetitem)
@ -1030,16 +1031,35 @@ class ServiceManager(QtGui.QWidget):
# force reset of renderer as theme data has changed # force reset of renderer as theme data has changed
self.mainwindow.renderer.themedata = None self.mainwindow.renderer.themedata = None
if self.serviceItems: if self.serviceItems:
for item in self.serviceItems:
item[u'selected'] = False
serviceIterator = QtGui.QTreeWidgetItemIterator(
self.serviceManagerList)
selectedItem = None
while serviceIterator.value():
if serviceIterator.value().isSelected():
selectedItem = serviceIterator.value()
serviceIterator += 1
if selectedItem is not None:
if selectedItem.parent() is None:
pos = selectedItem.data(0, QtCore.Qt.UserRole).toInt()[0]
else:
pos = selectedItem.parent().data(0, QtCore.Qt.UserRole). \
toInt()[0]
self.serviceItems[pos - 1][u'selected'] = True
tempServiceItems = self.serviceItems tempServiceItems = self.serviceItems
self.serviceManagerList.clear() self.serviceManagerList.clear()
self.serviceItems = [] self.serviceItems = []
self.isNew = True self.isNew = True
for item in tempServiceItems: for item in tempServiceItems:
self.addServiceItem( self.addServiceItem(
item[u'service_item'], False, expand=item[u'expanded']) item[u'service_item'], False, expand=item[u'expanded'],
repaint=False, selected=item[u'selected'])
# Set to False as items may have changed rendering # Set to False as items may have changed rendering
# does not impact the saved song so True may also be valid # does not impact the saved song so True may also be valid
self.setModified() self.setModified()
# Repaint it once only at the end
self.repaintServiceList(-1, -1)
Receiver.send_message(u'cursor_normal') Receiver.send_message(u'cursor_normal')
def serviceItemUpdate(self, message): def serviceItemUpdate(self, message):
@ -1069,7 +1089,7 @@ class ServiceManager(QtGui.QWidget):
self.setModified() self.setModified()
def addServiceItem(self, item, rebuild=False, expand=None, replace=False, def addServiceItem(self, item, rebuild=False, expand=None, replace=False,
repaint=True): repaint=True, selected=False):
""" """
Add a Service item to the list Add a Service item to the list
@ -1097,17 +1117,17 @@ class ServiceManager(QtGui.QWidget):
for inditem in item: for inditem in item:
self.serviceItems.append({u'service_item': inditem, self.serviceItems.append({u'service_item': inditem,
u'order': len(self.serviceItems) + 1, u'order': len(self.serviceItems) + 1,
u'expanded': expand}) u'expanded': expand, u'selected': selected})
else: else:
self.serviceItems.append({u'service_item': item, self.serviceItems.append({u'service_item': item,
u'order': len(self.serviceItems) + 1, u'order': len(self.serviceItems) + 1,
u'expanded': expand}) u'expanded': expand, u'selected': selected})
if repaint: if repaint:
self.repaintServiceList(len(self.serviceItems) - 1, -1) self.repaintServiceList(len(self.serviceItems) - 1, -1)
else: else:
self.serviceItems.insert(self.dropPosition, self.serviceItems.insert(self.dropPosition,
{u'service_item': item, u'order': self.dropPosition, {u'service_item': item, u'order': self.dropPosition,
u'expanded': expand}) u'expanded': expand, u'selected': selected})
self.repaintServiceList(self.dropPosition, -1) self.repaintServiceList(self.dropPosition, -1)
# if rebuilding list make sure live is fixed. # if rebuilding list make sure live is fixed.
if rebuild: if rebuild:

View File

@ -59,6 +59,7 @@ class SlideController(QtGui.QWidget):
""" """
QtGui.QWidget.__init__(self, parent) QtGui.QWidget.__init__(self, parent)
self.isLive = isLive self.isLive = isLive
self.display = None
self.screens = ScreenList.get_instance() self.screens = ScreenList.get_instance()
self.ratio = float(self.screens.current[u'size'].width()) / \ self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height()) float(self.screens.current[u'size'].height())
@ -422,6 +423,8 @@ class SlideController(QtGui.QWidget):
screen previews. screen previews.
""" """
# rebuild display as screen size changed # rebuild display as screen size changed
if self.display:
self.display.close()
self.display = MainDisplay(self, self.image_manager, self.isLive) self.display = MainDisplay(self, self.image_manager, self.isLive)
self.display.alertTab = self.alertTab self.display.alertTab = self.alertTab
self.display.setup() self.display.setup()
@ -742,8 +745,10 @@ class SlideController(QtGui.QWidget):
self.onThemeDisplay(True) self.onThemeDisplay(True)
elif display_type == u'hidden': elif display_type == u'hidden':
self.onHideDisplay(True) self.onHideDisplay(True)
else: elif display_type == u'blanked':
self.onBlankDisplay(True) self.onBlankDisplay(True)
else:
Receiver.send_message(u'maindisplay_show')
def onSlideBlank(self): def onSlideBlank(self):
""" """

View File

@ -202,7 +202,7 @@ 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.ThemeForm',
'(%d lines per slide)')) % int(lines)) '(approximately %d lines per slide)')) % int(lines))
def resizeEvent(self, event=None): def resizeEvent(self, event=None):
""" """

View File

@ -69,7 +69,6 @@ class VersionThread(QtCore.QThread):
Run the thread. Run the thread.
""" """
time.sleep(1) time.sleep(1)
Receiver.send_message(u'maindisplay_blank_check')
app_version = get_application_version() app_version = get_application_version()
version = check_latest_version(app_version) version = check_latest_version(app_version)
remote_version = {} remote_version = {}

View File

@ -77,6 +77,8 @@ class LanguageManager(object):
AppLocation.LanguageDir)) AppLocation.LanguageDir))
file_names = trans_dir.entryList(QtCore.QStringList(u'*.qm'), file_names = trans_dir.entryList(QtCore.QStringList(u'*.qm'),
QtCore.QDir.Files, QtCore.QDir.Name) QtCore.QDir.Files, QtCore.QDir.Name)
# Remove qm files from the list which start with "qt_".
file_names = file_names.filter(QtCore.QRegExp("^(?!qt_)"))
for name in file_names: for name in file_names:
file_names.replaceInStrings(name, trans_dir.filePath(name)) file_names.replaceInStrings(name, trans_dir.filePath(name))
return file_names return file_names

View File

@ -33,7 +33,8 @@ import shutil
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsManager, translate from openlp.core.lib import Receiver, SettingsManager, translate, \
check_directory_exists
from openlp.core.lib.db import delete_database from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import UiStrings, critical_error_message_box from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
@ -94,7 +95,7 @@ class BibleUpgradeForm(OpenLPWizard):
def onCheckBoxIndexChanged(self, index): def onCheckBoxIndexChanged(self, index):
""" """
Show/ Hide warnings if CheckBox state has changed Show/Hide warnings if CheckBox state has changed
""" """
for number, filename in enumerate(self.files): for number, filename in enumerate(self.files):
if not self.checkBox[number].checkState() == QtCore.Qt.Checked: if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
@ -114,6 +115,8 @@ class BibleUpgradeForm(OpenLPWizard):
self.stop_import_flag = True self.stop_import_flag = True
if not self.currentPage() == self.progressPage: if not self.currentPage() == self.progressPage:
self.done(QtGui.QDialog.Rejected) self.done(QtGui.QDialog.Rejected)
else:
self.postWizard()
def onCurrentIdChanged(self, pageId): def onCurrentIdChanged(self, pageId):
""" """
@ -126,14 +129,6 @@ class BibleUpgradeForm(OpenLPWizard):
elif self.page(pageId) == self.selectPage and self.maxBibles == 0: elif self.page(pageId) == self.selectPage and self.maxBibles == 0:
self.next() self.next()
def onFinishButton(self):
"""
Some cleanup while finishing
"""
for number, filename in enumerate(self.files):
if number in self.success and self.success[number] == True:
delete_file(os.path.join(self.path, filename[0]))
def onBackupBrowseButtonClicked(self): def onBackupBrowseButtonClicked(self):
""" """
Show the file open dialog for the OSIS file. Show the file open dialog for the OSIS file.
@ -154,17 +149,19 @@ class BibleUpgradeForm(OpenLPWizard):
self.backupDirectoryEdit.setEnabled(not checked) self.backupDirectoryEdit.setEnabled(not checked)
self.backupBrowseButton.setEnabled(not checked) self.backupBrowseButton.setEnabled(not checked)
def backupOldBibles(self, backupdirectory): def backupOldBibles(self, backup_directory):
""" """
Backup old bible databases in a given folder. Backup old bible databases in a given folder.
""" """
check_directory_exists(backup_directory)
success = True
for filename in self.files: for filename in self.files:
try: try:
shutil.copy(os.path.join(self.path, filename[0]), shutil.copy(os.path.join(self.path, filename[0]),
backupdirectory) backup_directory)
except: except:
return False success = False
return True return success
def customInit(self): def customInit(self):
""" """
@ -177,8 +174,6 @@ class BibleUpgradeForm(OpenLPWizard):
""" """
Set up the signals used in the bible importer. Set up the signals used in the bible importer.
""" """
QtCore.QObject.connect(self.finishButton,
QtCore.SIGNAL(u'clicked()'), self.onFinishButton)
QtCore.QObject.connect(self.backupBrowseButton, QtCore.QObject.connect(self.backupBrowseButton,
QtCore.SIGNAL(u'clicked()'), self.onBackupBrowseButtonClicked) QtCore.SIGNAL(u'clicked()'), self.onBackupBrowseButtonClicked)
QtCore.QObject.connect(self.noBackupCheckBox, QtCore.QObject.connect(self.noBackupCheckBox,
@ -318,7 +313,7 @@ class BibleUpgradeForm(OpenLPWizard):
QtGui.QFormLayout.FieldRole, self.versionNameEdit[number]) QtGui.QFormLayout.FieldRole, self.versionNameEdit[number])
self.versionNameEdit[number].setText(bible.get_name()) self.versionNameEdit[number].setText(bible.get_name())
self.formLayout.addWidget(self.formWidget[number]) self.formLayout.addWidget(self.formWidget[number])
#Set up the Signal for the checkbox # Set up the Signal for the checkbox.
QtCore.QObject.connect(self.checkBox[number], QtCore.QObject.connect(self.checkBox[number],
QtCore.SIGNAL(u'stateChanged(int)'), QtCore.SIGNAL(u'stateChanged(int)'),
self.onCheckBoxIndexChanged) self.onCheckBoxIndexChanged)
@ -414,29 +409,22 @@ class BibleUpgradeForm(OpenLPWizard):
return True return True
elif self.currentPage() == self.backupPage: elif self.currentPage() == self.backupPage:
if not self.noBackupCheckBox.checkState() == QtCore.Qt.Checked: if not self.noBackupCheckBox.checkState() == QtCore.Qt.Checked:
if not unicode(self.backupDirectoryEdit.text()): backup_path = unicode(self.backupDirectoryEdit.text())
if not backup_path:
critical_error_message_box(UiStrings().EmptyField, critical_error_message_box(UiStrings().EmptyField,
translate('BiblesPlugin.UpgradeWizardForm', translate('BiblesPlugin.UpgradeWizardForm',
'You need to specify a Backup Directory for your ' 'You need to specify a Backup Directory for your '
'Bibles.')) 'Bibles.'))
self.backupDirectoryEdit.setFocus() self.backupDirectoryEdit.setFocus()
return False return False
elif not os.path.exists(unicode(
self.backupDirectoryEdit.text())):
critical_error_message_box(UiStrings().Error,
translate('BiblesPlugin.UpgradeWizardForm',
'The given path is not an existing directory.'))
self.backupDirectoryEdit.setFocus()
return False
else: else:
if not self.backupOldBibles(unicode( if not self.backupOldBibles(backup_path):
self.backupDirectoryEdit.text())):
critical_error_message_box(UiStrings().Error, critical_error_message_box(UiStrings().Error,
translate('BiblesPlugin.UpgradeWizardForm', translate('BiblesPlugin.UpgradeWizardForm',
'The backup was not successfull.\nTo backup your ' 'The backup was not successful.\nTo backup your '
'Bibles you need the permission to write in the given ' 'Bibles you need permission to write to the given '
'directory. If you have a permissions to write and ' 'directory. If you have write permissions and this '
'this error still occurs, please report a bug.')) 'error still occurs, please report a bug.'))
return False return False
return True return True
elif self.currentPage() == self.selectPage: elif self.currentPage() == self.selectPage:
@ -540,7 +528,7 @@ class BibleUpgradeForm(OpenLPWizard):
""" """
Perform the actual upgrade. Perform the actual upgrade.
""" """
include_webbible = False self.include_webbible = False
proxy_server = None proxy_server = None
if self.maxBibles == 0: if self.maxBibles == 0:
self.progressLabel.setText( self.progressLabel.setText(
@ -582,19 +570,19 @@ class BibleUpgradeForm(OpenLPWizard):
name = unicode(self.versionNameEdit[biblenumber].text()) name = unicode(self.versionNameEdit[biblenumber].text())
self.newbibles[number] = BibleDB(self.mediaItem, path=self.path, self.newbibles[number] = BibleDB(self.mediaItem, path=self.path,
name=name) name=name)
self.newbibles[number].register(self.plugin.upgrade_wizard)
metadata = oldbible.get_metadata() metadata = oldbible.get_metadata()
webbible = False webbible = False
meta_data = {} meta_data = {}
for meta in metadata: for meta in metadata:
meta_data[meta[u'key']] = meta[u'value'] meta_data[meta[u'key']] = meta[u'value']
if not meta[u'key'] == u'Version': if not meta[u'key'] == u'Version' and not meta[u'key'] == \
u'dbversion':
self.newbibles[number].create_meta(meta[u'key'], self.newbibles[number].create_meta(meta[u'key'],
meta[u'value']) meta[u'value'])
else:
self.newbibles[number].create_meta(meta[u'key'], name)
if meta[u'key'] == u'download source': if meta[u'key'] == u'download source':
webbible = True webbible = True
include_webbible = True self.include_webbible = True
if meta.has_key(u'proxy server'): if meta.has_key(u'proxy server'):
proxy_server = meta[u'proxy server'] proxy_server = meta[u'proxy server']
if webbible: if webbible:
@ -606,12 +594,11 @@ class BibleUpgradeForm(OpenLPWizard):
handler = BSExtract(proxy_server) handler = BSExtract(proxy_server)
books = handler.get_books_from_http(meta_data[u'download name']) books = handler.get_books_from_http(meta_data[u'download name'])
if not books: if not books:
log.exception(u'Upgrading books from %s - download '\ log.error(u'Upgrading books from %s - download '\
u'name: "%s" failed' % ( u'name: "%s" failed' % (
meta_data[u'download source'], meta_data[u'download source'],
meta_data[u'download name'])) meta_data[u'download name']))
delete_database(self.path, delete_database(self.path, clean_filename(name))
clean_filename(self.newbibles[number].get_name()))
del self.newbibles[number] del self.newbibles[number]
critical_error_message_box( critical_error_message_box(
translate('BiblesPlugin.UpgradeWizardForm', translate('BiblesPlugin.UpgradeWizardForm',
@ -630,16 +617,15 @@ class BibleUpgradeForm(OpenLPWizard):
bible = BiblesResourcesDB.get_webbible( bible = BiblesResourcesDB.get_webbible(
meta_data[u'download name'], meta_data[u'download name'],
meta_data[u'download source'].lower()) meta_data[u'download source'].lower())
if bible[u'language_id']: if bible and bible[u'language_id']:
language_id = bible[u'language_id'] language_id = bible[u'language_id']
self.newbibles[number].create_meta(u'language_id', self.newbibles[number].create_meta(u'language_id',
language_id) language_id)
else: else:
language_id = self.newbibles[number].get_language(name) language_id = self.newbibles[number].get_language(name)
if not language_id: if not language_id:
log.exception(u'Upgrading from "%s" failed' % filename[0]) log.warn(u'Upgrading from "%s" failed' % filename[0])
delete_database(self.path, delete_database(self.path, clean_filename(name))
clean_filename(self.newbibles[number].get_name()))
del self.newbibles[number] del self.newbibles[number]
self.incrementProgressBar(unicode(translate( self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm', 'BiblesPlugin.UpgradeWizardForm',
@ -661,27 +647,42 @@ class BibleUpgradeForm(OpenLPWizard):
book_ref_id = self.newbibles[number].\ book_ref_id = self.newbibles[number].\
get_book_ref_id_by_name(book, len(books), language_id) get_book_ref_id_by_name(book, len(books), language_id)
if not book_ref_id: if not book_ref_id:
log.exception(u'Upgrading books from %s - download '\ log.warn(u'Upgrading books from %s - download '\
u'name: "%s" aborted by user' % ( u'name: "%s" aborted by user' % (
meta_data[u'download source'], meta_data[u'download source'],
meta_data[u'download name'])) meta_data[u'download name']))
delete_database(self.path, delete_database(self.path, clean_filename(name))
clean_filename(self.newbibles[number].get_name()))
del self.newbibles[number] del self.newbibles[number]
bible_failed = True bible_failed = True
break break
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id) book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
self.newbibles[number].create_book(book, book_ref_id, db_book = self.newbibles[number].create_book(book,
book_details[u'testament_id']) book_ref_id, book_details[u'testament_id'])
# Try to import still downloaded verses
oldbook = oldbible.get_book(book)
if oldbook:
verses = oldbible.get_verses(oldbook[u'id'])
if not verses:
log.warn(u'No verses found to import for book '
u'"%s"', book)
continue
for verse in verses:
if self.stop_import_flag:
bible_failed = True
break
self.newbibles[number].create_verse(db_book.id,
int(verse[u'chapter']),
int(verse[u'verse']), unicode(verse[u'text']))
Receiver.send_message(u'openlp_process_events')
self.newbibles[number].session.commit()
else: else:
language_id = self.newbibles[number].get_object(BibleMeta, language_id = self.newbibles[number].get_object(BibleMeta,
u'language_id') u'language_id')
if not language_id: if not language_id:
language_id = self.newbibles[number].get_language(name) language_id = self.newbibles[number].get_language(name)
if not language_id: if not language_id:
log.exception(u'Upgrading books from "%s" failed' % name) log.warn(u'Upgrading books from "%s" failed' % name)
delete_database(self.path, delete_database(self.path, clean_filename(name))
clean_filename(self.newbibles[number].get_name()))
del self.newbibles[number] del self.newbibles[number]
self.incrementProgressBar(unicode(translate( self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm', 'BiblesPlugin.UpgradeWizardForm',
@ -705,10 +706,9 @@ class BibleUpgradeForm(OpenLPWizard):
get_book_ref_id_by_name(book[u'name'], len(books), get_book_ref_id_by_name(book[u'name'], len(books),
language_id) language_id)
if not book_ref_id: if not book_ref_id:
log.exception(u'Upgrading books from %s " '\ log.warn(u'Upgrading books from %s " '\
'failed - aborted by user' % name) 'failed - aborted by user' % name)
delete_database(self.path, delete_database(self.path, clean_filename(name))
clean_filename(self.newbibles[number].get_name()))
del self.newbibles[number] del self.newbibles[number]
bible_failed = True bible_failed = True
break break
@ -717,7 +717,7 @@ class BibleUpgradeForm(OpenLPWizard):
book_ref_id, book_details[u'testament_id']) book_ref_id, book_details[u'testament_id'])
verses = oldbible.get_verses(book[u'id']) verses = oldbible.get_verses(book[u'id'])
if not verses: if not verses:
log.exception(u'No verses found to import for book ' log.warn(u'No verses found to import for book '
u'"%s"', book[u'name']) u'"%s"', book[u'name'])
self.newbibles[number].delete_book(db_book) self.newbibles[number].delete_book(db_book)
continue continue
@ -731,6 +731,8 @@ class BibleUpgradeForm(OpenLPWizard):
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
self.newbibles[number].session.commit() self.newbibles[number].session.commit()
if not bible_failed: if not bible_failed:
self.newbibles[number].create_meta(u'Version', name)
delete_file(os.path.join(self.path, filename[0]))
self.incrementProgressBar(unicode(translate( self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm', 'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\n' 'Upgrading Bible %s of %s: "%s"\n'
@ -743,10 +745,13 @@ class BibleUpgradeForm(OpenLPWizard):
'Upgrading Bible %s of %s: "%s"\nFailed')) % 'Upgrading Bible %s of %s: "%s"\nFailed')) %
(number + 1, self.maxBibles, name), (number + 1, self.maxBibles, name),
self.progressBar.maximum() - self.progressBar.value()) self.progressBar.maximum() - self.progressBar.value())
delete_database(self.path, delete_database(self.path, clean_filename(name))
clean_filename(name))
number += 1 number += 1
self.mediaItem.reloadBibles()
def postWizard(self):
"""
Clean up the UI after the import has finished.
"""
successful_import = 0 successful_import = 0
failed_import = 0 failed_import = 0
for number, filename in enumerate(self.files): for number, filename in enumerate(self.files):
@ -761,7 +766,7 @@ class BibleUpgradeForm(OpenLPWizard):
else: else:
failed_import_text = u'' failed_import_text = u''
if successful_import > 0: if successful_import > 0:
if include_webbible: if self.include_webbible:
self.progressLabel.setText(unicode( self.progressLabel.setText(unicode(
translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading ' translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading '
'Bible(s): %s successful%s\nPlease note, that verses from ' 'Bible(s): %s successful%s\nPlease note, that verses from '
@ -777,3 +782,4 @@ class BibleUpgradeForm(OpenLPWizard):
self.progressLabel.setText( self.progressLabel.setText(
translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade ' translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade '
'failed.')) 'failed.'))
OpenLPWizard.postWizard(self)

View File

@ -70,15 +70,15 @@ class BookNameForm(QDialog, Ui_BookNameDialog):
self.onCheckBoxIndexChanged) self.onCheckBoxIndexChanged)
def onCheckBoxIndexChanged(self, index): def onCheckBoxIndexChanged(self, index):
''' """
Reload Combobox if CheckBox state has changed Reload Combobox if CheckBox state has changed
''' """
self.reloadComboBox() self.reloadComboBox()
def reloadComboBox(self): def reloadComboBox(self):
''' """
Reload the Combobox items Reload the Combobox items
''' """
self.correspondingComboBox.clear() self.correspondingComboBox.clear()
items = BiblesResourcesDB.get_books() items = BiblesResourcesDB.get_books()
for item in items: for item in items:

View File

@ -381,6 +381,7 @@ class BibleDB(QtCore.QObject, Manager):
""" """
log.debug(u'BibleDB.get_verses("%s")', reference_list) log.debug(u'BibleDB.get_verses("%s")', reference_list)
verse_list = [] verse_list = []
book_error = False
for book_id, chapter, start_verse, end_verse in reference_list: for book_id, chapter, start_verse, end_verse in reference_list:
db_book = self.get_book_by_book_ref_id(book_id) db_book = self.get_book_by_book_ref_id(book_id)
if db_book: if db_book:
@ -398,12 +399,13 @@ class BibleDB(QtCore.QObject, Manager):
verse_list.extend(verses) verse_list.extend(verses)
else: else:
log.debug(u'OpenLP failed to find book with id "%s"', book_id) log.debug(u'OpenLP failed to find book with id "%s"', book_id)
if show_error: book_error = True
critical_error_message_box( if book_error and show_error:
translate('BiblesPlugin', 'No Book Found'), critical_error_message_box(
translate('BiblesPlugin', 'No matching book ' translate('BiblesPlugin', 'No Book Found'),
'could be found in this Bible. Check that you ' translate('BiblesPlugin', 'No matching book '
'have spelled the name of the book correctly.')) 'could be found in this Bible. Check that you '
'have spelled the name of the book correctly.'))
return verse_list return verse_list
def verse_search(self, text): def verse_search(self, text):
@ -1043,6 +1045,28 @@ class OldBibleDB(QtCore.QObject, Manager):
else: else:
return None return None
def get_book(self, name):
"""
Return a book by name or abbreviation.
``name``
The name or abbreviation of the book.
"""
if not isinstance(name, unicode):
name = unicode(name)
books = self.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation FROM book WHERE LOWER(name) = ? OR '
u'LOWER(abbreviation) = ?', (name.lower(), name.lower()))
if books:
return {
u'id': books[0][0],
u'testament_id': books[0][1],
u'name': unicode(books[0][2]),
u'abbreviation': unicode(books[0][3])
}
else:
return None
def get_books(self): def get_books(self):
""" """
Returns the books of the Bible. Returns the books of the Bible.

View File

@ -72,9 +72,8 @@ class BGExtract(object):
log.debug(u'BGExtract.get_bible_chapter("%s", "%s", "%s")', version, log.debug(u'BGExtract.get_bible_chapter("%s", "%s", "%s")', version,
bookname, chapter) bookname, chapter)
urlbookname = urllib.quote(bookname.encode("utf-8")) urlbookname = urllib.quote(bookname.encode("utf-8"))
url_params = urllib.urlencode( url_params = u'search=%s+%s&version=%s' % (urlbookname, chapter,
{u'search': u'%s %s' % (urlbookname, chapter), version)
u'version': u'%s' % version})
cleaner = [(re.compile('&nbsp;|<br />|\'\+\''), lambda match: '')] cleaner = [(re.compile('&nbsp;|<br />|\'\+\''), lambda match: '')]
soup = get_soup_for_bible_ref( soup = get_soup_for_bible_ref(
u'http://www.biblegateway.com/passage/?%s' % url_params, u'http://www.biblegateway.com/passage/?%s' % url_params,
@ -97,10 +96,10 @@ class BGExtract(object):
verse_list = {} verse_list = {}
# Cater for inconsistent mark up in the first verse of a chapter. # Cater for inconsistent mark up in the first verse of a chapter.
first_verse = verses.find(u'versenum') first_verse = verses.find(u'versenum')
if first_verse: if first_verse and len(first_verse.contents):
verse_list[1] = unicode(first_verse.contents[0]) verse_list[1] = unicode(first_verse.contents[0])
for verse in verses(u'sup', u'versenum'): for verse in verses(u'sup', u'versenum'):
raw_verse_num = verse.next raw_verse_num = verse.next
clean_verse_num = 0 clean_verse_num = 0
# Not all verses exist in all translations and may or may not be # Not all verses exist in all translations and may or may not be
# represented by a verse number. If they are not fine, if they are # represented by a verse number. If they are not fine, if they are
@ -110,7 +109,7 @@ 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:
log.exception(u'Illegal verse number in %s %s %s:%s', log.warn(u'Illegal verse number in %s %s %s:%s',
version, bookname, chapter, unicode(raw_verse_num)) version, bookname, chapter, unicode(raw_verse_num))
if clean_verse_num: if clean_verse_num:
verse_text = raw_verse_num.next verse_text = raw_verse_num.next
@ -140,16 +139,17 @@ class BGExtract(object):
""" """
log.debug(u'BGExtract.get_books_from_http("%s")', version) log.debug(u'BGExtract.get_books_from_http("%s")', version)
url_params = urllib.urlencode( url_params = urllib.urlencode(
{u'search': 'Bible-List', u'version': u'%s' % version}) {u'action': 'getVersionInfo', u'vid': u'%s' % version})
reference_url = u'http://www.biblegateway.com/passage/?%s' % url_params reference_url = u'http://www.biblegateway.com/versions/?%s#books' % \
url_params
page = get_web_page(reference_url) page = get_web_page(reference_url)
if not page: if not page:
send_error_message(u'download') send_error_message(u'download')
return None return None
page_source = page.read() page_source = page.read()
page_source = unicode(page_source, 'utf8') page_source = unicode(page_source, 'utf8')
page_source_temp = re.search(u'<table id="booklist".*?>.*?</table>', \ page_source_temp = re.search(u'<table .*?class="infotable".*?>.*?'\
page_source, re.DOTALL) u'</table>', page_source, re.DOTALL)
if page_source_temp: if page_source_temp:
soup = page_source_temp.group(0) soup = page_source_temp.group(0)
else: else:
@ -157,15 +157,17 @@ class BGExtract(object):
try: try:
soup = BeautifulSoup(soup) soup = BeautifulSoup(soup)
except HTMLParseError: except HTMLParseError:
log.exception(u'BeautifulSoup could not parse the Bible page.') log.error(u'BeautifulSoup could not parse the Bible page.')
send_error_message(u'parse')
return None
if not soup: if not soup:
send_error_message(u'parse') send_error_message(u'parse')
return None return None
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
content = soup.find(u'table', {u'id': u'booklist'}) content = soup.find(u'table', {u'class': u'infotable'})
content = content.findAll(u'tr') content = content.findAll(u'tr')
if not content: if not content:
log.exception(u'No books found in the Biblegateway response.') log.error(u'No books found in the Biblegateway response.')
send_error_message(u'parse') send_error_message(u'parse')
return None return None
books = [] books = []
@ -200,9 +202,10 @@ class BSExtract(object):
""" """
log.debug(u'BSExtract.get_bible_chapter("%s", "%s", "%s")', version, log.debug(u'BSExtract.get_bible_chapter("%s", "%s", "%s")', version,
bookname, chapter) bookname, chapter)
urlversion = urllib.quote(version.encode("utf-8"))
urlbookname = urllib.quote(bookname.encode("utf-8")) urlbookname = urllib.quote(bookname.encode("utf-8"))
chapter_url = u'http://m.bibleserver.com/text/%s/%s%s' % \ chapter_url = u'http://m.bibleserver.com/text/%s/%s%d' % \
(version, urlbookname, chapter) (urlversion, urlbookname, chapter)
header = (u'Accept-Language', u'en') header = (u'Accept-Language', u'en')
soup = get_soup_for_bible_ref(chapter_url, header) soup = get_soup_for_bible_ref(chapter_url, header)
if not soup: if not soup:
@ -210,7 +213,7 @@ class BSExtract(object):
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
content = soup.find(u'div', u'content') content = soup.find(u'div', u'content')
if not content: if not content:
log.exception(u'No verses found in the Bibleserver response.') log.error(u'No verses found in the Bibleserver response.')
send_error_message(u'parse') send_error_message(u'parse')
return None return None
content = content.find(u'div').findAll(u'div') content = content.find(u'div').findAll(u'div')
@ -231,14 +234,15 @@ class BSExtract(object):
The version of the Bible like NIV for New International Version The version of the Bible like NIV for New International Version
""" """
log.debug(u'BSExtract.get_books_from_http("%s")', version) log.debug(u'BSExtract.get_books_from_http("%s")', version)
urlversion = urllib.quote(version.encode("utf-8"))
chapter_url = u'http://m.bibleserver.com/overlay/selectBook?'\ chapter_url = u'http://m.bibleserver.com/overlay/selectBook?'\
'translation=%s' % (version) 'translation=%s' % (urlversion)
soup = get_soup_for_bible_ref(chapter_url) soup = get_soup_for_bible_ref(chapter_url)
if not soup: if not soup:
return None return None
content = soup.find(u'ul') content = soup.find(u'ul')
if not content: if not content:
log.exception(u'No books found in the Bibleserver response.') log.error(u'No books found in the Bibleserver response.')
send_error_message(u'parse') send_error_message(u'parse')
return None return None
content = content.findAll(u'li') content = content.findAll(u'li')
@ -282,7 +286,7 @@ class CWExtract(object):
Receiver.send_message(u'openlp_process_events') Receiver.send_message(u'openlp_process_events')
htmlverses = soup.findAll(u'span', u'versetext') htmlverses = soup.findAll(u'span', u'versetext')
if not htmlverses: if not htmlverses:
log.debug(u'No verses found in the CrossWalk response.') log.error(u'No verses found in the CrossWalk response.')
send_error_message(u'parse') send_error_message(u'parse')
return None return None
verses = {} verses = {}
@ -334,7 +338,7 @@ class CWExtract(object):
content = soup.find(u'div', {u'class': u'Body'}) content = soup.find(u'div', {u'class': u'Body'})
content = content.find(u'ul', {u'class': u'parent'}) content = content.find(u'ul', {u'class': u'parent'})
if not content: if not content:
log.exception(u'No books found in the Crosswalk response.') log.error(u'No books found in the Crosswalk response.')
send_error_message(u'parse') send_error_message(u'parse')
return None return None
content = content.findAll(u'li') content = content.findAll(u'li')

View File

@ -675,9 +675,32 @@ class BibleMediaItem(MediaManagerItem):
second_bible, text) second_bible, text)
if second_bible and self.search_results: if second_bible and self.search_results:
text = [] text = []
new_search_results = []
count = 0
passage_not_found = False
for verse in self.search_results: for verse in self.search_results:
text.append((verse.book.name, verse.chapter, verse.verse, db_book = bibles[second_bible].get_book_by_book_ref_id(
verse.verse)) verse.book.book_reference_id)
if not db_book:
log.debug(u'Passage "%s %d:%d" not found in Second '
u'Bible' % (verse.book.name, verse.chapter,
verse.verse))
passage_not_found = True
count += 1
continue
new_search_results.append(verse)
text.append((verse.book.book_reference_id, verse.chapter,
verse.verse, verse.verse))
if passage_not_found:
QtGui.QMessageBox.information(self,
translate('BiblePlugin.MediaItem', 'Information'),
unicode(translate('BiblePlugin.MediaItem',
'The second Bibles does not contain all the verses '
'that are in the main Bible. Only verses found in both '
'Bibles will be shown. %d verses have not been '
'included in the results.')) % count,
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Ok))
self.search_results = new_search_results
self.second_search_results = \ self.second_search_results = \
bibles[second_bible].get_verses(text) bibles[second_bible].get_verses(text)
if not self.quickLockButton.isChecked(): if not self.quickLockButton.isChecked():
@ -749,7 +772,7 @@ class BibleMediaItem(MediaManagerItem):
log.exception(u'The second_search_results does not have as ' log.exception(u'The second_search_results does not have as '
'many verses as the search_results.') '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, verse.chapter, verse_separator, verse.verse, version,
second_version) second_version)
else: else:
@ -807,7 +830,7 @@ class BibleMediaItem(MediaManagerItem):
bible_text = u'' bible_text = u''
# If we are 'Verse Per Line' then force a new line. # If we are 'Verse Per Line' then force a new line.
elif self.settings.layout_style == LayoutStyle.VersePerLine: elif self.settings.layout_style == LayoutStyle.VersePerLine:
bible_text = u'%s %s&nbsp;%s\n' % (bible_text, verse_text, text) bible_text = u'%s%s&nbsp;%s\n' % (bible_text, verse_text, text)
# We have to be 'Continuous'. # We have to be 'Continuous'.
else: else:
bible_text = u'%s %s&nbsp;%s\n' % (bible_text, verse_text, text) bible_text = u'%s %s&nbsp;%s\n' % (bible_text, verse_text, text)
@ -845,7 +868,8 @@ class BibleMediaItem(MediaManagerItem):
service_item.theme = None service_item.theme = None
else: else:
service_item.theme = self.settings.bible_theme service_item.theme = self.settings.bible_theme
[service_item.add_from_text(slide[:30], slide) for slide in raw_slides] for slide in raw_slides:
service_item.add_from_text(slide[:30], slide)
return True return True
def formatTitle(self, start_bitem, old_bitem): def formatTitle(self, start_bitem, old_bitem):
@ -959,7 +983,7 @@ class BibleMediaItem(MediaManagerItem):
Search for some Bible verses (by reference). Search for some Bible verses (by reference).
""" """
bible = unicode(self.quickVersionComboBox.currentText()) bible = unicode(self.quickVersionComboBox.currentText())
search_results = self.plugin.manager.get_verses(bible, string, False) search_results = self.plugin.manager.get_verses(bible, string, False, False)
results = [] results = []
if search_results: if search_results:
versetext = u' '.join([verse.text for verse in search_results]) versetext = u' '.join([verse.text for verse in search_results])

View File

@ -93,6 +93,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.titleEdit.setText(u'') self.titleEdit.setText(u'')
self.creditEdit.setText(u'') self.creditEdit.setText(u'')
self.themeComboBox.setCurrentIndex(0) self.themeComboBox.setCurrentIndex(0)
self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason)
else: else:
self.customSlide = self.manager.get_object(CustomSlide, id) self.customSlide = self.manager.get_object(CustomSlide, id)
self.titleEdit.setText(self.customSlide.title) self.titleEdit.setText(self.customSlide.title)
@ -115,7 +116,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
def accept(self): def accept(self):
log.debug(u'accept') log.debug(u'accept')
if self.saveCustom(): if self.saveCustom():
Receiver.send_message(u'custom_load_list')
QtGui.QDialog.accept(self) QtGui.QDialog.accept(self)
def saveCustom(self): def saveCustom(self):

View File

@ -109,7 +109,7 @@ class CustomMediaItem(MediaManagerItem):
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_edit_clear'), self.onRemoteEditClear) QtCore.SIGNAL(u'custom_edit_clear'), self.onRemoteEditClear)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_load_list'), self.initialise) QtCore.SIGNAL(u'custom_load_list'), self.loadList)
QtCore.QObject.connect(Receiver.get_receiver(), QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick) QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick)
@ -129,14 +129,6 @@ class CustomMediaItem(MediaManagerItem):
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value( self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value(
u'%s/last search type' % self.settingsSection, u'%s/last search type' % self.settingsSection,
QtCore.QVariant(CustomSearch.Titles)).toInt()[0]) QtCore.QVariant(CustomSearch.Titles)).toInt()[0])
# Called to redisplay the custom list screen edith from a search
# or from the exit of the Custom edit dialog. If remote editing is
# active trigger it and clean up so it will not update again.
if self.remoteTriggered == u'L':
self.onAddClick()
if self.remoteTriggered == u'P':
self.onPreviewClick()
self.onRemoteEditClear()
def loadList(self, custom_slides): def loadList(self, custom_slides):
# Sort out what custom we want to select after loading the list. # Sort out what custom we want to select after loading the list.
@ -155,11 +147,20 @@ class CustomMediaItem(MediaManagerItem):
if custom_slide.id == self.auto_select_id: if custom_slide.id == self.auto_select_id:
self.listView.setCurrentItem(custom_name) self.listView.setCurrentItem(custom_name)
self.auto_select_id = -1 self.auto_select_id = -1
# Called to redisplay the custom list screen edith from a search
# or from the exit of the Custom edit dialog. If remote editing is
# active trigger it and clean up so it will not update again.
if self.remoteTriggered == u'L':
self.onAddClick()
if self.remoteTriggered == u'P':
self.onPreviewClick()
self.onRemoteEditClear()
def onNewClick(self): def onNewClick(self):
self.edit_custom_form.loadCustom(0) self.edit_custom_form.loadCustom(0)
self.edit_custom_form.exec_() self.edit_custom_form.exec_()
self.initialise() self.onClearTextButtonClick()
self.onSelectionChange()
def onRemoteEditClear(self): def onRemoteEditClear(self):
self.remoteTriggered = None self.remoteTriggered = None
@ -179,6 +180,8 @@ class CustomMediaItem(MediaManagerItem):
self.remoteTriggered = remote_type self.remoteTriggered = remote_type
self.edit_custom_form.loadCustom(custom_id, (remote_type == u'P')) self.edit_custom_form.loadCustom(custom_id, (remote_type == u'P'))
self.edit_custom_form.exec_() self.edit_custom_form.exec_()
self.auto_select_id = -1
self.onSearchTextButtonClick()
def onEditClick(self): def onEditClick(self):
""" """
@ -189,7 +192,8 @@ class CustomMediaItem(MediaManagerItem):
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.edit_custom_form.loadCustom(item_id, False) self.edit_custom_form.loadCustom(item_id, False)
self.edit_custom_form.exec_() self.edit_custom_form.exec_()
self.initialise() self.auto_select_id = -1
self.onSearchTextButtonClick()
def onDeleteClick(self): def onDeleteClick(self):
""" """

View File

@ -125,7 +125,7 @@ class ImpressController(PresentationController):
try: try:
uno_instance = get_uno_instance(resolver) uno_instance = get_uno_instance(resolver)
except: except:
log.exception(u'Unable to find running instance ') log.warn(u'Unable to find running instance ')
self.start_process() self.start_process()
loop += 1 loop += 1
try: try:
@ -136,7 +136,7 @@ class ImpressController(PresentationController):
"com.sun.star.frame.Desktop", uno_instance) "com.sun.star.frame.Desktop", uno_instance)
return desktop return desktop
except: except:
log.exception(u'Failed to get UNO desktop') log.warn(u'Failed to get UNO desktop')
return None return None
def get_com_desktop(self): def get_com_desktop(self):
@ -151,7 +151,7 @@ class ImpressController(PresentationController):
try: try:
desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop') desktop = self.manager.createInstance(u'com.sun.star.frame.Desktop')
except AttributeError: except AttributeError:
log.exception(u'Failure to find desktop - Impress may have closed') log.warn(u'Failure to find desktop - Impress may have closed')
return desktop if desktop else None return desktop if desktop else None
def get_com_servicemanager(self): def get_com_servicemanager(self):
@ -162,7 +162,7 @@ class ImpressController(PresentationController):
try: try:
return Dispatch(u'com.sun.star.ServiceManager') return Dispatch(u'com.sun.star.ServiceManager')
except pywintypes.com_error: except pywintypes.com_error:
log.exception(u'Failed to get COM service manager. ' log.warn(u'Failed to get COM service manager. '
u'Impress Controller has been disabled') u'Impress Controller has been disabled')
return None return None
@ -180,7 +180,7 @@ class ImpressController(PresentationController):
else: else:
desktop = self.get_com_desktop() desktop = self.get_com_desktop()
except: except:
log.exception(u'Failed to find an OpenOffice desktop to terminate') log.warn(u'Failed to find an OpenOffice desktop to terminate')
if not desktop: if not desktop:
return return
docs = desktop.getComponents() docs = desktop.getComponents()
@ -191,7 +191,7 @@ class ImpressController(PresentationController):
desktop.terminate() desktop.terminate()
log.debug(u'OpenOffice killed') log.debug(u'OpenOffice killed')
except: except:
log.exception(u'Failed to terminate OpenOffice') log.warn(u'Failed to terminate OpenOffice')
class ImpressDocument(PresentationDocument): class ImpressDocument(PresentationDocument):
@ -244,7 +244,7 @@ class ImpressDocument(PresentationDocument):
self.document = desktop.loadComponentFromURL(url, u'_blank', self.document = desktop.loadComponentFromURL(url, u'_blank',
0, properties) 0, properties)
except: except:
log.exception(u'Failed to load presentation %s' % url) log.warn(u'Failed to load presentation %s' % url)
return False return False
if os.name == u'nt': if os.name == u'nt':
# As we can't start minimized the Impress window gets in the way. # As we can't start minimized the Impress window gets in the way.
@ -323,7 +323,7 @@ class ImpressDocument(PresentationDocument):
self.presentation = None self.presentation = None
self.document.dispose() self.document.dispose()
except: except:
log.exception("Closing presentation failed") log.warn("Closing presentation failed")
self.document = None self.document = None
self.controller.remove_doc(self) self.controller.remove_doc(self)
@ -341,7 +341,7 @@ class ImpressDocument(PresentationDocument):
log.debug("getPresentation failed to find a presentation") log.debug("getPresentation failed to find a presentation")
return False return False
except: except:
log.exception("getPresentation failed to find a presentation") log.warn("getPresentation failed to find a presentation")
return False return False
return True return True

View File

@ -77,7 +77,7 @@ class PresentationPlugin(Plugin):
try: try:
self.controllers[controller].start_process() self.controllers[controller].start_process()
except: except:
log.exception(u'Failed to start controller process') log.warn(u'Failed to start controller process')
self.controllers[controller].available = False self.controllers[controller].available = False
self.mediaItem.buildFileMaskString() self.mediaItem.buildFileMaskString()
@ -128,7 +128,7 @@ class PresentationPlugin(Plugin):
try: try:
__import__(modulename, globals(), locals(), []) __import__(modulename, globals(), locals(), [])
except ImportError: except ImportError:
log.exception(u'Failed to import %s on path %s', log.warn(u'Failed to import %s on path %s',
modulename, path) modulename, path)
controller_classes = PresentationController.__subclasses__() controller_classes = PresentationController.__subclasses__()
for controller_class in controller_classes: for controller_class in controller_classes:

View File

@ -696,7 +696,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.clearCaches() self.clearCaches()
if self._validate_song(): if self._validate_song():
self.saveSong() self.saveSong()
Receiver.send_message(u'songs_load_list')
self.song = None self.song = None
QtGui.QDialog.accept(self) QtGui.QDialog.accept(self)

View File

@ -772,9 +772,9 @@ class SongImportForm(OpenLPWizard):
SettingsManager.get_last_dir(self.plugin.settingsSection, 1)) SettingsManager.get_last_dir(self.plugin.settingsSection, 1))
if not filename: if not filename:
return return
file = codecs.open(filename, u'w', u'utf-8') report_file = codecs.open(filename, u'w', u'utf-8')
file.write(self.errorReportTextEdit.toPlainText()) report_file.write(self.errorReportTextEdit.toPlainText())
file.close() report_file.close()
def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False, def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False,
single_select=False): single_select=False):

View File

@ -32,6 +32,9 @@ from openlp.core.lib import translate
from db import Author from db import Author
from ui import SongStrings from ui import SongStrings
WHITESPACE = re.compile(r'[\W_]+', re.UNICODE)
APOSTROPHE = re.compile(u'[\'`ʻ]', re.UNICODE)
class VerseType(object): class VerseType(object):
""" """
VerseType provides an enumeration for the tags that may be associated VerseType provides an enumeration for the tags that may be associated
@ -246,6 +249,12 @@ def retrieve_windows_encoding(recommendation=None):
return None return None
return filter(lambda item: item[1] == choice[0], encodings)[0][0] return filter(lambda item: item[1] == choice[0], encodings)[0][0]
def clean_string(string):
"""
Strips punctuation from the passed string to assist searching
"""
return WHITESPACE.sub(u' ', APOSTROPHE.sub(u'', string)).lower()
def clean_song(manager, song): def clean_song(manager, song):
""" """
Cleans the search title, rebuilds the search lyrics, adds a default author Cleans the search title, rebuilds the search lyrics, adds a default author
@ -262,9 +271,8 @@ def clean_song(manager, song):
if song.alternate_title is None: if song.alternate_title is None:
song.alternate_title = u'' song.alternate_title = u''
song.alternate_title = song.alternate_title.strip() song.alternate_title = song.alternate_title.strip()
whitespace = re.compile(r'\W+', re.UNICODE) song.search_title = clean_string(song.title) + u'@' + \
song.search_title = (whitespace.sub(u' ', song.title).strip() + u'@' + clean_string(song.alternate_title)
whitespace.sub(u' ', song.alternate_title).strip()).strip().lower()
# Only do this, if we the song is a 1.9.4 song (or older). # Only do this, if we the song is a 1.9.4 song (or older).
if song.lyrics.find(u'<lyrics language="en">') != -1: if song.lyrics.find(u'<lyrics language="en">') != -1:
# Remove the old "language" attribute from lyrics tag (prior to 1.9.5). # Remove the old "language" attribute from lyrics tag (prior to 1.9.5).
@ -273,8 +281,8 @@ def clean_song(manager, song):
song.lyrics = song.lyrics.replace( song.lyrics = song.lyrics.replace(
u'<lyrics language="en">', u'<lyrics>') u'<lyrics language="en">', u'<lyrics>')
verses = SongXML().get_verses(song.lyrics) verses = SongXML().get_verses(song.lyrics)
lyrics = u' '.join([whitespace.sub(u' ', verse[1]) for verse in verses]) song.search_lyrics = u' '.join([clean_string(verse[1])
song.search_lyrics = lyrics.lower() for verse in verses])
# We need a new and clean SongXML instance. # We need a new and clean SongXML instance.
sxml = SongXML() sxml = SongXML()
# Rebuild the song's verses, to remove any wrong verse names (for # Rebuild the song's verses, to remove any wrong verse names (for
@ -316,6 +324,11 @@ def clean_song(manager, song):
if order not in compare_order: if order not in compare_order:
song.verse_order = u'' song.verse_order = u''
break break
else:
verses = SongXML().get_verses(song.lyrics)
song.search_lyrics = u' '.join([clean_string(verse[1])
for verse in verses])
# The song does not have any author, add one. # The song does not have any author, add one.
if not song.authors: if not song.authors:
name = SongStrings.AuthorUnknown name = SongStrings.AuthorUnknown

View File

@ -61,8 +61,8 @@ class EasiSlidesImport(SongImport):
""" """
log.info(u'Importing EasiSlides XML file %s', self.import_source) log.info(u'Importing EasiSlides XML file %s', self.import_source)
parser = etree.XMLParser(remove_blank_text=True) parser = etree.XMLParser(remove_blank_text=True)
file = etree.parse(self.import_source, parser) parsed_file = etree.parse(self.import_source, parser)
xml = unicode(etree.tostring(file)) xml = unicode(etree.tostring(parsed_file))
song_xml = objectify.fromstring(xml) song_xml = objectify.fromstring(xml)
self.import_wizard.progressBar.setMaximum(len(song_xml.Item)) self.import_wizard.progressBar.setMaximum(len(song_xml.Item))
for song in song_xml.Item: for song in song_xml.Item:

View File

@ -28,6 +28,7 @@
The :mod:`importer` modules provides the general song import functionality. The :mod:`importer` modules provides the general song import functionality.
""" """
import logging import logging
from opensongimport import OpenSongImport from opensongimport import OpenSongImport
from easislidesimport import EasiSlidesImport from easislidesimport import EasiSlidesImport
from olpimport import OpenLPSongImport from olpimport import OpenLPSongImport

View File

@ -38,7 +38,8 @@ from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import UiStrings from openlp.core.lib.ui import UiStrings
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \ from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
SongImportForm, SongExportForm SongImportForm, SongExportForm
from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType from openlp.plugins.songs.lib import OpenLyrics, SongXML, VerseType, \
clean_string
from openlp.plugins.songs.lib.db import Author, Song from openlp.plugins.songs.lib.db import Author, Song
from openlp.plugins.songs.lib.ui import SongStrings from openlp.plugins.songs.lib.ui import SongStrings
@ -181,13 +182,14 @@ class SongMediaItem(MediaManagerItem):
elif search_type == SongSearch.Titles: elif search_type == SongSearch.Titles:
log.debug(u'Titles Search') log.debug(u'Titles Search')
search_results = self.plugin.manager.get_all_objects(Song, search_results = self.plugin.manager.get_all_objects(Song,
Song.search_title.like(u'%' + self.whitespace.sub(u' ', Song.search_title.like(u'%' + clean_string(search_keywords) +
search_keywords.lower()) + u'%')) u'%'))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
elif search_type == SongSearch.Lyrics: elif search_type == SongSearch.Lyrics:
log.debug(u'Lyrics Search') log.debug(u'Lyrics Search')
search_results = self.plugin.manager.get_all_objects(Song, search_results = self.plugin.manager.get_all_objects(Song,
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%')) Song.search_lyrics.like(u'%' + clean_string(search_keywords) +
u'%'))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
elif search_type == SongSearch.Authors: elif search_type == SongSearch.Authors:
log.debug(u'Authors Search') log.debug(u'Authors Search')
@ -198,16 +200,16 @@ class SongMediaItem(MediaManagerItem):
elif search_type == SongSearch.Themes: elif search_type == SongSearch.Themes:
log.debug(u'Theme Search') log.debug(u'Theme Search')
search_results = self.plugin.manager.get_all_objects(Song, search_results = self.plugin.manager.get_all_objects(Song,
Song.theme_name.like(u'%' + self.whitespace.sub(u' ', Song.theme_name.like(u'%' + search_keywords + u'%'))
search_keywords) + u'%'))
self.displayResultsSong(search_results) self.displayResultsSong(search_results)
self.check_search_result() self.check_search_result()
def searchEntire(self, search_keywords): def searchEntire(self, search_keywords):
return self.plugin.manager.get_all_objects(Song, return self.plugin.manager.get_all_objects(Song,
or_(Song.search_title.like(u'%' + self.whitespace.sub(u' ', or_(Song.search_title.like(u'%' + clean_string(search_keywords)
search_keywords.lower()) + u'%'), + u'%'),
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'), Song.search_lyrics.like(u'%' + clean_string(search_keywords)
+ u'%'),
Song.comments.like(u'%' + search_keywords.lower() + u'%'))) Song.comments.like(u'%' + search_keywords.lower() + u'%')))
def onSongListLoad(self): def onSongListLoad(self):
@ -300,6 +302,9 @@ class SongMediaItem(MediaManagerItem):
log.debug(u'onNewClick') log.debug(u'onNewClick')
self.edit_song_form.newSong() self.edit_song_form.newSong()
self.edit_song_form.exec_() self.edit_song_form.exec_()
self.onClearTextButtonClick()
self.onSelectionChange()
self.auto_select_id = -1
def onSongMaintenanceClick(self): def onSongMaintenanceClick(self):
self.song_maintenance_form.exec_() self.song_maintenance_form.exec_()
@ -324,6 +329,8 @@ class SongMediaItem(MediaManagerItem):
self.remoteTriggered = remote_type self.remoteTriggered = remote_type
self.edit_song_form.loadSong(song_id, (remote_type == u'P')) self.edit_song_form.loadSong(song_id, (remote_type == u'P'))
self.edit_song_form.exec_() self.edit_song_form.exec_()
self.auto_select_id = -1
self.onSongListLoad()
def onEditClick(self): def onEditClick(self):
""" """
@ -335,6 +342,8 @@ class SongMediaItem(MediaManagerItem):
item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0] item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
self.edit_song_form.loadSong(item_id, False) self.edit_song_form.loadSong(item_id, False)
self.edit_song_form.exec_() self.edit_song_form.exec_()
self.auto_select_id = -1
self.onSongListLoad()
self.editItem = None self.editItem = None
def onDeleteClick(self): def onDeleteClick(self):

View File

@ -102,6 +102,13 @@ psvince.dll
the install will fail. The dll can be obtained from here: the install will fail. The dll can be obtained from here:
http://www.vincenzo.net/isxkb/index.php?title=PSVince) http://www.vincenzo.net/isxkb/index.php?title=PSVince)
Mako
Mako Templates for Python. This package is required for building the
remote plugin. It can be installed by going to your
python_directory\scripts\.. and running "easy_install Mako". If you do not
have easy_install, the Mako package can be obtained here:
http://www.makotemplates.org/download.html
""" """
import os import os
@ -194,7 +201,8 @@ def write_version_file():
code = bzr.wait() code = bzr.wait()
if code != 0: if code != 0:
raise Exception(u'Error running bzr log') raise Exception(u'Error running bzr log')
latest = output.split(u':')[0] outputAscii = unicode(output, errors='ignore')
latest = outputAscii.split(u':')[0]
versionstring = latest == revision and tag or u'%s-bzr%s' % (tag, latest) versionstring = latest == revision and tag or u'%s-bzr%s' % (tag, latest)
f = open(os.path.join(dist_path, u'.version'), u'w') f = open(os.path.join(dist_path, u'.version'), u'w')
f.write(versionstring) f.write(versionstring)