This commit is contained in:
Andreas Preikschat 2011-06-11 11:31:06 +02:00
commit 0c504099ae
77 changed files with 3122 additions and 1076 deletions

7
documentation/manual.txt Normal file
View File

@ -0,0 +1,7 @@
OpenLP Manual
=============
If you're reading this file, you're probably looking for the OpenLP manual. The
manual is hosted online at http://manual.openlp.org/. If you want to help with
the manual, contact the OpenLP team via IRC in the #openlp.org channel on the
Freenode network.

View File

@ -133,6 +133,8 @@ class OpenLP(QtGui.QApplication):
u'general/update check', QtCore.QVariant(True)).toBool()
if update_check:
VersionThread(self.mainWindow).start()
Receiver.send_message(u'maindisplay_blank_check')
self.mainWindow.appStartup()
DelayStartThread(self.mainWindow).start()
return self.exec_()

View File

@ -137,13 +137,12 @@ def image_to_byte(image):
# convert to base64 encoding so does not get missed!
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.
``image``
The image to resize. It has to be either a ``QImage`` instance or the
path to the image.
``image_path``
The path to the image to resize.
``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.
"""
log.debug(u'resize_image - start')
if isinstance(image, QtGui.QImage):
preview = image
reader = QtGui.QImageReader(image_path)
# 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:
preview = QtGui.QImage(image)
if not preview.isNull():
# Only resize if different size
if preview.width() == width and preview.height == height:
# Use the image's width as reference for the new size.
size = QtCore.QSize(width, 1 / (image_ratio / width))
reader.setScaledSize(size)
preview = reader.read()
if image_ratio == resize_ratio:
# We neither need to centre the image nor add "bars" to the image.
return preview
preview = preview.scaled(width, height, QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
realw = preview.width()
realh = preview.height()
# and move it to the centre of the preview space

View File

@ -34,6 +34,7 @@ from PyQt4 import QtCore
from sqlalchemy import create_engine, MetaData
from sqlalchemy.exc import InvalidRequestError
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.pool import NullPool
from openlp.core.utils import AppLocation, delete_file
@ -52,7 +53,7 @@ def init_db(url, auto_flush=True, auto_commit=False):
``auto_commit``
Sets the commit behaviour of the session
"""
engine = create_engine(url)
engine = create_engine(url, poolclass=NullPool)
metadata = MetaData(bind=engine)
session = scoped_session(sessionmaker(autoflush=auto_flush,
autocommit=auto_commit, bind=engine))

View File

@ -47,7 +47,6 @@ class OpenLPDockWidget(QtGui.QDockWidget):
"""
log.debug(u'Initialise the %s widget' % name)
QtGui.QDockWidget.__init__(self, parent)
self.parent = parent
if name:
self.setObjectName(name)
if icon:

View File

@ -91,10 +91,9 @@ class MediaManagerItem(QtGui.QWidget):
Constructor to create the media manager item.
"""
QtGui.QWidget.__init__(self)
self.parent = parent
self.whitespace = re.compile(r'\W+', re.UNICODE)
#TODO: plugin should not be the parent in future
self.plugin = parent # plugin
self.hide()
self.whitespace = re.compile(r'[\W_]+', re.UNICODE)
self.plugin = plugin
visible_title = self.plugin.getString(StringContent.VisibleName)
self.title = unicode(visible_title[u'title'])
self.settingsSection = self.plugin.name.lower()
@ -114,7 +113,7 @@ class MediaManagerItem(QtGui.QWidget):
self.retranslateUi()
self.auto_select_id = -1
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'%s_service_load' % self.parent.name.lower()),
QtCore.SIGNAL(u'%s_service_load' % self.plugin.name.lower()),
self.serviceLoad)
def requiredIcons(self):
@ -392,21 +391,26 @@ class MediaManagerItem(QtGui.QWidget):
self.iconFromFile(image, thumb)
return True
def iconFromFile(self, image, thumb):
def iconFromFile(self, image_path, thumb_path):
"""
Create a thumbnail icon from a given image.
``image``
``image_path``
The image file to create the icon from.
``thumb``
The filename to save the thumbnail to
``thumb_path``
The filename to save the thumbnail to.
"""
icon = build_icon(unicode(image))
pixmap = icon.pixmap(QtCore.QSize(88, 50))
ext = os.path.splitext(thumb)[1].lower()
pixmap.save(thumb, ext[1:])
return icon
ext = os.path.splitext(thumb_path)[1].lower()
reader = QtGui.QImageReader(image_path)
ratio = float(reader.size().width()) / float(reader.size().height())
reader.setScaledSize(QtCore.QSize(int(ratio * 88), 88))
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):
raise NotImplementedError(u'MediaManagerItem.loadList needs to be '
@ -455,7 +459,8 @@ class MediaManagerItem(QtGui.QWidget):
"""
if QtCore.QSettings().value(u'advanced/single click preview',
QtCore.QVariant(False)).toBool() and self.quickPreviewAllowed \
and self.listView.selectedIndexes():
and self.listView.selectedIndexes() \
and self.auto_select_id == -1:
self.onPreviewClick(True)
def onPreviewClick(self, keepFocus=False):
@ -472,7 +477,7 @@ class MediaManagerItem(QtGui.QWidget):
serviceItem = self.buildServiceItem()
if serviceItem:
serviceItem.from_plugin = True
self.parent.previewController.addServiceItem(serviceItem)
self.plugin.previewController.addServiceItem(serviceItem)
if keepFocus:
self.listView.setFocus()
@ -497,7 +502,7 @@ class MediaManagerItem(QtGui.QWidget):
if serviceItem:
if not item_id:
serviceItem.from_plugin = True
self.parent.liveController.addServiceItem(serviceItem)
self.plugin.liveController.addServiceItem(serviceItem)
def createItemFromId(self, item_id):
item = QtGui.QListWidgetItem()
@ -527,7 +532,7 @@ class MediaManagerItem(QtGui.QWidget):
serviceItem = self.buildServiceItem(item, True)
if serviceItem:
serviceItem.from_plugin = False
self.parent.serviceManager.addServiceItem(serviceItem,
self.plugin.serviceManager.addServiceItem(serviceItem,
replace=replace)
def onAddEditClick(self):
@ -540,14 +545,14 @@ class MediaManagerItem(QtGui.QWidget):
'You must select one or more items.'))
else:
log.debug(u'%s Add requested', self.plugin.name)
serviceItem = self.parent.serviceManager.getServiceItem()
serviceItem = self.plugin.serviceManager.getServiceItem()
if not serviceItem:
QtGui.QMessageBox.information(self, UiStrings().NISs,
translate('OpenLP.MediaManagerItem',
'You must select an existing service item to add to.'))
elif self.plugin.name.lower() == serviceItem.name.lower():
self.generateSlideData(serviceItem)
self.parent.serviceManager.addServiceItem(serviceItem,
self.plugin.serviceManager.addServiceItem(serviceItem,
replace=True)
else:
# Turn off the remote edit update message indicator
@ -561,8 +566,8 @@ class MediaManagerItem(QtGui.QWidget):
"""
Common method for generating a service item
"""
serviceItem = ServiceItem(self.parent)
serviceItem.add_icon(self.parent.icon_path)
serviceItem = ServiceItem(self.plugin)
serviceItem.add_icon(self.plugin.icon_path)
if self.generateSlideData(serviceItem, item, xmlVersion):
return serviceItem
else:

View File

@ -215,7 +215,8 @@ class Plugin(QtCore.QObject):
you need, and return it for integration into openlp.org.
"""
if self.media_item_class:
return self.media_item_class(self, self, self.icon)
return self.media_item_class(self.mediadock.media_dock, self,
self.icon)
return None
def addImportMenuItem(self, importMenu):
@ -299,6 +300,12 @@ class Plugin(QtCore.QObject):
if self.mediaItem:
self.mediadock.remove_dock(self.mediaItem)
def appStartup(self):
"""
Perform tasks on application starup
"""
pass
def usesTheme(self, theme):
"""
Called to find out if a plugin is currently using a theme.

View File

@ -67,7 +67,7 @@ class Renderer(object):
``theme_manager``
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.image_manager = image_manager
self.screens = ScreenList.get_instance()
@ -77,7 +77,7 @@ class Renderer(object):
self.theme_data = None
self.bg_frame = None
self.force_page = False
self.display = MainDisplay(self, self.image_manager, False)
self.display = MainDisplay(None, self.image_manager, False)
self.display.setup()
def update_display(self):
@ -86,7 +86,9 @@ class Renderer(object):
"""
log.debug(u'Update Display')
self._calculate_default(self.screens.current[u'size'])
self.display = MainDisplay(self, self.image_manager, False)
if self.display:
self.display.close()
self.display = MainDisplay(None, self.image_manager, False)
self.display.setup()
self.bg_frame = None
self.theme_data = None
@ -241,7 +243,7 @@ class Renderer(object):
``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.height = screen.height()
self.screen_ratio = float(self.height) / float(self.width)
@ -286,7 +288,7 @@ class Renderer(object):
``rect_footer``
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_footer = rect_footer
self.page_width = self._rect.width()
@ -339,7 +341,7 @@ class Renderer(object):
# Text too long so go to next page.
if self.web_frame.contentsSize().height() > self.page_height:
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
while html_text.endswith(u'<br>'):
html_text = html_text[:-4]

View File

@ -85,7 +85,6 @@ class UiStrings(object):
self.LengthTime = unicode(translate('OpenLP.Ui', 'Length %s'))
self.Live = translate('OpenLP.Ui', 'Live')
self.LiveBGError = translate('OpenLP.Ui', 'Live Background Error')
self.LivePanel = translate('OpenLP.Ui', 'Live Panel')
self.LiveToolbar = translate('OpenLP.Ui', 'Live Toolbar')
self.Load = translate('OpenLP.Ui', 'Load')
self.Minutes = translate('OpenLP.Ui', 'm',
@ -102,14 +101,13 @@ class UiStrings(object):
self.OLPV2 = translate('OpenLP.Ui', 'OpenLP 2.0')
self.OpenLPStart = translate('OpenLP.Ui', 'OpenLP is already running. '
'Do you wish to continue?')
self.OpenService = translate('OpenLP.Ui', 'Open Service')
self.OpenService = translate('OpenLP.Ui', 'Open service.')
self.Preview = translate('OpenLP.Ui', 'Preview')
self.PreviewPanel = translate('OpenLP.Ui', 'Preview Panel')
self.PrintServiceOrder = translate('OpenLP.Ui', 'Print Service Order')
self.PrintService = translate('OpenLP.Ui', 'Print Service')
self.ReplaceBG = translate('OpenLP.Ui', 'Replace Background')
self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace Live Background')
self.ReplaceLiveBG = translate('OpenLP.Ui', 'Replace live background.')
self.ResetBG = translate('OpenLP.Ui', 'Reset Background')
self.ResetLiveBG = translate('OpenLP.Ui', 'Reset Live Background')
self.ResetLiveBG = translate('OpenLP.Ui', 'Reset live background.')
self.Seconds = translate('OpenLP.Ui', 's',
'The abbreviated unit for seconds')
self.SaveAndPreview = translate('OpenLP.Ui', 'Save && Preview')
@ -121,6 +119,9 @@ class UiStrings(object):
self.Settings = translate('OpenLP.Ui', 'Settings')
self.SaveService = translate('OpenLP.Ui', 'Save Service')
self.Service = translate('OpenLP.Ui', 'Service')
self.Split = translate('OpenLP.Ui', '&Split')
self.SplitToolTip = translate('OpenLP.Ui', 'Split a slide into two '
'only if it does not fit on the screen as one slide.')
self.StartTimeCode = unicode(translate('OpenLP.Ui', 'Start %s'))
self.Theme = translate('OpenLP.Ui', 'Theme', 'Singular')
self.Themes = translate('OpenLP.Ui', 'Themes', 'Plural')

View File

@ -147,6 +147,7 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
DisplayTags.remove_html_tag(self.selected)
self.selected = -1
self._resetTable()
self._saveTable()
def onSavedPushed(self):
"""
@ -171,14 +172,19 @@ class DisplayTagForm(QtGui.QDialog, Ui_DisplayTagDialog):
html[u'end tag'] = u'{/%s}' % tag
self.selected = -1
self._resetTable()
temp = []
self._saveTable()
def _saveTable(self):
"""
Saves all display tags except protected ones.
"""
tags = []
for tag in DisplayTags.get_html_tags():
if not tag[u'protected']:
temp.append(tag)
if temp:
ctemp = cPickle.dumps(temp)
tags.append(tag)
if tags:
QtCore.QSettings().setValue(u'displayTags/html_tags',
QtCore.QVariant(ctemp))
QtCore.QVariant(cPickle.dumps(tags)))
else:
QtCore.QSettings().setValue(u'displayTags/html_tags',
QtCore.QVariant(u''))

View File

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

View File

@ -200,15 +200,14 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
"""
Prepare the UI for the process.
"""
# We start on 2 for plugins status setting plus a "finished" point.
max_progress = 2
self.max_progress = 0
# Loop through the songs list and increase for each selected item
for i in xrange(self.songsListWidget.count()):
item = self.songsListWidget.item(i)
if item.checkState() == QtCore.Qt.Checked:
filename = item.data(QtCore.Qt.UserRole).toString()
size = self._getFileSize(u'%s%s' % (self.web, filename))
max_progress += size
self.max_progress += size
# Loop through the Bibles list and increase for each selected item
iterator = QtGui.QTreeWidgetItemIterator(self.biblesTreeWidget)
while iterator.value():
@ -216,7 +215,7 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
if item.parent() and item.checkState(0) == QtCore.Qt.Checked:
filename = item.data(0, QtCore.Qt.UserRole).toString()
size = self._getFileSize(u'%s%s' % (self.web, filename))
max_progress += size
self.max_progress += size
iterator += 1
# Loop through the themes list and increase for each selected item
for i in xrange(self.themesListWidget.count()):
@ -224,23 +223,40 @@ class FirstTimeForm(QtGui.QWizard, Ui_FirstTimeWizard):
if item.checkState() == QtCore.Qt.Checked:
filename = item.data(QtCore.Qt.UserRole).toString()
size = self._getFileSize(u'%s%s' % (self.web, filename))
max_progress += size
self.max_progress += size
self.finishButton.setVisible(False)
if self.max_progress:
# Add on 2 for plugins status setting plus a "finished" point.
self.max_progress = self.max_progress + 2
self.progressBar.setValue(0)
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(max_progress)
self.progressBar.setMaximum(self.max_progress)
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard',
'Setting Up And Downloading'))
self.progressPage.setSubTitle(translate('OpenLP.FirstTimeWizard',
'Please wait while OpenLP is set up '
'and your data is downloaded.'))
else:
self.progressBar.setVisible(False)
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard',
'Setting Up'))
self.progressPage.setSubTitle(u'Setup complete.')
def _postWizard(self):
"""
Clean up the UI after the process has finished.
"""
if self.max_progress:
self.progressBar.setValue(self.progressBar.maximum())
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
'Download complete. Click the finish button to start OpenLP.'))
else:
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
'Click the finish button to start OpenLP.'))
self.finishButton.setVisible(True)
self.finishButton.setEnabled(True)
self.cancelButton.setVisible(False)
self.nextButton.setVisible(False)
self.progressLabel.setText(translate('OpenLP.FirstTimeWizard',
'Download complete. Click the finish button to start OpenLP.'))
Receiver.send_message(u'openlp_process_events')
def _performWizard(self):

View File

@ -254,10 +254,6 @@ class Ui_FirstTimeWizard(object):
'Default Settings'))
self.defaultsPage.setSubTitle(translate('OpenLP.FirstTimeWizard',
'Set up default settings to be used by OpenLP.'))
self.progressPage.setTitle(translate('OpenLP.FirstTimeWizard',
'Setting Up And Importing'))
self.progressPage.setSubTitle(translate('OpenLP.FirstTimeWizard',
'Please wait while OpenLP is set up and your data is imported.'))
self.displayLabel.setText(translate('OpenLP.FirstTimeWizard',
'Default output display:'))
self.themeLabel.setText(translate('OpenLP.FirstTimeWizard',

View File

@ -49,8 +49,7 @@ class MainDisplay(QtGui.QGraphicsView):
This is the display screen.
"""
def __init__(self, parent, image_manager, live):
QtGui.QGraphicsView.__init__(self)
self.parent = parent
QtGui.QGraphicsView.__init__(self, parent)
self.isLive = live
self.image_manager = image_manager
self.screens = ScreenList.get_instance()
@ -64,6 +63,7 @@ class MainDisplay(QtGui.QGraphicsView):
self.setStyleSheet(u'border: 0px; margin: 0px; padding: 0px;')
self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool |
QtCore.Qt.WindowStaysOnTopHint)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
if self.isLive:
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'maindisplay_hide'), self.hideDisplay)
@ -149,7 +149,6 @@ class MainDisplay(QtGui.QGraphicsView):
self.__hideMouse()
# To display or not to display?
if not self.screen[u'primary']:
self.show()
self.primary = False
else:
self.primary = True

View File

@ -179,7 +179,7 @@ class Ui_MainWindow(object):
u'printServiceItem', [QtGui.QKeySequence(u'Ctrl+P')],
self.serviceManagerContents.printServiceOrder,
category=UiStrings().File)
self.fileExitItem = shortcut_action(mainWindow, u'FileExitItem',
self.fileExitItem = shortcut_action(mainWindow, u'fileExitItem',
[QtGui.QKeySequence(u'Alt+F4')], mainWindow.close,
u':/system/system_exit.png', category=UiStrings().File)
action_list.add_category(UiStrings().Import, CategoryOrder.standardMenu)
@ -356,9 +356,9 @@ class Ui_MainWindow(object):
translate('OpenLP.MainWindow', 'Save Service As'))
self.fileSaveAsItem.setStatusTip(translate('OpenLP.MainWindow',
'Save the current service under a new name.'))
self.printServiceOrderItem.setText(UiStrings().PrintServiceOrder)
self.printServiceOrderItem.setText(UiStrings().PrintService)
self.printServiceOrderItem.setStatusTip(translate('OpenLP.MainWindow',
'Print the current Service Order.'))
'Print the current service.'))
self.fileExitItem.setText(
translate('OpenLP.MainWindow', 'E&xit'))
self.fileExitItem.setStatusTip(
@ -651,6 +651,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.setViewMode(False, True, False, False, True)
self.modeLiveItem.setChecked(True)
def appStartup(self):
# Give all the plugins a chance to perform some tasks at startup
Receiver.send_message(u'openlp_process_events')
for plugin in self.pluginManager.plugins:
if plugin.isActive():
Receiver.send_message(u'openlp_process_events')
plugin.appStartup()
Receiver.send_message(u'openlp_process_events')
def firstTime(self):
# Import themes if first time
Receiver.send_message(u'openlp_process_events')
@ -669,13 +678,12 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def blankCheck(self):
"""
Check and display message if screen blank on setup.
Triggered by delay thread.
"""
settings = QtCore.QSettings()
self.liveController.mainDisplaySetBackground()
if settings.value(u'%s/screen blank' % self.generalSettingsSection,
QtCore.QVariant(False)).toBool():
self.liveController.mainDisplaySetBackground()
if settings.value(u'blank warning',
if settings.value(u'%s/blank warning' % self.generalSettingsSection,
QtCore.QVariant(False)).toBool():
QtGui.QMessageBox.question(self,
translate('OpenLP.MainWindow',

View File

@ -40,7 +40,6 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
"""
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent)
self.parent = parent
self.activePlugin = None
self.programaticChange = False
self.setupUi(self)
@ -65,7 +64,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
self._clearDetails()
self.programaticChange = True
pluginListWidth = 0
for plugin in self.parent.pluginManager.plugins:
for plugin in self.parent().pluginManager.plugins:
item = QtGui.QListWidgetItem(self.pluginListWidget)
# We do this just to make 100% sure the status is an integer as
# sometimes when it's loaded from the config, it isn't cast to int.
@ -117,7 +116,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
plugin_name_singular = \
self.pluginListWidget.currentItem().text().split(u' ')[0]
self.activePlugin = None
for plugin in self.parent.pluginManager.plugins:
for plugin in self.parent().pluginManager.plugins:
if plugin.nameStrings[u'singular'] == plugin_name_singular:
self.activePlugin = plugin
break
@ -133,6 +132,7 @@ class PluginForm(QtGui.QDialog, Ui_PluginViewDialog):
Receiver.send_message(u'cursor_busy')
self.activePlugin.toggleStatus(PluginStatus.Active)
Receiver.send_message(u'cursor_normal')
self.activePlugin.appStartup()
else:
self.activePlugin.toggleStatus(PluginStatus.Inactive)
status_text = unicode(

View File

@ -149,7 +149,7 @@ class Ui_PrintServiceDialog(object):
QtCore.SIGNAL(u'toggled(bool)'), self.toggleOptions)
def retranslateUi(self, printServiceDialog):
printServiceDialog.setWindowTitle(UiStrings().PrintServiceOrder)
printServiceDialog.setWindowTitle(UiStrings().PrintService)
self.slideTextCheckBox.setText(translate('OpenLP.PrintServiceForm',
'Include slide text if available'))
self.pageBreakAfterText.setText(translate('OpenLP.PrintServiceForm',
@ -159,7 +159,7 @@ class Ui_PrintServiceDialog(object):
self.metaDataCheckBox.setText(translate('OpenLP.PrintServiceForm',
'Include play length of media items'))
self.titleLineEdit.setText(translate('OpenLP.PrintServiceForm',
'Service Order Sheet'))
'Service Sheet'))
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Page])
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.Width])
self.zoomComboBox.addItem(ZoomSize.Sizes[ZoomSize.OneHundred])

View File

@ -42,42 +42,44 @@ http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties
*/
.serviceTitle {
font-weight:600;
font-size:x-large;
color:black;
font-weight: 600;
font-size: x-large;
color: black;
}
.item {
color:black;
color: black;
}
.itemTitle {
font-weight:600;
font-size:large;
font-weight: 600;
font-size: large;
}
.itemText {}
.itemText {
margin-top: 10px;
}
.itemFooter {
font-size:8px;
font-size: 8px;
}
.itemNotes {}
.itemNotesTitle {
font-weight:bold;
font-size:12px;
font-weight: bold;
font-size: 12px;
}
.itemNotesText {
font-size:11px;
font-size: 11px;
}
.media {}
.mediaTitle {
font-weight:bold;
font-size:11px;
font-weight: bold;
font-size: 11px;
}
.mediaText {}
@ -89,16 +91,16 @@ http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties
}
.customNotesTitle {
font-weight:bold;
font-size:11px;
font-weight: bold;
font-size: 11px;
}
.customNotesText {
font-size:11px;
font-size: 11px;
}
.newPage {
page-break-before:always;
page-break-before: always;
}
"""
@ -212,11 +214,11 @@ class PrintServiceForm(QtGui.QDialog, Ui_PrintServiceDialog):
verse_def = None
for slide in item.get_frames():
if not verse_def or verse_def != slide[u'verseTag']:
p = self._addElement(u'div', parent=div,
text_div = self._addElement(u'div', parent=div,
classId=u'itemText')
else:
self._addElement(u'br', parent=p)
self._addElement(u'p', slide[u'html'], p)
self._addElement(u'br', parent=text_div)
self._addElement(u'span', slide[u'html'], text_div)
verse_def = slide[u'verseTag']
# Break the page before the div element.
if index != 0 and self.pageBreakAfterText.isChecked():

View File

@ -79,7 +79,7 @@ class ScreenList(object):
``number``
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:
if number == screen[u'number']:
newScreen = {
@ -104,6 +104,9 @@ class ScreenList(object):
``changed_screen``
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.
for screen in copy.deepcopy(self.screen_list):
if screen[u'number'] == self.desktop.numScreens():
@ -116,8 +119,7 @@ class ScreenList(object):
u'size': self.desktop.screenGeometry(number),
u'primary': (self.desktop.primaryScreen() == number)
})
# We do not want to send this message, when the method is called the
# first time.
# We do not want to send this message at start up.
if changed_screen != -1:
# Reload setting tabs to apply possible changes.
Receiver.send_message(u'config_screen_changed')
@ -241,6 +243,7 @@ class ScreenList(object):
height = settings.value(u'height',
QtCore.QVariant(self.current[u'size'].height())).toInt()[0]
self.override[u'size'] = QtCore.QRect(x, y, width, height)
self.override[u'primary'] = False
settings.endGroup()
if override_display:
self.set_override_display()

View File

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

View File

@ -46,7 +46,6 @@ class SlideList(QtGui.QTableWidget):
"""
def __init__(self, parent=None, name=None):
QtGui.QTableWidget.__init__(self, parent.controller)
self.parent = parent
class SlideController(QtGui.QWidget):
@ -60,13 +59,13 @@ class SlideController(QtGui.QWidget):
"""
QtGui.QWidget.__init__(self, parent)
self.isLive = isLive
self.parent = parent
self.display = None
self.screens = ScreenList.get_instance()
self.ratio = float(self.screens.current[u'size'].width()) / \
float(self.screens.current[u'size'].height())
self.image_manager = self.parent.image_manager
self.image_manager = self.parent().image_manager
self.loopList = [
u'Start Loop',
u'Play Slides Menu',
u'Loop Separator',
u'Image SpinBox'
]
@ -153,6 +152,7 @@ class SlideController(QtGui.QWidget):
context=QtCore.Qt.WidgetWithChildrenShortcut)
self.toolbar.addToolbarSeparator(u'Close Separator')
if self.isLive:
# Hide Menu
self.hideMenu = QtGui.QToolButton(self.toolbar)
self.hideMenu.setText(translate('OpenLP.SlideController', 'Hide'))
self.hideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
@ -180,27 +180,34 @@ class SlideController(QtGui.QWidget):
self.hideMenu.menu().addAction(self.themeScreen)
self.hideMenu.menu().addAction(self.desktopScreen)
self.toolbar.addToolbarSeparator(u'Loop Separator')
startLoop = self.toolbar.addToolbarButton(
# Does not need translating - control string.
u'Start Loop', u':/media/media_time.png',
translate('OpenLP.SlideController', 'Enable timed slides.'),
self.onStartLoop)
startLoop.setObjectName(u'startLoop')
action_list = ActionList.get_instance()
action_list.add_action(startLoop, UiStrings().LiveToolbar)
stopLoop = self.toolbar.addToolbarButton(
# Does not need translating - control string.
u'Stop Loop', u':/media/media_stop.png',
translate('OpenLP.SlideController', 'Stop timed slides.'),
self.onStopLoop)
stopLoop.setObjectName(u'stopLoop')
action_list.add_action(stopLoop, UiStrings().LiveToolbar)
self.toogleLoop = shortcut_action(self, u'toogleLoop',
[QtGui.QKeySequence(u'L')], self.onToggleLoop,
category=UiStrings().LiveToolbar)
self.toogleLoop.setText(translate('OpenLP.SlideController',
'Start/Stop continuous loop'))
self.addAction(self.toogleLoop)
# Play Slides Menu
self.playSlidesMenu = QtGui.QToolButton(self.toolbar)
self.playSlidesMenu.setText(translate('OpenLP.SlideController',
'Play Slides'))
self.playSlidesMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup)
self.toolbar.addToolbarWidget(u'Play Slides Menu',
self.playSlidesMenu)
self.playSlidesMenu.setMenu(QtGui.QMenu(
translate('OpenLP.SlideController', 'Play Slides'),
self.toolbar))
self.playSlidesLoop = shortcut_action(self.playSlidesMenu,
u'playSlidesLoop', [], self.onPlaySlidesLoop,
u':/media/media_time.png', False, UiStrings().LiveToolbar)
self.playSlidesLoop.setText(
translate('OpenLP.SlideController', 'Play Slides in Loop'))
self.playSlidesOnce = shortcut_action(self.playSlidesMenu,
u'playSlidesOnce', [], self.onPlaySlidesOnce,
u':/media/media_time.png', False, UiStrings().LiveToolbar)
self.playSlidesOnce.setText(
translate('OpenLP.SlideController', 'Play Slides to End'))
if QtCore.QSettings().value(self.parent().generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool():
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
else:
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
self.playSlidesMenu.menu().addAction(self.playSlidesLoop)
self.playSlidesMenu.menu().addAction(self.playSlidesOnce)
# Loop Delay Spinbox
self.delaySpinBox = QtGui.QSpinBox()
self.delaySpinBox.setRange(1, 180)
self.toolbar.addToolbarWidget(u'Image SpinBox', self.delaySpinBox)
@ -321,7 +328,6 @@ class SlideController(QtGui.QWidget):
QtCore.SIGNAL(u'slidecontroller_live_spin_delay'),
self.receiveSpinDelay)
self.toolbar.makeWidgetsInvisible(self.loopList)
self.toolbar.actions[u'Stop Loop'].setVisible(False)
else:
QtCore.QObject.connect(self.previewListWidget,
QtCore.SIGNAL(u'doubleClicked(QModelIndex)'),
@ -417,6 +423,8 @@ class SlideController(QtGui.QWidget):
screen previews.
"""
# rebuild display as screen size changed
if self.display:
self.display.close()
self.display = MainDisplay(self, self.image_manager, self.isLive)
self.display.alertTab = self.alertTab
self.display.setup()
@ -461,7 +469,7 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.resizeRowsToContents()
else:
# Sort out image heights.
width = self.parent.controlSplitter.sizes()[self.split]
width = self.parent().controlSplitter.sizes()[self.split]
for framenumber in range(len(self.serviceItem.get_frames())):
self.previewListWidget.setRowHeight(
framenumber, width / self.ratio)
@ -496,21 +504,14 @@ class SlideController(QtGui.QWidget):
self.mediabar.setVisible(False)
self.toolbar.makeWidgetsInvisible([u'Song Menu'])
self.toolbar.makeWidgetsInvisible(self.loopList)
self.toogleLoop.setEnabled(False)
self.toolbar.actions[u'Start Loop'].setEnabled(False)
self.toolbar.actions[u'Stop Loop'].setEnabled(False)
self.toolbar.actions[u'Stop Loop'].setVisible(False)
if item.is_text():
if QtCore.QSettings().value(
self.parent.songsSettingsSection + u'/display songbar',
self.parent().songsSettingsSection + u'/display songbar',
QtCore.QVariant(True)).toBool() and len(self.slideList) > 0:
self.toolbar.makeWidgetsVisible([u'Song Menu'])
if item.is_capable(ItemCapabilities.AllowsLoop) and \
len(item.get_frames()) > 1:
self.toolbar.makeWidgetsVisible(self.loopList)
self.toogleLoop.setEnabled(True)
self.toolbar.actions[u'Start Loop'].setEnabled(True)
self.toolbar.actions[u'Stop Loop'].setEnabled(True)
if item.is_media():
self.toolbar.setVisible(False)
self.mediabar.setVisible(True)
@ -591,7 +592,7 @@ class SlideController(QtGui.QWidget):
Receiver.send_message(u'%s_start' % serviceItem.name.lower(),
[serviceItem, self.isLive, self.hideMode(), slideno])
self.slideList = {}
width = self.parent.controlSplitter.sizes()[self.split]
width = self.parent().controlSplitter.sizes()[self.split]
self.previewListWidget.clear()
self.previewListWidget.setRowCount(0)
self.previewListWidget.setColumnWidth(0, width)
@ -625,8 +626,8 @@ class SlideController(QtGui.QWidget):
label.setScaledContents(True)
if self.serviceItem.is_command():
image = resize_image(frame[u'image'],
self.parent.renderer.width,
self.parent.renderer.height)
self.parent().renderer.width,
self.parent().renderer.height)
else:
# If current slide set background to image
if framenumber == slideno:
@ -635,7 +636,7 @@ class SlideController(QtGui.QWidget):
image = self.image_manager.get_image(frame[u'title'])
label.setPixmap(QtGui.QPixmap.fromImage(image))
self.previewListWidget.setCellWidget(framenumber, 0, label)
slideHeight = width * self.parent.renderer.screen_ratio
slideHeight = width * self.parent().renderer.screen_ratio
row += 1
text.append(unicode(row))
self.previewListWidget.setItem(framenumber, 0, item)
@ -736,7 +737,7 @@ class SlideController(QtGui.QWidget):
"""
log.debug(u'mainDisplaySetBackground live = %s' % self.isLive)
display_type = QtCore.QSettings().value(
self.parent.generalSettingsSection + u'/screen blank',
self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'')).toString()
if not self.display.primary:
# Order done to handle initial conversion
@ -744,8 +745,10 @@ class SlideController(QtGui.QWidget):
self.onThemeDisplay(True)
elif display_type == u'hidden':
self.onHideDisplay(True)
else:
elif display_type == u'blanked':
self.onBlankDisplay(True)
else:
Receiver.send_message(u'maindisplay_show')
def onSlideBlank(self):
"""
@ -772,11 +775,11 @@ class SlideController(QtGui.QWidget):
self.desktopScreen.setChecked(False)
if checked:
QtCore.QSettings().setValue(
self.parent.generalSettingsSection + u'/screen blank',
self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'blanked'))
else:
QtCore.QSettings().remove(
self.parent.generalSettingsSection + u'/screen blank')
self.parent().generalSettingsSection + u'/screen blank')
self.blankPlugin()
self.updatePreview()
@ -793,11 +796,11 @@ class SlideController(QtGui.QWidget):
self.desktopScreen.setChecked(False)
if checked:
QtCore.QSettings().setValue(
self.parent.generalSettingsSection + u'/screen blank',
self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'themed'))
else:
QtCore.QSettings().remove(
self.parent.generalSettingsSection + u'/screen blank')
self.parent().generalSettingsSection + u'/screen blank')
self.blankPlugin()
self.updatePreview()
@ -814,11 +817,11 @@ class SlideController(QtGui.QWidget):
self.desktopScreen.setChecked(checked)
if checked:
QtCore.QSettings().setValue(
self.parent.generalSettingsSection + u'/screen blank',
self.parent().generalSettingsSection + u'/screen blank',
QtCore.QVariant(u'hidden'))
else:
QtCore.QSettings().remove(
self.parent.generalSettingsSection + u'/screen blank')
self.parent().generalSettingsSection + u'/screen blank')
self.hidePlugin(checked)
self.updatePreview()
@ -943,7 +946,7 @@ class SlideController(QtGui.QWidget):
rect.y(), rect.width(), rect.height())
self.slidePreview.setPixmap(winimg)
def onSlideSelectedNext(self):
def onSlideSelectedNext(self, wrap=None):
"""
Go to the next slide.
"""
@ -956,8 +959,11 @@ class SlideController(QtGui.QWidget):
else:
row = self.previewListWidget.currentRow() + 1
if row == self.previewListWidget.rowCount():
if QtCore.QSettings().value(self.parent.generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool():
if wrap is None:
wrap = QtCore.QSettings().value(
self.parent().generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool()
if wrap:
row = 0
else:
row = self.previewListWidget.rowCount() - 1
@ -977,8 +983,8 @@ class SlideController(QtGui.QWidget):
else:
row = self.previewListWidget.currentRow() - 1
if row == -1:
if QtCore.QSettings().value(self.parent.generalSettingsSection +
u'/enable slide loop', QtCore.QVariant(True)).toBool():
if QtCore.QSettings().value(self.parent().generalSettingsSection
+ u'/enable slide loop', QtCore.QVariant(True)).toBool():
row = self.previewListWidget.rowCount() - 1
else:
row = 0
@ -1006,11 +1012,11 @@ class SlideController(QtGui.QWidget):
self.previewListWidget.rowCount() - 1)
self.slideSelected()
def onToggleLoop(self, toggled):
def onToggleLoop(self):
"""
Toggles the loop state.
"""
if self.toolbar.actions[u'Start Loop'].isVisible():
if self.playSlidesLoop.isChecked() or self.playSlidesOnce.isChecked():
self.onStartLoop()
else:
self.onStopLoop()
@ -1022,8 +1028,6 @@ class SlideController(QtGui.QWidget):
if self.previewListWidget.rowCount() > 1:
self.timer_id = self.startTimer(
int(self.delaySpinBox.value()) * 1000)
self.toolbar.actions[u'Stop Loop'].setVisible(True)
self.toolbar.actions[u'Start Loop'].setVisible(False)
def onStopLoop(self):
"""
@ -1032,15 +1036,39 @@ class SlideController(QtGui.QWidget):
if self.timer_id != 0:
self.killTimer(self.timer_id)
self.timer_id = 0
self.toolbar.actions[u'Start Loop'].setVisible(True)
self.toolbar.actions[u'Stop Loop'].setVisible(False)
def onPlaySlidesLoop(self, checked=None):
"""
Start or stop 'Play Slides in Loop'
"""
if checked is None:
checked = self.playSlidesLoop.isChecked()
else:
self.playSlidesLoop.setChecked(checked)
log.debug(u'onPlaySlidesLoop %s' % checked)
self.playSlidesMenu.setDefaultAction(self.playSlidesLoop)
self.playSlidesOnce.setChecked(False)
self.onToggleLoop()
def onPlaySlidesOnce(self, checked=None):
"""
Start or stop 'Play Slides to End'
"""
if checked is None:
checked = self.playSlidesOnce.isChecked()
else:
self.playSlidesOnce.setChecked(checked)
log.debug(u'onPlaySlidesOnce %s' % checked)
self.playSlidesMenu.setDefaultAction(self.playSlidesOnce)
self.playSlidesLoop.setChecked(False)
self.onToggleLoop()
def timerEvent(self, event):
"""
If the timer event is for this window select next slide
"""
if event.timerId() == self.timer_id:
self.onSlideSelectedNext()
self.onSlideSelectedNext(self.playSlidesLoop.isChecked())
def onEditSong(self):
"""
@ -1055,7 +1083,8 @@ class SlideController(QtGui.QWidget):
From the preview display request the Item to be added to service
"""
if self.serviceItem:
self.parent.serviceManagerContents.addServiceItem(self.serviceItem)
self.parent().serviceManagerContents.addServiceItem(
self.serviceItem)
def onGoLiveClick(self):
"""
@ -1083,7 +1112,7 @@ class SlideController(QtGui.QWidget):
Receiver.send_message('servicemanager_preview_live',
u'%s:%s' % (self.serviceItem._uuid, row))
else:
self.parent.liveController.addServiceManagerItem(
self.parent().liveController.addServiceManagerItem(
self.serviceItem, row)
def onMediaStart(self, item):

View File

@ -202,7 +202,7 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard):
Updates the lines on a page on the wizard
"""
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):
"""

View File

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

View File

@ -77,6 +77,8 @@ class LanguageManager(object):
AppLocation.LanguageDir))
file_names = trans_dir.entryList(QtCore.QStringList(u'*.qm'),
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:
file_names.replaceInStrings(name, trans_dir.filePath(name))
return file_names

View File

@ -41,7 +41,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
Initialise the alert form
"""
self.manager = plugin.manager
self.parent = plugin
self.plugin = plugin
self.item_id = None
QtGui.QDialog.__init__(self, plugin.formparent)
self.setupUi(self)
@ -195,7 +195,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog):
self.parameterEdit.setFocus()
return False
text = text.replace(u'<>', unicode(self.parameterEdit.text()))
self.parent.alertsmanager.displayAlert(text)
self.plugin.alertsmanager.displayAlert(text)
return True
def onCurrentRowChanged(self, row):

View File

@ -40,8 +40,7 @@ class AlertsManager(QtCore.QObject):
log.info(u'Alert Manager loaded')
def __init__(self, parent):
QtCore.QObject.__init__(self)
self.parent = parent
QtCore.QObject.__init__(self, parent)
self.screen = None
self.timer_id = 0
self.alertList = []
@ -85,8 +84,8 @@ class AlertsManager(QtCore.QObject):
if len(self.alertList) == 0:
return
text = self.alertList.pop(0)
alertTab = self.parent.settings_tab
self.parent.liveController.display.alert(text)
alertTab = self.parent().settings_tab
self.parent().liveController.display.alert(text)
# Check to see if we have a timer running.
if self.timer_id == 0:
self.timer_id = self.startTimer(int(alertTab.timeout) * 1000)
@ -101,7 +100,7 @@ class AlertsManager(QtCore.QObject):
"""
log.debug(u'timer event')
if event.timerId() == self.timer_id:
self.parent.liveController.display.alert(u'')
self.parent().liveController.display.alert(u'')
self.killTimer(self.timer_id)
self.timer_id = 0
self.generateAlert()

View File

@ -33,6 +33,7 @@ from openlp.core.lib import Plugin, StringContent, build_icon, translate
from openlp.core.lib.ui import base_action, UiStrings
from openlp.core.utils.actions import ActionList
from openlp.plugins.bibles.lib import BibleManager, BiblesTab, BibleMediaItem
from openlp.plugins.bibles.forms import BibleUpgradeForm
log = logging.getLogger(__name__)
@ -59,6 +60,8 @@ class BiblePlugin(Plugin):
#action_list.add_action(self.exportBibleItem, UiStrings().Export)
# Set to invisible until we can export bibles
self.exportBibleItem.setVisible(False)
if len(self.manager.old_bible_databases):
self.toolsUpgradeItem.setVisible(True)
def finalise(self):
"""
@ -73,6 +76,19 @@ class BiblePlugin(Plugin):
#action_list.remove_action(self.exportBibleItem, UiStrings().Export)
self.exportBibleItem.setVisible(False)
def appStartup(self):
"""
Perform tasks on application starup
"""
if len(self.manager.old_bible_databases):
if QtGui.QMessageBox.information(self.formparent,
translate('OpenLP', 'Information'), translate('OpenLP',
'Bible format has changed.\nYou have to upgrade your '
'existing Bibles.\nShould OpenLP upgrade now?'),
QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes |
QtGui.QMessageBox.No)) == QtGui.QMessageBox.Yes:
self.onToolsUpgradeItemTriggered()
def addImportMenuItem(self, import_menu):
self.importBibleItem = base_action(import_menu, u'importBibleItem')
self.importBibleItem.setText(translate('BiblesPlugin', '&Bible'))
@ -88,6 +104,39 @@ class BiblePlugin(Plugin):
export_menu.addAction(self.exportBibleItem)
self.exportBibleItem.setVisible(False)
def addToolsMenuItem(self, tools_menu):
"""
Give the bible plugin the opportunity to add items to the
**Tools** menu.
``tools_menu``
The actual **Tools** menu item, so that your actions can
use it as their parent.
"""
log.debug(u'add tools menu')
self.toolsUpgradeItem = QtGui.QAction(tools_menu)
self.toolsUpgradeItem.setObjectName(u'toolsUpgradeItem')
self.toolsUpgradeItem.setText(
translate('BiblePlugin', '&Upgrade older Bibles'))
self.toolsUpgradeItem.setStatusTip(
translate('BiblePlugin', 'Upgrade the Bible databases to the '
'latest format'))
tools_menu.addAction(self.toolsUpgradeItem)
QtCore.QObject.connect(self.toolsUpgradeItem,
QtCore.SIGNAL(u'triggered()'), self.onToolsUpgradeItemTriggered)
self.toolsUpgradeItem.setVisible(False)
def onToolsUpgradeItemTriggered(self):
"""
Upgrade older bible databases.
"""
if not hasattr(self, u'upgrade_wizard'):
self.upgrade_wizard = BibleUpgradeForm(self.formparent,
self.manager, self)
# If the import was not cancelled then reload.
if self.upgrade_wizard.exec_():
self.mediaItem.reloadBibles()
def onBibleImportClick(self):
if self.mediaItem:
self.mediaItem.onImportClick()
@ -149,4 +198,3 @@ class BiblePlugin(Plugin):
'Add the selected Bible to the service.')
}
self.setPluginUiTextStrings(tooltips)

View File

@ -51,7 +51,10 @@ This allows OpenLP to use ``self.object`` for all the GUI elements while keeping
them separate from the functionality, so that it is easier to recreate the GUI
from the .ui files later if necessary.
"""
from booknameform import BookNameForm
from languageform import LanguageForm
from bibleimportform import BibleImportForm
from bibleupgradeform import BibleUpgradeForm
__all__ = ['BibleImportForm']
__all__ = [u'BookNameForm', u'LanguageForm', u'BibleImportForm',
u'BibleUpgradeForm']

View File

@ -41,6 +41,7 @@ from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, string_is_unicode
from openlp.plugins.bibles.lib.manager import BibleFormat
from openlp.plugins.bibles.lib.db import BiblesResourcesDB, clean_filename
log = logging.getLogger(__name__)
@ -125,9 +126,6 @@ class BibleImportForm(OpenLPWizard):
QtCore.QObject.connect(self.osisBrowseButton,
QtCore.SIGNAL(u'clicked()'),
self.onOsisBrowseButtonClicked)
QtCore.QObject.connect(self.csvTestamentsButton,
QtCore.SIGNAL(u'clicked()'),
self.onCsvTestamentsBrowseButtonClicked)
QtCore.QObject.connect(self.csvBooksButton,
QtCore.SIGNAL(u'clicked()'),
self.onCsvBooksBrowseButtonClicked)
@ -188,18 +186,6 @@ class BibleImportForm(OpenLPWizard):
self.csvLayout = QtGui.QFormLayout(self.csvWidget)
self.csvLayout.setMargin(0)
self.csvLayout.setObjectName(u'CsvLayout')
self.csvTestamentsLabel = QtGui.QLabel(self.csvWidget)
self.csvTestamentsLabel.setObjectName(u'CsvTestamentsLabel')
self.csvTestamentsLayout = QtGui.QHBoxLayout()
self.csvTestamentsLayout.setObjectName(u'CsvTestamentsLayout')
self.csvTestamentsEdit = QtGui.QLineEdit(self.csvWidget)
self.csvTestamentsEdit.setObjectName(u'CsvTestamentsEdit')
self.csvTestamentsLayout.addWidget(self.csvTestamentsEdit)
self.csvTestamentsButton = QtGui.QToolButton(self.csvWidget)
self.csvTestamentsButton.setIcon(self.openIcon)
self.csvTestamentsButton.setObjectName(u'CsvTestamentsButton')
self.csvTestamentsLayout.addWidget(self.csvTestamentsButton)
self.csvLayout.addRow(self.csvTestamentsLabel, self.csvTestamentsLayout)
self.csvBooksLabel = QtGui.QLabel(self.csvWidget)
self.csvBooksLabel.setObjectName(u'CsvBooksLabel')
self.csvBooksLayout = QtGui.QHBoxLayout()
@ -384,8 +370,6 @@ class BibleImportForm(OpenLPWizard):
translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.osisFileLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Bible file:'))
self.csvTestamentsLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Testaments file:'))
self.csvBooksLabel.setText(
translate('BiblesPlugin.ImportWizardForm', 'Books file:'))
self.csvVersesLabel.setText(
@ -436,7 +420,6 @@ class BibleImportForm(OpenLPWizard):
# Align all QFormLayouts towards each other.
labelWidth = max(self.formatLabel.minimumSizeHint().width(),
self.osisFileLabel.minimumSizeHint().width(),
self.csvTestamentsLabel.minimumSizeHint().width(),
self.csvBooksLabel.minimumSizeHint().width(),
self.csvVersesLabel.minimumSizeHint().width(),
self.openSongFileLabel.minimumSizeHint().width(),
@ -458,14 +441,6 @@ class BibleImportForm(OpenLPWizard):
self.osisFileEdit.setFocus()
return False
elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV:
if not self.field(u'csv_testamentsfile').toString():
answer = critical_error_message_box(UiStrings().NFSs,
translate('BiblesPlugin.ImportWizardForm',
'You have not specified a testaments file. Do you '
'want to proceed with the import?'), question=True)
if answer == QtGui.QMessageBox.No:
self.csvTestamentsEdit.setFocus()
return False
if not self.field(u'csv_booksfile').toString():
critical_error_message_box(UiStrings().NFSs,
translate('BiblesPlugin.ImportWizardForm',
@ -498,6 +473,7 @@ class BibleImportForm(OpenLPWizard):
license_version = unicode(self.field(u'license_version').toString())
license_copyright = \
unicode(self.field(u'license_copyright').toString())
path = AppLocation.get_section_data_path(u'bibles')
if not license_version:
critical_error_message_box(UiStrings().EmptyField,
translate('BiblesPlugin.ImportWizardForm',
@ -519,6 +495,15 @@ class BibleImportForm(OpenLPWizard):
'a different Bible or first delete the existing one.'))
self.versionNameEdit.setFocus()
return False
elif os.path.exists(os.path.join(path, clean_filename(
license_version))):
critical_error_message_box(
translate('BiblesPlugin.ImportWizardForm', 'Bible Exists'),
translate('BiblesPlugin.ImportWizardForm',
'This Bible already exists. Please import '
'a different Bible or first delete the existing one.'))
self.versionNameEdit.setFocus()
return False
return True
if self.currentPage() == self.progressPage:
return True
@ -543,14 +528,6 @@ class BibleImportForm(OpenLPWizard):
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.OSIS,
self.osisFileEdit)
def onCsvTestamentsBrowseButtonClicked(self):
"""
Show the file open dialog for the testaments CSV file.
"""
self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.CSV,
self.csvTestamentsEdit, u'%s (*.csv)'
% translate('BiblesPlugin.ImportWizardForm', 'CSV File'))
def onCsvBooksBrowseButtonClicked(self):
"""
Show the file open dialog for the books CSV file.
@ -589,8 +566,6 @@ class BibleImportForm(OpenLPWizard):
"""
self.selectPage.registerField(u'source_format', self.formatComboBox)
self.selectPage.registerField(u'osis_location', self.osisFileEdit)
self.selectPage.registerField(
u'csv_testamentsfile', self.csvTestamentsEdit)
self.selectPage.registerField(u'csv_booksfile', self.csvBooksEdit)
self.selectPage.registerField(u'csv_versefile', self.csvVersesEdit)
self.selectPage.registerField(u'opensong_file', self.openSongFileEdit)
@ -619,7 +594,6 @@ class BibleImportForm(OpenLPWizard):
self.cancelButton.setVisible(True)
self.setField(u'source_format', QtCore.QVariant(0))
self.setField(u'osis_location', QtCore.QVariant(''))
self.setField(u'csv_testamentsfile', QtCore.QVariant(''))
self.setField(u'csv_booksfile', QtCore.QVariant(''))
self.setField(u'csv_versefile', QtCore.QVariant(''))
self.setField(u'opensong_file', QtCore.QVariant(''))
@ -646,46 +620,27 @@ class BibleImportForm(OpenLPWizard):
"""
Load the lists of Crosswalk, BibleGateway and Bibleserver bibles.
"""
filepath = AppLocation.get_directory(AppLocation.PluginsDir)
filepath = os.path.join(filepath, u'bibles', u'resources')
# Load Crosswalk Bibles.
self.loadBibleResourceFile(
os.path.join(filepath, u'crosswalkbooks.csv'),
WebDownload.Crosswalk)
self.loadBibleResource(WebDownload.Crosswalk)
# Load BibleGateway Bibles.
self.loadBibleResourceFile(os.path.join(filepath, u'biblegateway.csv'),
WebDownload.BibleGateway)
self.loadBibleResource(WebDownload.BibleGateway)
# Load and Bibleserver Bibles.
self.loadBibleResourceFile(os.path.join(filepath, u'bibleserver.csv'),
WebDownload.Bibleserver)
self.loadBibleResource(WebDownload.Bibleserver)
def loadBibleResourceFile(self, file_path_name, download_type):
def loadBibleResource(self, download_type):
"""
Loads a web bible resource file.
``file_path_name``
The file to load including the file's path.
Loads a web bible from bible_resources.sqlite.
``download_type``
The WebDownload type this file is for.
The WebDownload type e.g. bibleserver.
"""
self.web_bible_list[download_type] = {}
books_file = None
try:
books_file = open(file_path_name, 'rb')
dialect = csv.Sniffer().sniff(books_file.read(1024))
books_file.seek(0)
books_reader = csv.reader(books_file, dialect)
for line in books_reader:
ver = string_is_unicode(line[0])
name = string_is_unicode(line[1])
self.web_bible_list[download_type][ver] = name.strip()
except IOError:
log.exception(u'%s resources missing' %
bibles = BiblesResourcesDB.get_webbibles(
WebDownload.Names[download_type])
finally:
if books_file:
books_file.close()
for bible in bibles:
version = bible[u'name']
name = bible[u'abbreviation']
self.web_bible_list[download_type][version] = name.strip()
def preWizard(self):
"""
@ -720,8 +675,7 @@ class BibleImportForm(OpenLPWizard):
elif bible_type == BibleFormat.CSV:
# Import a CSV bible.
importer = self.manager.import_bible(BibleFormat.CSV,
name=license_version, testamentsfile=unicode(
self.field(u'csv_testamentsfile').toString()),
name=license_version,
booksfile=unicode(self.field(u'csv_booksfile').toString()),
versefile=unicode(self.field(u'csv_versefile').toString())
)
@ -752,7 +706,7 @@ class BibleImportForm(OpenLPWizard):
name=license_version,
filename=unicode(self.field(u'openlp1_location').toString())
)
if importer.do_import():
if importer.do_import(license_version):
self.manager.save_meta_data(license_version, license_version,
license_copyright, license_permissions)
self.manager.reload_bibles()

View File

@ -0,0 +1,786 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
The bible import functions for OpenLP
"""
import logging
import os.path
import re
import shutil
from PyQt4 import QtCore, QtGui
from openlp.core.lib import Receiver, SettingsManager, translate, \
check_directory_exists
from openlp.core.lib.db import delete_database
from openlp.core.lib.ui import UiStrings, critical_error_message_box
from openlp.core.ui.wizard import OpenLPWizard, WizardStrings
from openlp.core.utils import AppLocation, delete_file
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB,\
BiblesResourcesDB, clean_filename
from openlp.plugins.bibles.lib.http import BSExtract, BGExtract, CWExtract
log = logging.getLogger(__name__)
class BibleUpgradeForm(OpenLPWizard):
"""
This is the Bible Upgrade Wizard, which allows easy importing of Bibles
into OpenLP from older OpenLP2 database versions.
"""
log.info(u'BibleUpgradeForm loaded')
def __init__(self, parent, manager, bibleplugin):
"""
Instantiate the wizard, and run any extra setup we need to.
``parent``
The QWidget-derived parent of the wizard.
``manager``
The Bible manager.
``bibleplugin``
The Bible plugin.
"""
self.manager = manager
self.mediaItem = bibleplugin.mediaItem
self.suffix = u'.sqlite'
self.settingsSection = u'bibles'
self.path = AppLocation.get_section_data_path(
self.settingsSection)
self.files = self.manager.old_bible_databases
self.success = {}
self.newbibles = {}
OpenLPWizard.__init__(self, parent, bibleplugin, u'bibleUpgradeWizard',
u':/wizards/wizard_importbible.bmp')
def setupUi(self, image):
"""
Set up the UI for the bible wizard.
"""
OpenLPWizard.setupUi(self, image)
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
def stop_import(self):
"""
Stops the import of the Bible.
"""
log.debug(u'Stopping import')
self.stop_import_flag = True
def onCheckBoxIndexChanged(self, index):
"""
Show/Hide warnings if CheckBox state has changed
"""
for number, filename in enumerate(self.files):
if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
self.verticalWidget[number].hide()
self.formWidget[number].hide()
else:
version_name = unicode(self.versionNameEdit[number].text())
if self.manager.exists(version_name):
self.verticalWidget[number].show()
self.formWidget[number].show()
def reject(self):
"""
Stop the wizard on cancel button, close button or ESC key.
"""
log.debug(u'Wizard cancelled by user')
self.stop_import_flag = True
if not self.currentPage() == self.progressPage:
self.done(QtGui.QDialog.Rejected)
else:
self.postWizard()
def onCurrentIdChanged(self, pageId):
"""
Perform necessary functions depending on which wizard page is active.
"""
if self.page(pageId) == self.progressPage:
self.preWizard()
self.performWizard()
self.postWizard()
elif self.page(pageId) == self.selectPage and self.maxBibles == 0:
self.next()
def onBackupBrowseButtonClicked(self):
"""
Show the file open dialog for the OSIS file.
"""
filename = QtGui.QFileDialog.getExistingDirectory(self, translate(
'BiblesPlugin.UpgradeWizardForm', 'Select a Backup Directory'),
os.path.dirname(SettingsManager.get_last_dir(
self.plugin.settingsSection, 1)))
if filename:
self.backupDirectoryEdit.setText(filename)
SettingsManager.set_last_dir(self.plugin.settingsSection,
filename, 1)
def onNoBackupCheckBoxToggled(self, checked):
"""
Enable or disable the backup directory widgets.
"""
self.backupDirectoryEdit.setEnabled(not checked)
self.backupBrowseButton.setEnabled(not checked)
def backupOldBibles(self, backup_directory):
"""
Backup old bible databases in a given folder.
"""
check_directory_exists(backup_directory)
success = True
for filename in self.files:
try:
shutil.copy(os.path.join(self.path, filename[0]),
backup_directory)
except:
success = False
return success
def customInit(self):
"""
Perform any custom initialisation for bible upgrading.
"""
self.manager.set_process_dialog(self)
self.restart()
def customSignals(self):
"""
Set up the signals used in the bible importer.
"""
QtCore.QObject.connect(self.backupBrowseButton,
QtCore.SIGNAL(u'clicked()'), self.onBackupBrowseButtonClicked)
QtCore.QObject.connect(self.noBackupCheckBox,
QtCore.SIGNAL(u'toggled(bool)'), self.onNoBackupCheckBoxToggled)
def addCustomPages(self):
"""
Add the bible import specific wizard pages.
"""
# Backup Page
self.backupPage = QtGui.QWizardPage()
self.backupPage.setObjectName(u'BackupPage')
self.backupLayout = QtGui.QVBoxLayout(self.backupPage)
self.backupLayout.setObjectName(u'BackupLayout')
self.backupInfoLabel = QtGui.QLabel(self.backupPage)
self.backupInfoLabel.setOpenExternalLinks(True)
self.backupInfoLabel.setTextFormat(QtCore.Qt.RichText)
self.backupInfoLabel.setWordWrap(True)
self.backupInfoLabel.setObjectName(u'backupInfoLabel')
self.backupLayout.addWidget(self.backupInfoLabel)
self.selectLabel = QtGui.QLabel(self.backupPage)
self.selectLabel.setObjectName(u'selectLabel')
self.backupLayout.addWidget(self.selectLabel)
self.formLayout = QtGui.QFormLayout()
self.formLayout.setMargin(0)
self.formLayout.setObjectName(u'FormLayout')
self.backupDirectoryLabel = QtGui.QLabel(self.backupPage)
self.backupDirectoryLabel.setObjectName(u'backupDirectoryLabel')
self.backupDirectoryLayout = QtGui.QHBoxLayout()
self.backupDirectoryLayout.setObjectName(u'BackupDirectoryLayout')
self.backupDirectoryEdit = QtGui.QLineEdit(self.backupPage)
self.backupDirectoryEdit.setObjectName(u'BackupFolderEdit')
self.backupDirectoryLayout.addWidget(self.backupDirectoryEdit)
self.backupBrowseButton = QtGui.QToolButton(self.backupPage)
self.backupBrowseButton.setIcon(self.openIcon)
self.backupBrowseButton.setObjectName(u'BackupBrowseButton')
self.backupDirectoryLayout.addWidget(self.backupBrowseButton)
self.formLayout.addRow(self.backupDirectoryLabel,
self.backupDirectoryLayout)
self.backupLayout.addLayout(self.formLayout)
self.noBackupCheckBox = QtGui.QCheckBox(self.backupPage)
self.noBackupCheckBox.setObjectName('NoBackupCheckBox')
self.backupLayout.addWidget(self.noBackupCheckBox)
self.spacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Minimum)
self.backupLayout.addItem(self.spacer)
self.addPage(self.backupPage)
# Select Page
self.selectPage = QtGui.QWizardPage()
self.selectPage.setObjectName(u'SelectPage')
self.pageLayout = QtGui.QVBoxLayout(self.selectPage)
self.pageLayout.setObjectName(u'pageLayout')
self.scrollArea = QtGui.QScrollArea(self.selectPage)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName(u'scrollArea')
self.scrollArea.setHorizontalScrollBarPolicy(
QtCore.Qt.ScrollBarAlwaysOff)
self.scrollAreaContents = QtGui.QWidget(self.scrollArea)
self.scrollAreaContents.setObjectName(u'scrollAreaContents')
self.formLayout = QtGui.QVBoxLayout(self.scrollAreaContents)
self.formLayout.setSpacing(2)
self.formLayout.setObjectName(u'formLayout')
self.addScrollArea()
self.pageLayout.addWidget(self.scrollArea)
self.addPage(self.selectPage)
def addScrollArea(self):
"""
Add the content to the scrollArea.
"""
self.checkBox = {}
self.versionNameEdit = {}
self.versionNameLabel = {}
self.versionInfoLabel = {}
self.versionInfoPixmap = {}
self.verticalWidget = {}
self.horizontalLayout = {}
self.formWidget = {}
self.formLayoutAttention = {}
for number, filename in enumerate(self.files):
bible = OldBibleDB(self.mediaItem, path=self.path, file=filename[0])
self.checkBox[number] = QtGui.QCheckBox(self.scrollAreaContents)
checkBoxName = u'checkBox[%d]' % number
self.checkBox[number].setObjectName(checkBoxName)
self.checkBox[number].setText(bible.get_name())
self.checkBox[number].setCheckState(QtCore.Qt.Checked)
self.formLayout.addWidget(self.checkBox[number])
self.verticalWidget[number] = QtGui.QWidget(self.scrollAreaContents)
verticalWidgetName = u'verticalWidget[%d]' % number
self.verticalWidget[number].setObjectName(verticalWidgetName)
self.horizontalLayout[number] = QtGui.QHBoxLayout(
self.verticalWidget[number])
self.horizontalLayout[number].setContentsMargins(25, 0, 0, 0)
horizontalLayoutName = u'horizontalLayout[%d]' % number
self.horizontalLayout[number].setObjectName(horizontalLayoutName)
self.versionInfoPixmap[number] = QtGui.QLabel(
self.verticalWidget[number])
versionInfoPixmapName = u'versionInfoPixmap[%d]' % number
self.versionInfoPixmap[number].setObjectName(versionInfoPixmapName)
self.versionInfoPixmap[number].setPixmap(QtGui.QPixmap(
u':/bibles/bibles_upgrade_alert.png'))
self.versionInfoPixmap[number].setAlignment(QtCore.Qt.AlignRight)
self.horizontalLayout[number].addWidget(
self.versionInfoPixmap[number])
self.versionInfoLabel[number] = QtGui.QLabel(
self.verticalWidget[number])
versionInfoLabelName = u'versionInfoLabel[%d]' % number
self.versionInfoLabel[number].setObjectName(versionInfoLabelName)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(
self.versionInfoLabel[number].sizePolicy().hasHeightForWidth())
self.versionInfoLabel[number].setSizePolicy(sizePolicy)
self.horizontalLayout[number].addWidget(
self.versionInfoLabel[number])
self.formLayout.addWidget(self.verticalWidget[number])
self.formWidget[number] = QtGui.QWidget(self.scrollAreaContents)
formWidgetName = u'formWidget[%d]' % number
self.formWidget[number].setObjectName(formWidgetName)
self.formLayoutAttention[number] = QtGui.QFormLayout(
self.formWidget[number])
self.formLayoutAttention[number].setContentsMargins(25, 0, 0, 5)
formLayoutAttentionName = u'formLayoutAttention[%d]' % number
self.formLayoutAttention[number].setObjectName(
formLayoutAttentionName)
self.versionNameLabel[number] = QtGui.QLabel(
self.formWidget[number])
self.versionNameLabel[number].setObjectName(u'VersionNameLabel')
self.formLayoutAttention[number].setWidget(0,
QtGui.QFormLayout.LabelRole, self.versionNameLabel[number])
self.versionNameEdit[number] = QtGui.QLineEdit(
self.formWidget[number])
self.versionNameEdit[number].setObjectName(u'VersionNameEdit')
self.formLayoutAttention[number].setWidget(0,
QtGui.QFormLayout.FieldRole, self.versionNameEdit[number])
self.versionNameEdit[number].setText(bible.get_name())
self.formLayout.addWidget(self.formWidget[number])
# Set up the Signal for the checkbox.
QtCore.QObject.connect(self.checkBox[number],
QtCore.SIGNAL(u'stateChanged(int)'),
self.onCheckBoxIndexChanged)
self.spacerItem = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum,
QtGui.QSizePolicy.Expanding)
self.formLayout.addItem(self.spacerItem)
self.scrollArea.setWidget(self.scrollAreaContents)
def clearScrollArea(self):
"""
Remove the content from the scrollArea.
"""
for number, filename in enumerate(self.files):
self.formLayout.removeWidget(self.checkBox[number])
self.checkBox[number].setParent(None)
self.horizontalLayout[number].removeWidget(
self.versionInfoPixmap[number])
self.versionInfoPixmap[number].setParent(None)
self.horizontalLayout[number].removeWidget(
self.versionInfoLabel[number])
self.versionInfoLabel[number].setParent(None)
self.formLayout.removeWidget(self.verticalWidget[number])
self.verticalWidget[number].setParent(None)
self.formLayoutAttention[number].removeWidget(
self.versionNameLabel[number])
self.versionNameLabel[number].setParent(None)
self.formLayoutAttention[number].removeWidget(
self.versionNameEdit[number])
self.formLayoutAttention[number].deleteLater()
self.versionNameEdit[number].setParent(None)
self.formLayout.removeWidget(self.formWidget[number])
self.formWidget[number].setParent(None)
self.formLayout.removeItem(self.spacerItem)
def retranslateUi(self):
"""
Allow for localisation of the bible import wizard.
"""
self.setWindowTitle(translate('BiblesPlugin.UpgradeWizardForm',
'Bible Upgrade Wizard'))
self.titleLabel.setText(WizardStrings.HeaderStyle %
translate('OpenLP.Ui', 'Welcome to the Bible Upgrade Wizard'))
self.informationLabel.setText(
translate('BiblesPlugin.UpgradeWizardForm',
'This wizard will help you to upgrade your existing Bibles from a '
'prior version of OpenLP 2. Click the next button below to start '
'the upgrade process.'))
self.backupPage.setTitle(
translate('BiblesPlugin.UpgradeWizardForm',
'Select Backup Directory'))
self.backupPage.setSubTitle(
translate('BiblesPlugin.UpgradeWizardForm',
'Please select a backup directory for your Bibles'))
self.backupInfoLabel.setText(translate('BiblesPlugin.UpgradeWizardForm',
'Previous releases of OpenLP 2.0 are unable to use upgraded Bibles.'
' This will create a backup of your current Bibles so that you can '
'simply copy the files back to your OpenLP data directory if you '
'need to revert to a previous release of OpenLP. Instructions on '
'how to restore the files can be found in our <a href="'
'http://wiki.openlp.org/faq">Frequently Asked Questions</a>.'))
self.selectLabel.setText(translate('BiblesPlugin.UpgradeWizardForm',
'Please select a backup location for your Bibles.'))
self.backupDirectoryLabel.setText(
translate('BiblesPlugin.UpgradeWizardForm', 'Backup Directory:'))
self.noBackupCheckBox.setText(
translate('BiblesPlugin.UpgradeWizardForm',
'There is no need to backup my Bibles'))
self.selectPage.setTitle(
translate('BiblesPlugin.UpgradeWizardForm',
'Select Bibles'))
self.selectPage.setSubTitle(
translate('BiblesPlugin.UpgradeWizardForm',
'Please select the Bibles to upgrade'))
for number, bible in enumerate(self.files):
self.versionNameLabel[number].setText(
translate('BiblesPlugin.UpgradeWizardForm', 'Version name:'))
self.versionInfoLabel[number].setText(
translate('BiblesPlugin.UpgradeWizardForm', 'This '
'Bible still exists. Please change the name or uncheck it.'))
self.progressPage.setTitle(translate('BiblesPlugin.UpgradeWizardForm',
'Upgrading'))
self.progressPage.setSubTitle(
translate('BiblesPlugin.UpgradeWizardForm',
'Please wait while your Bibles are upgraded.'))
self.progressLabel.setText(WizardStrings.Ready)
self.progressBar.setFormat(u'%p%')
def validateCurrentPage(self):
"""
Validate the current page before moving on to the next page.
"""
if self.currentPage() == self.welcomePage:
return True
elif self.currentPage() == self.backupPage:
if not self.noBackupCheckBox.checkState() == QtCore.Qt.Checked:
backup_path = unicode(self.backupDirectoryEdit.text())
if not backup_path:
critical_error_message_box(UiStrings().EmptyField,
translate('BiblesPlugin.UpgradeWizardForm',
'You need to specify a Backup Directory for your '
'Bibles.'))
self.backupDirectoryEdit.setFocus()
return False
else:
if not self.backupOldBibles(backup_path):
critical_error_message_box(UiStrings().Error,
translate('BiblesPlugin.UpgradeWizardForm',
'The backup was not successful.\nTo backup your '
'Bibles you need permission to write to the given '
'directory. If you have write permissions and this '
'error still occurs, please report a bug.'))
return False
return True
elif self.currentPage() == self.selectPage:
for number, filename in enumerate(self.files):
if not self.checkBox[number].checkState() == QtCore.Qt.Checked:
continue
version_name = unicode(self.versionNameEdit[number].text())
if not version_name:
critical_error_message_box(UiStrings().EmptyField,
translate('BiblesPlugin.UpgradeWizardForm',
'You need to specify a version name for your Bible.'))
self.versionNameEdit[number].setFocus()
return False
elif self.manager.exists(version_name):
critical_error_message_box(
translate('BiblesPlugin.UpgradeWizardForm',
'Bible Exists'),
translate('BiblesPlugin.UpgradeWizardForm',
'This Bible already exists. Please upgrade '
'a different Bible, delete the existing one or '
'uncheck.'))
self.versionNameEdit[number].setFocus()
return False
elif os.path.exists(os.path.join(self.path, clean_filename(
version_name))) and version_name == filename[1]:
newfilename = u'old_database_%s' % filename[0]
if not os.path.exists(os.path.join(self.path,
newfilename)):
os.rename(os.path.join(self.path, filename[0]),
os.path.join(self.path, newfilename))
self.files[number] = [newfilename, filename[1]]
continue
else:
critical_error_message_box(
translate('BiblesPlugin.UpgradeWizardForm',
'Bible Exists'),
translate('BiblesPlugin.UpgradeWizardForm',
'This Bible already exists. Please upgrade '
'a different Bible, delete the existing one or '
'uncheck.'))
self.verticalWidget[number].show()
self.formWidget[number].show()
self.versionNameEdit[number].setFocus()
return False
elif os.path.exists(os.path.join(self.path,
clean_filename(version_name))):
critical_error_message_box(
translate('BiblesPlugin.UpgradeWizardForm',
'Bible Exists'),
translate('BiblesPlugin.UpgradeWizardForm',
'This Bible already exists. Please upgrade '
'a different Bible, delete the existing one or '
'uncheck.'))
self.versionNameEdit[number].setFocus()
return False
return True
if self.currentPage() == self.progressPage:
return True
def setDefaults(self):
"""
Set default values for the wizard pages.
"""
log.debug(u'BibleUpgrade setDefaults')
settings = QtCore.QSettings()
settings.beginGroup(self.plugin.settingsSection)
self.stop_import_flag = False
self.success.clear()
self.newbibles.clear()
self.clearScrollArea()
self.files = self.manager.old_bible_databases
self.addScrollArea()
self.retranslateUi()
self.maxBibles = len(self.files)
for number, filename in enumerate(self.files):
self.checkBox[number].setCheckState(QtCore.Qt.Checked)
oldname = filename[1]
if self.manager.exists(oldname):
self.verticalWidget[number].show()
self.formWidget[number].show()
else:
self.verticalWidget[number].hide()
self.formWidget[number].hide()
self.progressBar.show()
self.restart()
self.finishButton.setVisible(False)
self.cancelButton.setVisible(True)
settings.endGroup()
def preWizard(self):
"""
Prepare the UI for the upgrade.
"""
OpenLPWizard.preWizard(self)
self.progressLabel.setText(translate(
'BiblesPlugin.UpgradeWizardForm',
'Starting upgrading Bible(s)...'))
Receiver.send_message(u'openlp_process_events')
def performWizard(self):
"""
Perform the actual upgrade.
"""
self.include_webbible = False
proxy_server = None
if self.maxBibles == 0:
self.progressLabel.setText(
translate('BiblesPlugin.UpgradeWizardForm', 'There are no '
'Bibles available to upgrade.'))
self.progressBar.hide()
return
self.maxBibles = 0
for number, file in enumerate(self.files):
if self.checkBox[number].checkState() == QtCore.Qt.Checked:
self.maxBibles += 1
number = 0
for biblenumber, filename in enumerate(self.files):
if self.stop_import_flag:
bible_failed = True
break
bible_failed = False
self.success[biblenumber] = False
if not self.checkBox[biblenumber].checkState() == QtCore.Qt.Checked:
continue
self.progressBar.reset()
oldbible = OldBibleDB(self.mediaItem, path=self.path,
file=filename[0])
name = filename[1]
if name is None:
delete_file(os.path.join(self.path, filename[0]))
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\nFailed')) %
(number + 1, self.maxBibles, name),
self.progressBar.maximum() - self.progressBar.value())
number += 1
continue
self.progressLabel.setText(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\nUpgrading ...')) %
(number + 1, self.maxBibles, name))
if os.path.exists(os.path.join(self.path, filename[0])):
name = unicode(self.versionNameEdit[biblenumber].text())
self.newbibles[number] = BibleDB(self.mediaItem, path=self.path,
name=name)
self.newbibles[number].register(self.plugin.upgrade_wizard)
metadata = oldbible.get_metadata()
webbible = False
meta_data = {}
for meta in metadata:
meta_data[meta[u'key']] = meta[u'value']
if not meta[u'key'] == u'Version' and not meta[u'key'] == \
u'dbversion':
self.newbibles[number].create_meta(meta[u'key'],
meta[u'value'])
if meta[u'key'] == u'download source':
webbible = True
self.include_webbible = True
if meta.has_key(u'proxy server'):
proxy_server = meta[u'proxy server']
if webbible:
if meta_data[u'download source'].lower() == u'crosswalk':
handler = CWExtract(proxy_server)
elif meta_data[u'download source'].lower() == u'biblegateway':
handler = BGExtract(proxy_server)
elif meta_data[u'download source'].lower() == u'bibleserver':
handler = BSExtract(proxy_server)
books = handler.get_books_from_http(meta_data[u'download name'])
if not books:
log.error(u'Upgrading books from %s - download '\
u'name: "%s" failed' % (
meta_data[u'download source'],
meta_data[u'download name']))
delete_database(self.path, clean_filename(name))
del self.newbibles[number]
critical_error_message_box(
translate('BiblesPlugin.UpgradeWizardForm',
'Download Error'),
translate('BiblesPlugin.UpgradeWizardForm',
'To upgrade your Web Bibles an Internet connection is '
'required. If you have a working Internet connection '
'and this error still occurs, please report a bug.'))
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\nFailed')) %
(number + 1, self.maxBibles, name),
self.progressBar.maximum() - self.progressBar.value())
number += 1
continue
bible = BiblesResourcesDB.get_webbible(
meta_data[u'download name'],
meta_data[u'download source'].lower())
if bible and bible[u'language_id']:
language_id = bible[u'language_id']
self.newbibles[number].create_meta(u'language_id',
language_id)
else:
language_id = self.newbibles[number].get_language(name)
if not language_id:
log.warn(u'Upgrading from "%s" failed' % filename[0])
delete_database(self.path, clean_filename(name))
del self.newbibles[number]
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\nFailed')) %
(number + 1, self.maxBibles, name),
self.progressBar.maximum() - self.progressBar.value())
number += 1
continue
self.progressBar.setMaximum(len(books))
for book in books:
if self.stop_import_flag:
bible_failed = True
break
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\n'
'Upgrading %s ...')) %
(number + 1, self.maxBibles, name, book))
book_ref_id = self.newbibles[number].\
get_book_ref_id_by_name(book, len(books), language_id)
if not book_ref_id:
log.warn(u'Upgrading books from %s - download '\
u'name: "%s" aborted by user' % (
meta_data[u'download source'],
meta_data[u'download name']))
delete_database(self.path, clean_filename(name))
del self.newbibles[number]
bible_failed = True
break
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
db_book = self.newbibles[number].create_book(book,
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:
language_id = self.newbibles[number].get_object(BibleMeta,
u'language_id')
if not language_id:
language_id = self.newbibles[number].get_language(name)
if not language_id:
log.warn(u'Upgrading books from "%s" failed' % name)
delete_database(self.path, clean_filename(name))
del self.newbibles[number]
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\nFailed')) %
(number + 1, self.maxBibles, name),
self.progressBar.maximum() - self.progressBar.value())
number += 1
continue
books = oldbible.get_books()
self.progressBar.setMaximum(len(books))
for book in books:
if self.stop_import_flag:
bible_failed = True
break
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\n'
'Upgrading %s ...')) %
(number + 1, self.maxBibles, name, book[u'name']))
book_ref_id = self.newbibles[number].\
get_book_ref_id_by_name(book[u'name'], len(books),
language_id)
if not book_ref_id:
log.warn(u'Upgrading books from %s " '\
'failed - aborted by user' % name)
delete_database(self.path, clean_filename(name))
del self.newbibles[number]
bible_failed = True
break
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
db_book = self.newbibles[number].create_book(book[u'name'],
book_ref_id, book_details[u'testament_id'])
verses = oldbible.get_verses(book[u'id'])
if not verses:
log.warn(u'No verses found to import for book '
u'"%s"', book[u'name'])
self.newbibles[number].delete_book(db_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()
if not bible_failed:
self.newbibles[number].create_meta(u'Version', name)
oldbible.close_connection()
delete_file(os.path.join(self.path, filename[0]))
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\n'
'Done')) %
(number + 1, self.maxBibles, name))
self.success[biblenumber] = True
else:
self.incrementProgressBar(unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
'Upgrading Bible %s of %s: "%s"\nFailed')) %
(number + 1, self.maxBibles, name),
self.progressBar.maximum() - self.progressBar.value())
delete_database(self.path, clean_filename(name))
number += 1
def postWizard(self):
"""
Clean up the UI after the import has finished.
"""
successful_import = 0
failed_import = 0
for number, filename in enumerate(self.files):
if number in self.success and self.success[number] == True:
successful_import += 1
elif self.checkBox[number].checkState() == QtCore.Qt.Checked:
failed_import += 1
if failed_import > 0:
failed_import_text = unicode(translate(
'BiblesPlugin.UpgradeWizardForm',
', %s failed')) % failed_import
else:
failed_import_text = u''
if successful_import > 0:
if self.include_webbible:
self.progressLabel.setText(unicode(
translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading '
'Bible(s): %s successful%s\nPlease note, that verses from '
'Web Bibles will be downloaded\non demand and so an '
'Internet connection is required.')) %
(successful_import, failed_import_text))
else:
self.progressLabel.setText(unicode(
translate('BiblesPlugin.UpgradeWizardForm', 'Upgrading '
'Bible(s): %s successful%s')) % (successful_import,
failed_import_text))
else:
self.progressLabel.setText(
translate('BiblesPlugin.UpgradeWizardForm', 'Upgrade '
'failed.'))
OpenLPWizard.postWizard(self)

View File

@ -0,0 +1,114 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
class Ui_BookNameDialog(object):
def setupUi(self, bookNameDialog):
bookNameDialog.setObjectName(u'bookNameDialog')
bookNameDialog.resize(400, 271)
self.bookNameLayout = QtGui.QVBoxLayout(bookNameDialog)
self.bookNameLayout.setSpacing(8)
self.bookNameLayout.setMargin(8)
self.bookNameLayout.setObjectName(u'bookNameLayout')
self.infoLabel = QtGui.QLabel(bookNameDialog)
self.infoLabel.setWordWrap(True)
self.infoLabel.setObjectName(u'infoLabel')
self.bookNameLayout.addWidget(self.infoLabel)
self.correspondingLayout = QtGui.QGridLayout()
self.correspondingLayout.setColumnStretch(1, 1)
self.correspondingLayout.setSpacing(8)
self.correspondingLayout.setObjectName(u'correspondingLayout')
self.currentLabel = QtGui.QLabel(bookNameDialog)
self.currentLabel.setObjectName(u'currentLabel')
self.correspondingLayout.addWidget(self.currentLabel, 0, 0, 1, 1)
self.currentBookLabel = QtGui.QLabel(bookNameDialog)
self.currentBookLabel.setObjectName(u'currentBookLabel')
self.correspondingLayout.addWidget(self.currentBookLabel, 0, 1, 1, 1)
self.correspondingLabel = QtGui.QLabel(bookNameDialog)
self.correspondingLabel.setObjectName(u'correspondingLabel')
self.correspondingLayout.addWidget(
self.correspondingLabel, 1, 0, 1, 1)
self.correspondingComboBox = QtGui.QComboBox(bookNameDialog)
self.correspondingComboBox.setObjectName(u'correspondingComboBox')
self.correspondingLayout.addWidget(
self.correspondingComboBox, 1, 1, 1, 1)
self.bookNameLayout.addLayout(self.correspondingLayout)
self.optionsGroupBox = QtGui.QGroupBox(bookNameDialog)
self.optionsGroupBox.setObjectName(u'optionsGroupBox')
self.optionsLayout = QtGui.QVBoxLayout(self.optionsGroupBox)
self.optionsLayout.setSpacing(8)
self.optionsLayout.setMargin(8)
self.optionsLayout.setObjectName(u'optionsLayout')
self.oldTestamentCheckBox = QtGui.QCheckBox(self.optionsGroupBox)
self.oldTestamentCheckBox.setObjectName(u'oldTestamentCheckBox')
self.oldTestamentCheckBox.setCheckState(QtCore.Qt.Checked)
self.optionsLayout.addWidget(self.oldTestamentCheckBox)
self.newTestamentCheckBox = QtGui.QCheckBox(self.optionsGroupBox)
self.newTestamentCheckBox.setObjectName(u'newTestamentCheckBox')
self.newTestamentCheckBox.setCheckState(QtCore.Qt.Checked)
self.optionsLayout.addWidget(self.newTestamentCheckBox)
self.apocryphaCheckBox = QtGui.QCheckBox(self.optionsGroupBox)
self.apocryphaCheckBox.setObjectName(u'apocryphaCheckBox')
self.apocryphaCheckBox.setCheckState(QtCore.Qt.Checked)
self.optionsLayout.addWidget(self.apocryphaCheckBox)
self.bookNameLayout.addWidget(self.optionsGroupBox)
self.buttonBox = QtGui.QDialogButtonBox(bookNameDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(
QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(u'buttonBox')
self.bookNameLayout.addWidget(self.buttonBox)
self.retranslateUi(bookNameDialog)
QtCore.QObject.connect(
self.buttonBox, QtCore.SIGNAL(u'accepted()'),
bookNameDialog.accept)
QtCore.QObject.connect(
self.buttonBox, QtCore.SIGNAL(u'rejected()'),
bookNameDialog.reject)
QtCore.QMetaObject.connectSlotsByName(bookNameDialog)
def retranslateUi(self, bookNameDialog):
bookNameDialog.setWindowTitle(translate('BiblesPlugin.BookNameDialog',
'Select Book Name'))
self.infoLabel.setText(translate('BiblesPlugin.BookNameDialog',
'The following book name cannot be matched up internally. Please '
'select the corresponding English name from the list.'))
self.currentLabel.setText(translate('BiblesPlugin.BookNameDialog',
'Current name:'))
self.correspondingLabel.setText(translate(
'BiblesPlugin.BookNameDialog', 'Corresponding name:'))
self.optionsGroupBox.setTitle(translate('BiblesPlugin.BookNameDialog',
'Show Books From'))
self.oldTestamentCheckBox.setText(translate(
'BiblesPlugin.BookNameDialog', 'Old Testament'))
self.newTestamentCheckBox.setText(translate(
'BiblesPlugin.BookNameDialog', 'New Testament'))
self.apocryphaCheckBox.setText(translate('BiblesPlugin.BookNameDialog',
'Apocrypha'))

View File

@ -0,0 +1,123 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Module implementing BookNameForm.
"""
import logging
from PyQt4.QtGui import QDialog
from PyQt4 import QtCore
from openlp.core.lib import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.forms.booknamedialog import \
Ui_BookNameDialog
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
log = logging.getLogger(__name__)
class BookNameForm(QDialog, Ui_BookNameDialog):
"""
Class to manage a dialog which help the user to refer a book name a
to a english book name
"""
log.info(u'BookNameForm loaded')
def __init__(self, parent = None):
"""
Constructor
"""
QDialog.__init__(self, parent)
self.setupUi(self)
self.customSignals()
def customSignals(self):
"""
Set up the signals used in the booknameform.
"""
QtCore.QObject.connect(self.oldTestamentCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onCheckBoxIndexChanged)
QtCore.QObject.connect(self.newTestamentCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onCheckBoxIndexChanged)
QtCore.QObject.connect(self.apocryphaCheckBox,
QtCore.SIGNAL(u'stateChanged(int)'),
self.onCheckBoxIndexChanged)
def onCheckBoxIndexChanged(self, index):
"""
Reload Combobox if CheckBox state has changed
"""
self.reloadComboBox()
def reloadComboBox(self):
"""
Reload the Combobox items
"""
self.correspondingComboBox.clear()
items = BiblesResourcesDB.get_books()
for item in items:
addBook = True
for book in self.books:
if book.book_reference_id == item[u'id']:
addBook = False
break
if self.oldTestamentCheckBox.checkState() == QtCore.Qt.Unchecked \
and item[u'testament_id'] == 1:
addBook = False
elif self.newTestamentCheckBox.checkState() == QtCore.Qt.Unchecked \
and item[u'testament_id'] == 2:
addBook = False
elif self.apocryphaCheckBox.checkState() == QtCore.Qt.Unchecked \
and item[u'testament_id'] == 3:
addBook = False
if addBook:
self.correspondingComboBox.addItem(item[u'name'])
def exec_(self, name, books, maxbooks):
self.books = books
log.debug(maxbooks)
if maxbooks <= 27:
self.oldTestamentCheckBox.setCheckState(QtCore.Qt.Unchecked)
self.apocryphaCheckBox.setCheckState(QtCore.Qt.Unchecked)
elif maxbooks <= 66:
self.apocryphaCheckBox.setCheckState(QtCore.Qt.Unchecked)
self.reloadComboBox()
self.currentBookLabel.setText(unicode(name))
self.correspondingComboBox.setFocus()
return QDialog.exec_(self)
def accept(self):
if self.correspondingComboBox.currentText() == u'':
critical_error_message_box(
message=translate('BiblesPlugin.BookNameForm',
'You need to select a book.'))
self.correspondingComboBox.setFocus()
return False
else:
return QDialog.accept(self)

View File

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
class Ui_LanguageDialog(object):
def setupUi(self, languageDialog):
languageDialog.setObjectName(u'languageDialog')
languageDialog.resize(400, 165)
self.languageLayout = QtGui.QVBoxLayout(languageDialog)
self.languageLayout.setSpacing(8)
self.languageLayout.setMargin(8)
self.languageLayout.setObjectName(u'languageLayout')
self.bibleLabel = QtGui.QLabel(languageDialog)
self.bibleLabel.setObjectName(u'bibleLabel')
self.languageLayout.addWidget(self.bibleLabel)
self.infoLabel = QtGui.QLabel(languageDialog)
self.infoLabel.setWordWrap(True)
self.infoLabel.setObjectName(u'infoLabel')
self.languageLayout.addWidget(self.infoLabel)
self.languageHBoxLayout = QtGui.QHBoxLayout()
self.languageHBoxLayout.setSpacing(8)
self.languageHBoxLayout.setObjectName(u'languageHBoxLayout')
self.languageLabel = QtGui.QLabel(languageDialog)
self.languageLabel.setObjectName(u'languageLabel')
self.languageHBoxLayout.addWidget(self.languageLabel)
self.languageComboBox = QtGui.QComboBox(languageDialog)
sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding,
QtGui.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(
self.languageComboBox.sizePolicy().hasHeightForWidth())
self.languageComboBox.setSizePolicy(sizePolicy)
self.languageComboBox.setObjectName(u'languageComboBox')
self.languageHBoxLayout.addWidget(self.languageComboBox)
self.languageLayout.addLayout(self.languageHBoxLayout)
self.buttonBox = QtGui.QDialogButtonBox(languageDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|
QtGui.QDialogButtonBox.Ok)
self.buttonBox.setObjectName(u'buttonBox')
self.languageLayout.addWidget(self.buttonBox)
self.retranslateUi(languageDialog)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'),
languageDialog.accept)
QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'),
languageDialog.reject)
def retranslateUi(self, languageDialog):
languageDialog.setWindowTitle(
translate('BiblesPlugin.LanguageDialog', 'Select Language'))
self.bibleLabel.setText(translate('BiblesPlugin.LanguageDialog', ''))
self.infoLabel.setText(translate('BiblesPlugin.LanguageDialog',
'OpenLP is unable to determine the language of this translation '
'of the Bible. Please select the language from the list below.'))
self.languageLabel.setText(translate('BiblesPlugin.LanguageDialog',
'Language:'))

View File

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Meinert Jordan, Armin Köhler, Andreas Preikschat, #
# Christian Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon #
# Tibble, Carsten Tinggaard, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
"""
Module implementing LanguageForm.
"""
import logging
from PyQt4.QtGui import QDialog
from openlp.core.lib import translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.plugins.bibles.forms.languagedialog import \
Ui_LanguageDialog
from openlp.plugins.bibles.lib.db import BiblesResourcesDB
log = logging.getLogger(__name__)
class LanguageForm(QDialog, Ui_LanguageDialog):
"""
Class to manage a dialog which ask the user for a language.
"""
log.info(u'LanguageForm loaded')
def __init__(self, parent = None):
"""
Constructor
"""
QDialog.__init__(self, parent)
self.setupUi(self)
def exec_(self, bible_name):
self.languageComboBox.addItem(u'')
if bible_name:
self.bibleLabel.setText(unicode(bible_name))
items = BiblesResourcesDB.get_languages()
for item in items:
self.languageComboBox.addItem(item[u'name'])
return QDialog.exec_(self)
def accept(self):
if self.languageComboBox.currentText() == u'':
critical_error_message_box(
message=translate('BiblesPlugin.LanguageForm',
'You need to choose a language.'))
self.languageComboBox.setFocus()
return False
else:
return QDialog.accept(self)

View File

@ -71,7 +71,7 @@ import chardet
import csv
from openlp.core.lib import Receiver, translate
from openlp.plugins.bibles.lib.db import BibleDB, Testament
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
log = logging.getLogger(__name__)
@ -79,6 +79,8 @@ class CSVBible(BibleDB):
"""
This class provides a specialisation for importing of CSV Bibles.
"""
log.info(u'CSVBible loaded')
def __init__(self, parent, **kwargs):
"""
Loads a Bible from a set of CVS files.
@ -87,48 +89,10 @@ class CSVBible(BibleDB):
"""
log.info(self.__class__.__name__)
BibleDB.__init__(self, parent, **kwargs)
try:
self.testamentsfile = kwargs[u'testamentsfile']
except KeyError:
self.testamentsfile = None
self.booksfile = kwargs[u'booksfile']
self.versesfile = kwargs[u'versefile']
def setup_testaments(self):
"""
Overrides parent method so we can handle importing a testament file.
"""
if self.testamentsfile:
self.wizard.progressBar.setMinimum(0)
self.wizard.progressBar.setMaximum(2)
self.wizard.progressBar.setValue(0)
testaments_file = None
try:
details = get_file_encoding(self.testamentsfile)
testaments_file = open(self.testamentsfile, 'rb')
testaments_reader = csv.reader(testaments_file, delimiter=',',
quotechar='"')
for line in testaments_reader:
if self.stop_import_flag:
break
self.wizard.incrementProgressBar(unicode(
translate('BibleDB.Wizard',
'Importing testaments... %s')) %
unicode(line[1], details['encoding']), 0)
self.save_object(Testament.populate(
name=unicode(line[1], details['encoding'])))
Receiver.send_message(u'openlp_process_events')
except (IOError, IndexError):
log.exception(u'Loading testaments from file failed')
finally:
if testaments_file:
testaments_file.close()
self.wizard.incrementProgressBar(unicode(translate(
'BibleDB.Wizard', 'Importing testaments... done.')), 2)
else:
BibleDB.setup_testaments(self)
def do_import(self):
def do_import(self, bible_name=None):
"""
Import the bible books and verses.
"""
@ -136,6 +100,10 @@ class CSVBible(BibleDB):
self.wizard.progressBar.setMinimum(0)
self.wizard.progressBar.setMaximum(66)
success = True
language_id = self.get_language(bible_name)
if not language_id:
log.exception(u'Importing books from "%s" failed' % self.filename)
return False
books_file = None
book_list = {}
# Populate the Tables
@ -149,8 +117,15 @@ class CSVBible(BibleDB):
self.wizard.incrementProgressBar(unicode(
translate('BibleDB.Wizard', 'Importing books... %s')) %
unicode(line[2], details['encoding']))
book_ref_id = self.get_book_ref_id_by_name(
unicode(line[2], details['encoding']), 67, language_id)
if not book_ref_id:
log.exception(u'Importing books from "%s" '\
'failed' % self.booksfile)
return False
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
self.create_book(unicode(line[2], details['encoding']),
unicode(line[3], details['encoding']), int(line[1]))
book_ref_id, book_details[u'testament_id'])
book_list[int(line[0])] = unicode(line[2], details['encoding'])
Receiver.send_message(u'openlp_process_events')
except (IOError, IndexError):

View File

@ -27,16 +27,19 @@
import logging
import chardet
import os
import re
import sqlite3
from PyQt4 import QtCore
from sqlalchemy import Column, ForeignKey, or_, Table, types
from sqlalchemy.orm import class_mapper, mapper, relation
from sqlalchemy.orm.exc import UnmappedClassError
from openlp.core.lib import Receiver, translate
from openlp.core.lib import Receiver, translate, check_directory_exists
from openlp.core.lib.db import BaseModel, init_db, Manager
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation
log = logging.getLogger(__name__)
@ -47,13 +50,6 @@ class BibleMeta(BaseModel):
pass
class Testament(BaseModel):
"""
Bible Testaments
"""
pass
class Book(BaseModel):
"""
Song model
@ -67,6 +63,18 @@ class Verse(BaseModel):
"""
pass
def clean_filename(filename):
"""
Clean up the version name of the Bible and convert it into a valid
file name.
``filename``
The "dirty" file name or version name.
"""
if not isinstance(filename, unicode):
filename = unicode(filename, u'utf-8')
filename = re.sub(r'[^\w]+', u'_', filename).strip(u'_')
return filename + u'.sqlite'
def init_schema(url):
"""
@ -81,19 +89,17 @@ def init_schema(url):
Column(u'key', types.Unicode(255), primary_key=True, index=True),
Column(u'value', types.Unicode(255)),
)
testament_table = Table(u'testament', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'name', types.Unicode(50)),
)
book_table = Table(u'book', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'testament_id', types.Integer, ForeignKey(u'testament.id')),
Column(u'book_reference_id', types.Integer, index=True),
Column(u'testament_reference_id', types.Integer),
Column(u'name', types.Unicode(50), index=True),
Column(u'abbreviation', types.Unicode(5), index=True),
)
verse_table = Table(u'verse', metadata,
Column(u'id', types.Integer, primary_key=True, index=True),
Column(u'book_id', types.Integer, ForeignKey(u'book.id'), index=True),
Column(u'book_id', types.Integer, ForeignKey(
u'book.id'), index=True),
Column(u'chapter', types.Integer, index=True),
Column(u'verse', types.Integer, index=True),
Column(u'text', types.UnicodeText, index=True),
@ -103,11 +109,6 @@ def init_schema(url):
class_mapper(BibleMeta)
except UnmappedClassError:
mapper(BibleMeta, meta_table)
try:
class_mapper(Testament)
except UnmappedClassError:
mapper(Testament, testament_table,
properties={'books': relation(Book, backref='testament')})
try:
class_mapper(Book)
except UnmappedClassError:
@ -129,6 +130,7 @@ class BibleDB(QtCore.QObject, Manager):
methods, but benefit from the database methods in here via inheritance,
rather than depending on yet another object.
"""
log.info(u'BibleDB loaded')
def __init__(self, parent, **kwargs):
"""
@ -156,12 +158,14 @@ class BibleDB(QtCore.QObject, Manager):
self.name = kwargs[u'name']
if not isinstance(self.name, unicode):
self.name = unicode(self.name, u'utf-8')
self.file = self.clean_filename(self.name)
self.file = clean_filename(self.name)
if u'file' in kwargs:
self.file = kwargs[u'file']
Manager.__init__(self, u'bibles', init_schema, self.file)
if u'file' in kwargs:
self.get_name()
if u'path' in kwargs:
self.path = kwargs[u'path']
self.wizard = None
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import)
@ -181,19 +185,6 @@ class BibleDB(QtCore.QObject, Manager):
self.name = version_name.value if version_name else None
return self.name
def clean_filename(self, old_filename):
"""
Clean up the version name of the Bible and convert it into a valid
file name.
``old_filename``
The "dirty" file name or version name.
"""
if not isinstance(old_filename, unicode):
old_filename = unicode(old_filename, u'utf-8')
old_filename = re.sub(r'[^\w]+', u'_', old_filename).strip(u'_')
return old_filename + u'.sqlite'
def register(self, wizard):
"""
This method basically just initialialises the database. It is called
@ -206,36 +197,40 @@ class BibleDB(QtCore.QObject, Manager):
"""
self.wizard = wizard
self.create_meta(u'dbversion', u'2')
self.setup_testaments()
return self.name
def setup_testaments(self):
"""
Initialise the testaments section of a bible with suitable defaults.
"""
self.save_object(Testament.populate(name=u'Old Testament'))
self.save_object(Testament.populate(name=u'New Testament'))
self.save_object(Testament.populate(name=u'Apocrypha'))
def create_book(self, name, abbrev, testament=1):
def create_book(self, name, bk_ref_id, testament=1):
"""
Add a book to the database.
``name``
The name of the book.
``abbrev``
The abbreviation of the book.
``bk_ref_id``
The book_reference_id from bibles_resources.sqlite of the book.
``testament``
*Defaults to 1.* The id of the testament this book belongs to.
*Defaults to 1.* The testament_reference_id from
bibles_resources.sqlite of the testament this book belongs to.
"""
log.debug(u'create_book %s,%s', name, abbrev)
book = Book.populate(name=name, abbreviation=abbrev,
testament_id=testament)
log.debug(u'BibleDB.create_book("%s", "%s")', name, bk_ref_id)
book = Book.populate(name=name, book_reference_id=bk_ref_id,
testament_reference_id=testament)
self.save_object(book)
return book
def delete_book(self, db_book):
"""
Delete a book from the database.
``db_book``
The book object.
"""
log.debug(u'BibleDB.delete_book("%s")', db_book.name)
if self.delete_object(Book, db_book.id):
return True
return False
def create_chapter(self, book_id, chapter, textlist):
"""
Add a chapter and its verses to a book.
@ -250,7 +245,7 @@ class BibleDB(QtCore.QObject, Manager):
A dict of the verses to be inserted. The key is the verse number,
and the value is the verse text.
"""
log.debug(u'create_chapter %s,%s', book_id, chapter)
log.debug(u'BibleDBcreate_chapter("%s", "%s")', book_id, chapter)
# Text list has book and chapter as first two elements of the array.
for verse_number, verse_text in textlist.iteritems():
verse = Verse.populate(
@ -300,7 +295,9 @@ class BibleDB(QtCore.QObject, Manager):
``value``
The value for this instance.
"""
log.debug(u'save_meta %s/%s', key, value)
if not isinstance(value, unicode):
value = unicode(value)
log.debug(u'BibleDB.save_meta("%s/%s")', key, value)
self.save_object(BibleMeta.populate(key=key, value=value))
def get_book(self, book):
@ -310,20 +307,60 @@ class BibleDB(QtCore.QObject, Manager):
``book``
The name of the book to return.
"""
log.debug(u'BibleDb.get_book("%s")', book)
db_book = self.get_object_filtered(Book, Book.name.like(book + u'%'))
if db_book is None:
db_book = self.get_object_filtered(Book,
Book.abbreviation.like(book + u'%'))
return db_book
log.debug(u'BibleDB.get_book("%s")', book)
return self.get_object_filtered(Book, Book.name.like(book + u'%'))
def get_books(self):
"""
A wrapper so both local and web bibles have a get_books() method that
manager can call. Used in the media manager advanced search tab.
"""
log.debug(u'BibleDB.get_books()')
return self.get_all_objects(Book, order_by_ref=Book.id)
def get_book_by_book_ref_id(self, id):
"""
Return a book object from the database.
``id``
The reference id of the book to return.
"""
log.debug(u'BibleDB.get_book_by_book_ref_id("%s")', id)
return self.get_object_filtered(Book, Book.book_reference_id.like(id))
def get_book_ref_id_by_name(self, book, maxbooks, language_id=None):
log.debug(u'BibleDB.get_book_ref_id_by_name:("%s", "%s")', book,
language_id)
if BiblesResourcesDB.get_book(book, True):
book_temp = BiblesResourcesDB.get_book(book, True)
book_id = book_temp[u'id']
elif BiblesResourcesDB.get_alternative_book_name(book):
book_id = BiblesResourcesDB.get_alternative_book_name(book)
elif AlternativeBookNamesDB.get_book_reference_id(book):
book_id = AlternativeBookNamesDB.get_book_reference_id(book)
else:
from openlp.plugins.bibles.forms import BookNameForm
book_ref = None
book_name = BookNameForm(self.wizard)
if book_name.exec_(book, self.get_books(), maxbooks):
book_ref = unicode(
book_name.correspondingComboBox.currentText())
if not book_ref:
return None
else:
book_temp = BiblesResourcesDB.get_book(book_ref)
if book_temp:
book_id = book_temp[u'id']
else:
return None
if book_id:
AlternativeBookNamesDB.create_alternative_book_name(
book, book_id, language_id)
if book_id:
return book_id
else:
return None
def get_verses(self, reference_list, show_error=True):
"""
This is probably the most used function. It retrieves the list of
@ -333,24 +370,25 @@ class BibleDB(QtCore.QObject, Manager):
This is the list of references the media manager item wants. It is
a list of tuples, with the following format::
(book, chapter, start_verse, end_verse)
(book_reference_id, chapter, start_verse, end_verse)
Therefore, when you are looking for multiple items, simply break
them up into references like this, bundle them into a list. This
function then runs through the list, and returns an amalgamated
list of ``Verse`` objects. For example::
[(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)]
[(u'35', 1, 1, 1), (u'35', 2, 2, 3)]
"""
log.debug(u'BibleDB.get_verses: %s', reference_list)
log.debug(u'BibleDB.get_verses("%s")', reference_list)
verse_list = []
for book, chapter, start_verse, end_verse in reference_list:
db_book = self.get_book(book)
book_error = False
for book_id, chapter, start_verse, end_verse in reference_list:
db_book = self.get_book_by_book_ref_id(book_id)
if db_book:
book = db_book.name
log.debug(u'Book name corrected to "%s"', book)
book_id = db_book.book_reference_id
log.debug(u'Book name corrected to "%s"', db_book.name)
if end_verse == -1:
end_verse = self.get_verse_count(book, chapter)
end_verse = self.get_verse_count(book_id, chapter)
verses = self.session.query(Verse)\
.filter_by(book_id=db_book.id)\
.filter_by(chapter=chapter)\
@ -360,8 +398,9 @@ class BibleDB(QtCore.QObject, Manager):
.all()
verse_list.extend(verses)
else:
log.debug(u'OpenLP failed to find book %s', book)
if show_error:
log.debug(u'OpenLP failed to find book with id "%s"', book_id)
book_error = True
if book_error and show_error:
critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'),
translate('BiblesPlugin', 'No matching book '
@ -399,18 +438,18 @@ class BibleDB(QtCore.QObject, Manager):
Return the number of chapters in a book.
``book``
The book to get the chapter count for.
The book object to get the chapter count for.
"""
log.debug(u'BibleDB.get_chapter_count("%s")', book)
log.debug(u'BibleDB.get_chapter_count("%s")', book.name)
count = self.session.query(Verse.chapter).join(Book)\
.filter(Book.name == book)\
.filter(Book.book_reference_id==book.book_reference_id)\
.distinct().count()
if not count:
return 0
else:
return count
def get_verse_count(self, book, chapter):
def get_verse_count(self, book_id, chapter):
"""
Return the number of verses in a chapter.
@ -420,16 +459,49 @@ class BibleDB(QtCore.QObject, Manager):
``chapter``
The chapter to get the verse count for.
"""
log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter)
log.debug(u'BibleDB.get_verse_count("%s", "%s")', book_id, chapter)
count = self.session.query(Verse).join(Book)\
.filter(Book.name == book)\
.filter(Verse.chapter == chapter)\
.filter(Book.book_reference_id==book_id)\
.filter(Verse.chapter==chapter)\
.count()
if not count:
return 0
else:
return count
def get_language(self, bible_name=None):
"""
If no language is given it calls a dialog window where the user could
select the bible language.
Return the language id of a bible.
``book``
The language the bible is.
"""
log.debug(u'BibleDB.get_language()')
from openlp.plugins.bibles.forms import LanguageForm
language = None
language_form = LanguageForm(self.wizard)
if language_form.exec_(bible_name):
language = unicode(language_form.languageComboBox.currentText())
if not language:
return False
language = BiblesResourcesDB.get_language(language)
language_id = language[u'id']
self.create_meta(u'language_id', language_id)
return language_id
def is_old_database(self):
"""
Returns ``True`` if it is a bible database, which has been created
prior to 1.9.6.
"""
try:
columns = self.session.query(Book).all()
except:
return True
return False
def dump_bible(self):
"""
Utility debugging method to dump the contents of a bible.
@ -441,3 +513,595 @@ class BibleDB(QtCore.QObject, Manager):
log.debug(u'...............................Verses ')
verses = self.session.query(Verse).all()
log.debug(verses)
class BiblesResourcesDB(QtCore.QObject, Manager):
"""
This class represents the database-bound Bible Resources. It provide
some resources which are used in the Bibles plugin.
A wrapper class around a small SQLite database which contains the download
resources, a biblelist from the different download resources, the books,
chapter counts and verse counts for the web download Bibles, a language
reference, the testament reference and some alternative book names. This
class contains a singleton "cursor" so that only one connection to the
SQLite database is ever used.
"""
cursor = None
@staticmethod
def get_cursor():
"""
Return the cursor object. Instantiate one if it doesn't exist yet.
"""
if BiblesResourcesDB.cursor is None:
filepath = os.path.join(
AppLocation.get_directory(AppLocation.PluginsDir), u'bibles',
u'resources', u'bibles_resources.sqlite')
conn = sqlite3.connect(filepath)
BiblesResourcesDB.cursor = conn.cursor()
return BiblesResourcesDB.cursor
@staticmethod
def run_sql(query, parameters=()):
"""
Run an SQL query on the database, returning the results.
``query``
The actual SQL query to run.
``parameters``
Any variable parameters to add to the query.
"""
cursor = BiblesResourcesDB.get_cursor()
cursor.execute(query, parameters)
return cursor.fetchall()
@staticmethod
def get_books():
"""
Return a list of all the books of the Bible.
"""
log.debug(u'BiblesResourcesDB.get_books()')
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM book_reference ORDER BY id')
return [
{
u'id': book[0],
u'testament_id': book[1],
u'name': unicode(book[2]),
u'abbreviation': unicode(book[3]),
u'chapters': book[4]
}
for book in books
]
@staticmethod
def get_book(name, lower=False):
"""
Return a book by name or abbreviation.
``name``
The name or abbreviation of the book.
``lower``
True if the comparsion should be only lowercase
"""
log.debug(u'BiblesResourcesDB.get_book("%s")', name)
if not isinstance(name, unicode):
name = unicode(name)
if lower:
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM book_reference WHERE '
u'LOWER(name) = ? OR LOWER(abbreviation) = ?',
(name.lower(), name.lower()))
else:
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM book_reference WHERE name = ?'
u' OR abbreviation = ?', (name, name))
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]),
u'chapters': books[0][4]
}
else:
return None
@staticmethod
def get_book_by_id(id):
"""
Return a book by id.
``id``
The id of the book.
"""
log.debug(u'BiblesResourcesDB.get_book_by_id("%s")', id)
if not isinstance(id, int):
id = int(id)
books = BiblesResourcesDB.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM book_reference WHERE id = ?',
(id, ))
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]),
u'chapters': books[0][4]
}
else:
return None
@staticmethod
def get_chapter(book_id, chapter):
"""
Return the chapter details for a specific chapter of a book.
``book_id``
The id of a book.
``chapter``
The chapter number.
"""
log.debug(u'BiblesResourcesDB.get_chapter("%s", "%s")', book_id,
chapter)
if not isinstance(chapter, int):
chapter = int(chapter)
chapters = BiblesResourcesDB.run_sql(u'SELECT id, book_reference_id, '
u'chapter, verse_count FROM chapters WHERE book_reference_id = ?',
(book_id,))
if chapters:
return {
u'id': chapters[chapter-1][0],
u'book_reference_id': chapters[chapter-1][1],
u'chapter': chapters[chapter-1][2],
u'verse_count': chapters[chapter-1][3]
}
else:
return None
@staticmethod
def get_chapter_count(book_id):
"""
Return the number of chapters in a book.
``book_id``
The id of the book.
"""
log.debug(u'BiblesResourcesDB.get_chapter_count("%s")', book_id)
details = BiblesResourcesDB.get_book_by_id(book_id)
if details:
return details[u'chapters']
return 0
@staticmethod
def get_verse_count(book_id, chapter):
"""
Return the number of verses in a chapter.
``book``
The id of the book.
``chapter``
The number of the chapter.
"""
log.debug(u'BiblesResourcesDB.get_verse_count("%s", "%s")', book_id,
chapter)
details = BiblesResourcesDB.get_chapter(book_id, chapter)
if details:
return details[u'verse_count']
return 0
@staticmethod
def get_download_source(source):
"""
Return a download_source_id by source.
``name``
The name or abbreviation of the book.
"""
log.debug(u'BiblesResourcesDB.get_download_source("%s")', source)
if not isinstance(source, unicode):
source = unicode(source)
source = source.title()
dl_source = BiblesResourcesDB.run_sql(u'SELECT id, source FROM '
u'download_source WHERE source = ?', (source.lower(),))
if dl_source:
return {
u'id': dl_source[0][0],
u'source': dl_source[0][1]
}
else:
return None
@staticmethod
def get_webbibles(source):
"""
Return the bibles a webbible provide for download.
``source``
The source of the webbible.
"""
log.debug(u'BiblesResourcesDB.get_webbibles("%s")', source)
if not isinstance(source, unicode):
source = unicode(source)
source = BiblesResourcesDB.get_download_source(source)
bibles = BiblesResourcesDB.run_sql(u'SELECT id, name, abbreviation, '
u'language_id, download_source_id FROM webbibles WHERE '
u'download_source_id = ?', (source[u'id'],))
if bibles:
return [
{
u'id': bible[0],
u'name': bible[1],
u'abbreviation': bible[2],
u'language_id': bible[3],
u'download_source_id': bible[4]
}
for bible in bibles
]
else:
return None
@staticmethod
def get_webbible(abbreviation, source):
"""
Return the bibles a webbible provide for download.
``abbreviation``
The abbreviation of the webbible.
``source``
The source of the webbible.
"""
log.debug(u'BiblesResourcesDB.get_webbibles("%s", "%s")', abbreviation,
source)
if not isinstance(abbreviation, unicode):
abbreviation = unicode(abbreviation)
if not isinstance(source, unicode):
source = unicode(source)
source = BiblesResourcesDB.get_download_source(source)
bible = BiblesResourcesDB.run_sql(u'SELECT id, name, abbreviation, '
u'language_id, download_source_id FROM webbibles WHERE '
u'download_source_id = ? AND abbreviation = ?', (source[u'id'],
abbreviation))
if bible:
return {
u'id': bible[0][0],
u'name': bible[0][1],
u'abbreviation': bible[0][2],
u'language_id': bible[0][3],
u'download_source_id': bible[0][4]
}
else:
return None
@staticmethod
def get_alternative_book_name(name, language_id=None):
"""
Return a book_reference_id if the name matches.
``name``
The name to search the id.
``language_id``
The language_id for which language should be searched
"""
log.debug(u'BiblesResourcesDB.get_alternative_book_name("%s", "%s")',
name, language_id)
if language_id:
books = BiblesResourcesDB.run_sql(u'SELECT book_reference_id, name '
u'FROM alternative_book_names WHERE language_id = ? ORDER BY '
u'id', (language_id, ))
else:
books = BiblesResourcesDB.run_sql(u'SELECT book_reference_id, name '
u'FROM alternative_book_names ORDER BY id')
for book in books:
if book[1].lower() == name.lower():
return book[0]
return None
@staticmethod
def get_language(name):
"""
Return a dict containing the language id, name and code by name or
abbreviation.
``name``
The name or abbreviation of the language.
"""
log.debug(u'BiblesResourcesDB.get_language("%s")', name)
if not isinstance(name, unicode):
name = unicode(name)
language = BiblesResourcesDB.run_sql(u'SELECT id, name, code FROM '
u'language WHERE name = ? OR code = ?', (name, name.lower()))
if language:
return {
u'id': language[0][0],
u'name': unicode(language[0][1]),
u'code': unicode(language[0][2])
}
else:
return None
@staticmethod
def get_languages():
"""
Return a dict containing all languages with id, name and code.
"""
log.debug(u'BiblesResourcesDB.get_languages()')
languages = BiblesResourcesDB.run_sql(u'SELECT id, name, code FROM '
u'language ORDER by name')
if languages:
return [
{
u'id': language[0],
u'name': unicode(language[1]),
u'code': unicode(language[2])
}
for language in languages
]
else:
return None
@staticmethod
def get_testament_reference():
"""
Return a list of all testaments and their id of the Bible.
"""
log.debug(u'BiblesResourcesDB.get_testament_reference()')
testaments = BiblesResourcesDB.run_sql(u'SELECT id, name FROM '
u'testament_reference ORDER BY id')
return [
{
u'id': testament[0],
u'name': unicode(testament[1])
}
for testament in testaments
]
class AlternativeBookNamesDB(QtCore.QObject, Manager):
"""
This class represents a database-bound alternative book names system.
"""
cursor = None
conn = None
@staticmethod
def get_cursor():
"""
Return the cursor object. Instantiate one if it doesn't exist yet.
If necessary loads up the database and creates the tables if the
database doesn't exist.
"""
if AlternativeBookNamesDB.cursor is None:
filepath = os.path.join(
AppLocation.get_directory(AppLocation.DataDir), u'bibles',
u'alternative_book_names.sqlite')
if not os.path.exists(filepath):
#create new DB, create table alternative_book_names
AlternativeBookNamesDB.conn = sqlite3.connect(filepath)
AlternativeBookNamesDB.conn.execute(u'CREATE TABLE '
u'alternative_book_names(id INTEGER NOT NULL, '
u'book_reference_id INTEGER, language_id INTEGER, name '
u'VARCHAR(50), PRIMARY KEY (id))')
else:
#use existing DB
AlternativeBookNamesDB.conn = sqlite3.connect(filepath)
AlternativeBookNamesDB.cursor = AlternativeBookNamesDB.conn.cursor()
return AlternativeBookNamesDB.cursor
@staticmethod
def run_sql(query, parameters=(), commit=None):
"""
Run an SQL query on the database, returning the results.
``query``
The actual SQL query to run.
``parameters``
Any variable parameters to add to the query
``commit``
If a commit statement is necessary this should be True.
"""
cursor = AlternativeBookNamesDB.get_cursor()
cursor.execute(query, parameters)
if commit:
AlternativeBookNamesDB.conn.commit()
return cursor.fetchall()
@staticmethod
def get_book_reference_id(name, language_id=None):
"""
Return a book_reference_id if the name matches.
``name``
The name to search the id.
``language_id``
The language_id for which language should be searched
"""
log.debug(u'AlternativeBookNamesDB.get_book_reference_id("%s", "%s")',
name, language_id)
if language_id:
books = AlternativeBookNamesDB.run_sql(u'SELECT book_reference_id, '
u'name FROM alternative_book_names WHERE language_id = ?',
(language_id, ))
else:
books = AlternativeBookNamesDB.run_sql(u'SELECT book_reference_id, '
u'name FROM alternative_book_names')
for book in books:
if book[1].lower() == name.lower():
return book[0]
return None
@staticmethod
def create_alternative_book_name(name, book_reference_id, language_id):
"""
Add an alternative book name to the database.
``name``
The name of the alternative book name.
``book_reference_id``
The book_reference_id of the book.
``language_id``
The language to which the alternative book name belong.
"""
log.debug(u'AlternativeBookNamesDB.create_alternative_book_name("%s", '
'"%s", "%s"', name, book_reference_id, language_id)
return AlternativeBookNamesDB.run_sql(u'INSERT INTO '
u'alternative_book_names(book_reference_id, language_id, name) '
u'VALUES (?, ?, ?)', (book_reference_id, language_id, name), True)
class OldBibleDB(QtCore.QObject, Manager):
"""
This class conects to the old bible databases to reimport them to the new
database scheme.
"""
cursor = None
def __init__(self, parent, **kwargs):
"""
The constructor loads up the database and creates and initialises the
tables if the database doesn't exist.
**Required keyword arguments:**
``path``
The path to the bible database file.
``name``
The name of the database. This is also used as the file name for
SQLite databases.
"""
log.info(u'OldBibleDB loaded')
QtCore.QObject.__init__(self)
if u'path' not in kwargs:
raise KeyError(u'Missing keyword argument "path".')
if u'file' not in kwargs:
raise KeyError(u'Missing keyword argument "file".')
if u'path' in kwargs:
self.path = kwargs[u'path']
if u'file' in kwargs:
self.file = kwargs[u'file']
def get_cursor(self):
"""
Return the cursor object. Instantiate one if it doesn't exist yet.
"""
if self.cursor is None:
filepath = os.path.join(self.path, self.file)
self.connection = sqlite3.connect(filepath)
self.cursor = self.connection.cursor()
return self.cursor
def run_sql(self, query, parameters=()):
"""
Run an SQL query on the database, returning the results.
``query``
The actual SQL query to run.
``parameters``
Any variable parameters to add to the query.
"""
cursor = self.get_cursor()
cursor.execute(query, parameters)
return cursor.fetchall()
def get_name(self):
"""
Returns the version name of the Bible.
"""
version_name = self.run_sql(u'SELECT value FROM '
u'metadata WHERE key = "Version"')
if version_name:
self.name = version_name[0][0]
else:
self.name = None
return self.name
def get_metadata(self):
"""
Returns the metadata of the Bible.
"""
metadata = self.run_sql(u'SELECT key, value FROM metadata '
u'ORDER BY rowid')
if metadata:
return [
{
u'key': unicode(meta[0]),
u'value': unicode(meta[1])
}
for meta in metadata
]
else:
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):
"""
Returns the books of the Bible.
"""
books = self.run_sql(u'SELECT name, id FROM book ORDER BY id')
if books:
return [
{
u'name': unicode(book[0]),
u'id':int(book[1])
}
for book in books
]
else:
return None
def get_verses(self, book_id):
"""
Returns the verses of the Bible.
"""
verses = self.run_sql(u'SELECT book_id, chapter, verse, text FROM '
u'verse WHERE book_id = ? ORDER BY id', (book_id, ))
if verses:
return [
{
u'book_id': int(verse[0]),
u'chapter': int(verse[1]),
u'verse': int(verse[2]),
u'text': unicode(verse[3])
}
for verse in verses
]
else:
return None
def close_connection(self):
self.cursor.close()
self.connection.close()

View File

@ -42,161 +42,26 @@ from openlp.core.lib import Receiver, translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, get_web_page
from openlp.plugins.bibles.lib import SearchResults
from openlp.plugins.bibles.lib.db import BibleDB, Book
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB, \
Book
log = logging.getLogger(__name__)
class HTTPBooks(object):
"""
A wrapper class around a small SQLite database which contains the books,
chapter counts and verse counts for the web download Bibles. This class
contains a singleton "cursor" so that only one connection to the SQLite
database is ever used.
"""
cursor = None
@staticmethod
def get_cursor():
"""
Return the cursor object. Instantiate one if it doesn't exist yet.
"""
if HTTPBooks.cursor is None:
filepath = os.path.join(
AppLocation.get_directory(AppLocation.PluginsDir), u'bibles',
u'resources', u'httpbooks.sqlite')
conn = sqlite3.connect(filepath)
HTTPBooks.cursor = conn.cursor()
return HTTPBooks.cursor
@staticmethod
def run_sql(query, parameters=()):
"""
Run an SQL query on the database, returning the results.
``query``
The actual SQL query to run.
``parameters``
Any variable parameters to add to the query.
"""
cursor = HTTPBooks.get_cursor()
cursor.execute(query, parameters)
return cursor.fetchall()
@staticmethod
def get_books():
"""
Return a list of all the books of the Bible.
"""
books = HTTPBooks.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM books ORDER BY id')
book_list = []
for book in books:
book_list.append({
u'id': book[0],
u'testament_id': book[1],
u'name': unicode(book[2]),
u'abbreviation': unicode(book[3]),
u'chapters': book[4]
})
return book_list
@staticmethod
def get_book(name):
"""
Return a book by name or abbreviation.
``name``
The name or abbreviation of the book.
"""
if not isinstance(name, unicode):
name = unicode(name)
name = name.title()
books = HTTPBooks.run_sql(u'SELECT id, testament_id, name, '
u'abbreviation, chapters FROM books WHERE name = ? OR '
u'abbreviation = ?', (name, name))
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]),
u'chapters': books[0][4]
}
else:
return None
@staticmethod
def get_chapter(name, chapter):
"""
Return the chapter details for a specific chapter of a book.
``name``
The name or abbreviation of a book.
``chapter``
The chapter number.
"""
if not isinstance(name, int):
chapter = int(chapter)
book = HTTPBooks.get_book(name)
chapters = HTTPBooks.run_sql(u'SELECT id, book_id, chapter, '
u'verses FROM chapters WHERE book_id = ?', (book[u'id'],))
if chapters:
return {
u'id': chapters[chapter-1][0],
u'book_id': chapters[chapter-1][1],
u'chapter': chapters[chapter-1][2],
u'verses': chapters[chapter-1][3]
}
else:
return None
@staticmethod
def get_chapter_count(book):
"""
Return the number of chapters in a book.
``book``
The name or abbreviation of the book.
"""
details = HTTPBooks.get_book(book)
if details:
return details[u'chapters']
return 0
@staticmethod
def get_verse_count(book, chapter):
"""
Return the number of verses in a chapter.
``book``
The name or abbreviation of the book.
``chapter``
The number of the chapter.
"""
details = HTTPBooks.get_chapter(book, chapter)
if details:
return details[u'verses']
return 0
class BGExtract(object):
"""
Extract verses from BibleGateway
"""
def __init__(self, proxyurl=None):
log.debug(u'init %s', proxyurl)
log.debug(u'BGExtract.init("%s")', proxyurl)
self.proxyurl = proxyurl
socket.setdefaulttimeout(30)
def get_bible_chapter(self, version, bookname, chapter):
"""
Access and decode bibles via the BibleGateway website.
Access and decode Bibles via the BibleGateway website.
``version``
The version of the bible like 31 for New International version.
The version of the Bible like 31 for New International version.
``bookname``
Name of the Book.
@ -204,10 +69,11 @@ class BGExtract(object):
``chapter``
Chapter number.
"""
log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter)
url_params = urllib.urlencode(
{u'search': u'%s %s' % (bookname, chapter),
u'version': u'%s' % version})
log.debug(u'BGExtract.get_bible_chapter("%s", "%s", "%s")', version,
bookname, chapter)
urlbookname = urllib.quote(bookname.encode("utf-8"))
url_params = u'search=%s+%s&version=%s' % (urlbookname, chapter,
version)
cleaner = [(re.compile('&nbsp;|<br />|\'\+\''), lambda match: '')]
soup = get_soup_for_bible_ref(
u'http://www.biblegateway.com/passage/?%s' % url_params,
@ -230,7 +96,7 @@ class BGExtract(object):
verse_list = {}
# Cater for inconsistent mark up in the first verse of a chapter.
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])
for verse in verses(u'sup', u'versenum'):
raw_verse_num = verse.next
@ -243,7 +109,7 @@ class BGExtract(object):
try:
clean_verse_num = int(str(raw_verse_num))
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))
if clean_verse_num:
verse_text = raw_verse_num.next
@ -264,13 +130,60 @@ class BGExtract(object):
return None
return SearchResults(bookname, chapter, verse_list)
def get_books_from_http(self, version):
"""
Load a list of all books a Bible contaions from BibleGateway website.
``version``
The version of the Bible like NIV for New International Version
"""
log.debug(u'BGExtract.get_books_from_http("%s")', version)
url_params = urllib.urlencode(
{u'action': 'getVersionInfo', u'vid': u'%s' % version})
reference_url = u'http://www.biblegateway.com/versions/?%s#books' % \
url_params
page = get_web_page(reference_url)
if not page:
send_error_message(u'download')
return None
page_source = page.read()
page_source = unicode(page_source, 'utf8')
page_source_temp = re.search(u'<table .*?class="infotable".*?>.*?'\
u'</table>', page_source, re.DOTALL)
if page_source_temp:
soup = page_source_temp.group(0)
else:
soup = None
try:
soup = BeautifulSoup(soup)
except HTMLParseError:
log.error(u'BeautifulSoup could not parse the Bible page.')
send_error_message(u'parse')
return None
if not soup:
send_error_message(u'parse')
return None
Receiver.send_message(u'openlp_process_events')
content = soup.find(u'table', {u'class': u'infotable'})
content = content.findAll(u'tr')
if not content:
log.error(u'No books found in the Biblegateway response.')
send_error_message(u'parse')
return None
books = []
for book in content:
book = book.find(u'td')
if book:
books.append(book.contents[0])
return books
class BSExtract(object):
"""
Extract verses from Bibleserver.com
"""
def __init__(self, proxyurl=None):
log.debug(u'init %s', proxyurl)
log.debug(u'BSExtract.init("%s")', proxyurl)
self.proxyurl = proxyurl
socket.setdefaulttimeout(30)
@ -287,9 +200,12 @@ class BSExtract(object):
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter)
chapter_url = u'http://m.bibleserver.com/text/%s/%s%s' % \
(version, bookname, chapter)
log.debug(u'BSExtract.get_bible_chapter("%s", "%s", "%s")', version,
bookname, chapter)
urlversion = urllib.quote(version.encode("utf-8"))
urlbookname = urllib.quote(bookname.encode("utf-8"))
chapter_url = u'http://m.bibleserver.com/text/%s/%s%d' % \
(urlversion, urlbookname, chapter)
header = (u'Accept-Language', u'en')
soup = get_soup_for_bible_ref(chapter_url, header)
if not soup:
@ -297,7 +213,7 @@ class BSExtract(object):
Receiver.send_message(u'openlp_process_events')
content = soup.find(u'div', u'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')
return None
content = content.find(u'div').findAll(u'div')
@ -309,13 +225,38 @@ class BSExtract(object):
verses[versenumber] = verse.contents[1].rstrip(u'\n')
return SearchResults(bookname, chapter, verses)
def get_books_from_http(self, version):
"""
Load a list of all books a Bible contains from Bibleserver mobile
website.
``version``
The version of the Bible like NIV for New International 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?'\
'translation=%s' % (urlversion)
soup = get_soup_for_bible_ref(chapter_url)
if not soup:
return None
content = soup.find(u'ul')
if not content:
log.error(u'No books found in the Bibleserver response.')
send_error_message(u'parse')
return None
content = content.findAll(u'li')
return [
book.contents[0].contents[0] for book in content
]
class CWExtract(object):
"""
Extract verses from CrossWalk/BibleStudyTools
"""
def __init__(self, proxyurl=None):
log.debug(u'init %s', proxyurl)
log.debug(u'CWExtract.init("%s")', proxyurl)
self.proxyurl = proxyurl
socket.setdefaulttimeout(30)
@ -324,7 +265,7 @@ class CWExtract(object):
Access and decode bibles via the Crosswalk website
``version``
The version of the bible like niv for New International Version
The version of the Bible like niv for New International Version
``bookname``
Text name of in english e.g. 'gen' for Genesis
@ -332,17 +273,20 @@ class CWExtract(object):
``chapter``
Chapter number
"""
log.debug(u'get_bible_chapter %s,%s,%s', version, bookname, chapter)
log.debug(u'CWExtract.get_bible_chapter("%s", "%s", "%s")', version,
bookname, chapter)
urlbookname = bookname.replace(u' ', u'-')
urlbookname = urlbookname.lower()
urlbookname = urllib.quote(urlbookname.encode("utf-8"))
chapter_url = u'http://www.biblestudytools.com/%s/%s/%s.html' % \
(version, urlbookname.lower(), chapter)
(version, urlbookname, chapter)
soup = get_soup_for_bible_ref(chapter_url)
if not soup:
return None
Receiver.send_message(u'openlp_process_events')
htmlverses = soup.findAll(u'span', u'versetext')
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')
return None
verses = {}
@ -378,6 +322,32 @@ class CWExtract(object):
verses[versenumber] = versetext
return SearchResults(bookname, chapter, verses)
def get_books_from_http(self, version):
"""
Load a list of all books a Bible contain from the Crosswalk website.
``version``
The version of the bible like NIV for New International Version
"""
log.debug(u'CWExtract.get_books_from_http("%s")', version)
chapter_url = u'http://www.biblestudytools.com/%s/'\
% (version)
soup = get_soup_for_bible_ref(chapter_url)
if not soup:
return None
content = soup.find(u'div', {u'class': u'Body'})
content = content.find(u'ul', {u'class': u'parent'})
if not content:
log.error(u'No books found in the Crosswalk response.')
send_error_message(u'parse')
return None
content = content.findAll(u'li')
books = []
for book in content:
book = book.find(u'a')
books.append(book.contents[0])
return books
class HTTPBible(BibleDB):
log.info(u'%s HTTPBible loaded' , __name__)
@ -400,6 +370,8 @@ class HTTPBible(BibleDB):
self.proxy_server = None
self.proxy_username = None
self.proxy_password = None
if u'path' in kwargs:
self.path = kwargs[u'path']
if u'proxy_server' in kwargs:
self.proxy_server = kwargs[u'proxy_server']
if u'proxy_username' in kwargs:
@ -407,13 +379,15 @@ class HTTPBible(BibleDB):
if u'proxy_password' in kwargs:
self.proxy_password = kwargs[u'proxy_password']
def do_import(self):
def do_import(self, bible_name=None):
"""
Run the import. This method overrides the parent class method. Returns
``True`` on success, ``False`` on failure.
"""
self.wizard.progressBar.setMaximum(2)
self.wizard.incrementProgressBar('Registering bible...')
self.wizard.progressBar.setMaximum(68)
self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.HTTPBible',
'Registering Bible and loading books...')))
self.create_meta(u'download source', self.download_source)
self.create_meta(u'download name', self.download_name)
if self.proxy_server:
@ -424,6 +398,50 @@ class HTTPBible(BibleDB):
if self.proxy_password:
# Store the proxy password.
self.create_meta(u'proxy password', self.proxy_password)
if self.download_source.lower() == u'crosswalk':
handler = CWExtract(self.proxy_server)
elif self.download_source.lower() == u'biblegateway':
handler = BGExtract(self.proxy_server)
elif self.download_source.lower() == u'bibleserver':
handler = BSExtract(self.proxy_server)
books = handler.get_books_from_http(self.download_name)
if not books:
log.exception(u'Importing books from %s - download name: "%s" '\
'failed' % (self.download_source, self.download_name))
return False
self.wizard.progressBar.setMaximum(len(books)+2)
self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.HTTPBible', 'Registering Language...')))
bible = BiblesResourcesDB.get_webbible(self.download_name,
self.download_source.lower())
if bible[u'language_id']:
language_id = bible[u'language_id']
self.create_meta(u'language_id', language_id)
else:
language_id = self.get_language(bible_name)
if not language_id:
log.exception(u'Importing books from %s " '\
'failed' % self.filename)
return False
for book in books:
if self.stop_import_flag:
break
self.wizard.incrementProgressBar(unicode(translate(
'BiblesPlugin.HTTPBible', 'Importing %s...',
'Importing <book name>...')) % book)
book_ref_id = self.get_book_ref_id_by_name(book, len(books),
language_id)
if not book_ref_id:
log.exception(u'Importing books from %s - download name: "%s" '\
'failed' % (self.download_source, self.download_name))
return False
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
log.debug(u'Book details: Name:%s; id:%s; testament_id:%s',
book, book_ref_id, book_details[u'testament_id'])
self.create_book(book, book_ref_id, book_details[u'testament_id'])
if self.stop_import_flag:
return False
else:
return True
def get_verses(self, reference_list, show_error=True):
@ -438,22 +456,20 @@ class HTTPBible(BibleDB):
This is the list of references the media manager item wants. It is
a list of tuples, with the following format::
(book, chapter, start_verse, end_verse)
(book_reference_id, chapter, start_verse, end_verse)
Therefore, when you are looking for multiple items, simply break
them up into references like this, bundle them into a list. This
function then runs through the list, and returns an amalgamated
list of ``Verse`` objects. For example::
[(u'Genesis', 1, 1, 1), (u'Genesis', 2, 2, 3)]
[(u'35', 1, 1, 1), (u'35', 2, 2, 3)]
"""
log.debug(u'HTTPBible.get_verses("%s")', reference_list)
for reference in reference_list:
log.debug(u'Reference: %s', reference)
book = reference[0]
db_book = self.get_book(book)
book_id = reference[0]
db_book = self.get_book_by_book_ref_id(book_id)
if not db_book:
book_details = HTTPBooks.get_book(book)
if not book_details:
if show_error:
critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'),
@ -461,11 +477,8 @@ class HTTPBible(BibleDB):
'book could be found in this Bible. Check that you '
'have spelled the name of the book correctly.'))
return []
db_book = self.create_book(book_details[u'name'],
book_details[u'abbreviation'],
book_details[u'testament_id'])
book = db_book.name
if BibleDB.get_verse_count(self, book, reference[1]) == 0:
if BibleDB.get_verse_count(self, book_id, reference[1]) == 0:
Receiver.send_message(u'cursor_busy')
search_results = self.get_chapter(book, reference[1])
if search_results and search_results.has_verselist():
@ -488,7 +501,7 @@ class HTTPBible(BibleDB):
"""
Receive the request and call the relevant handler methods.
"""
log.debug(u'get_chapter %s, %s', book, chapter)
log.debug(u'HTTPBible.get_chapter("%s", "%s")', book, chapter)
log.debug(u'source = %s', self.download_source)
if self.download_source.lower() == u'crosswalk':
handler = CWExtract(self.proxy_server)
@ -502,16 +515,20 @@ class HTTPBible(BibleDB):
"""
Return the list of books.
"""
return [Book.populate(name=book['name'])
for book in HTTPBooks.get_books()]
log.debug(u'HTTPBible.get_books("%s")', Book.name)
return self.get_all_objects(Book, order_by_ref=Book.id)
def get_chapter_count(self, book):
"""
Return the number of chapters in a particular book.
"""
return HTTPBooks.get_chapter_count(book)
def get_verse_count(self, book, chapter):
``book``
The book object to get the chapter count for.
"""
log.debug(u'HTTPBible.get_chapter_count("%s")', book.name)
return BiblesResourcesDB.get_chapter_count(book.book_reference_id)
def get_verse_count(self, book_id, chapter):
"""
Return the number of verses for the specified chapter and book.
@ -521,7 +538,8 @@ class HTTPBible(BibleDB):
``chapter``
The chapter whose verses are being counted.
"""
return HTTPBooks.get_verse_count(book, chapter)
log.debug(u'HTTPBible.get_verse_count("%s", %s)', book_id, chapter)
return BiblesResourcesDB.get_verse_count(book_id, chapter)
def get_soup_for_bible_ref(reference_url, header=None, pre_parse_regex=None,
pre_parse_substitute=None, cleaner=None):

View File

@ -31,9 +31,10 @@ import os
from PyQt4 import QtCore
from openlp.core.lib import Receiver, SettingsManager, translate
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.utils import AppLocation, delete_file
from openlp.plugins.bibles.lib import parse_reference
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta
from openlp.plugins.bibles.lib.db import BibleDB, BibleMeta, OldBibleDB
from csvbible import CSVBible
from http import HTTPBible
from opensong import OpenSongBible
@ -140,8 +141,11 @@ class BibleManager(object):
"""
log.debug(u'Reload bibles')
files = SettingsManager.get_files(self.settingsSection, self.suffix)
if u'alternative_book_names.sqlite' in files:
files.remove(u'alternative_book_names.sqlite')
log.debug(u'Bible Files %s', files)
self.db_cache = {}
self.old_bible_databases = []
for filename in files:
bible = BibleDB(self.parent, path=self.path, file=filename)
name = bible.get_name()
@ -149,6 +153,11 @@ class BibleManager(object):
if name is None:
delete_file(os.path.join(self.path, filename))
continue
# Find old database versions
if bible.is_old_database():
self.old_bible_databases.append([filename, name])
bible.session.close()
continue
log.debug(u'Bible Name: "%s"', name)
self.db_cache[name] = bible
# Look to see if lazy load bible exists and get create getter.
@ -211,7 +220,8 @@ class BibleManager(object):
return [
{
u'name': book.name,
u'chapters': self.db_cache[bible].get_chapter_count(book.name)
u'book_reference_id': book.book_reference_id,
u'chapters': self.db_cache[bible].get_chapter_count(book)
}
for book in self.db_cache[bible].get_books()
]
@ -219,8 +229,15 @@ class BibleManager(object):
def get_chapter_count(self, bible, book):
"""
Returns the number of Chapters for a given book.
``bible``
Unicode. The Bible to get the list of books from.
``book``
The book object to get the chapter count for.
"""
log.debug(u'get_book_chapter_count %s', book)
log.debug(u'BibleManager.get_book_chapter_count ("%s", "%s")', bible,
book.name)
return self.db_cache[bible].get_chapter_count(book)
def get_verse_count(self, bible, book, chapter):
@ -230,9 +247,11 @@ class BibleManager(object):
"""
log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)',
bible, book, chapter)
return self.db_cache[bible].get_verse_count(book, chapter)
db_book = self.db_cache[bible].get_book(book)
book_ref_id = db_book.book_reference_id
return self.db_cache[bible].get_verse_count(book_ref_id, chapter)
def get_verses(self, bible, versetext, show_error=True):
def get_verses(self, bible, versetext, firstbible=False, show_error=True):
"""
Parses a scripture reference, fetches the verses from the Bible
specified, and returns a list of ``Verse`` objects.
@ -264,6 +283,28 @@ class BibleManager(object):
return None
reflist = parse_reference(versetext)
if reflist:
new_reflist = []
for item in reflist:
if item:
if firstbible:
db_book = self.db_cache[firstbible].get_book(item[0])
db_book = self.db_cache[bible].get_book_by_book_ref_id(
db_book.book_reference_id)
else:
db_book = self.db_cache[bible].get_book(item[0])
if db_book:
book_id = db_book.book_reference_id
log.debug(u'Book name corrected to "%s"', db_book.name)
new_reflist.append((book_id, item[1], item[2],
item[3]))
else:
log.debug(u'OpenLP failed to find book %s', item[0])
critical_error_message_box(
translate('BiblesPlugin', 'No Book Found'),
translate('BiblesPlugin', 'No matching book '
'could be found in this Bible. Check that you have '
'spelled the name of the book correctly.'))
reflist = new_reflist
return self.db_cache[bible].get_verses(reflist, show_error)
else:
if show_error:

View File

@ -61,7 +61,7 @@ class BibleMediaItem(MediaManagerItem):
self.unlockIcon = QtGui.QIcon(u':/bibles/bibles_search_unlock.png')
MediaManagerItem.__init__(self, parent, plugin, icon)
# Place to store the search results for both bibles.
self.settings = self.parent.settings_tab
self.settings = self.plugin.settings_tab
self.quickPreviewAllowed = True
self.hasSearch = True
self.search_results = {}
@ -239,8 +239,14 @@ class BibleMediaItem(MediaManagerItem):
self.advancedLayout.addWidget(self.advancedToVerse, 4, 2)
self.addSearchFields(u'advanced', UiStrings().Advanced)
# Combo Boxes
QtCore.QObject.connect(self.quickVersionComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onQuickVersionComboBox)
QtCore.QObject.connect(self.quickSecondComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onQuickSecondComboBox)
QtCore.QObject.connect(self.advancedVersionComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onAdvancedVersionComboBox)
QtCore.QObject.connect(self.advancedSecondComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onAdvancedSecondComboBox)
QtCore.QObject.connect(self.advancedBookComboBox,
QtCore.SIGNAL(u'activated(int)'), self.onAdvancedBookComboBox)
QtCore.QObject.connect(self.advancedFromChapter,
@ -338,7 +344,7 @@ class BibleMediaItem(MediaManagerItem):
def initialise(self):
log.debug(u'bible manager initialise')
self.parent.manager.media = self
self.plugin.manager.media = self
self.loadBibles()
bible = QtCore.QSettings().value(
self.settingsSection + u'/quick bible', QtCore.QVariant(
@ -365,7 +371,7 @@ class BibleMediaItem(MediaManagerItem):
self.quickSecondComboBox.addItem(u'')
self.advancedSecondComboBox.addItem(u'')
# Get all bibles and sort the list.
bibles = self.parent.manager.get_bibles().keys()
bibles = self.plugin.manager.get_bibles().keys()
bibles.sort(cmp=locale.strcoll)
# Load the bibles into the combo boxes.
for bible in bibles:
@ -386,7 +392,7 @@ class BibleMediaItem(MediaManagerItem):
def reloadBibles(self):
log.debug(u'Reloading Bibles')
self.parent.manager.reload_bibles()
self.plugin.manager.reload_bibles()
self.loadBibles()
def initialiseAdvancedBible(self, bible):
@ -400,7 +406,17 @@ class BibleMediaItem(MediaManagerItem):
The bible to initialise (unicode).
"""
log.debug(u'initialiseAdvancedBible %s', bible)
book_data = self.parent.manager.get_books(bible)
book_data = self.plugin.manager.get_books(bible)
secondbible = unicode(self.advancedSecondComboBox.currentText())
if secondbible != u'':
secondbook_data = self.plugin.manager.get_books(secondbible)
book_data_temp = []
for book in book_data:
for secondbook in secondbook_data:
if book['book_reference_id'] == \
secondbook['book_reference_id']:
book_data_temp.append(book)
book_data = book_data_temp
self.advancedBookComboBox.clear()
first = True
for book in book_data:
@ -416,7 +432,7 @@ class BibleMediaItem(MediaManagerItem):
def initialiseChapterVerse(self, bible, book, chapter_count):
log.debug(u'initialiseChapterVerse %s, %s', bible, book)
self.chapter_count = chapter_count
verse_count = self.parent.manager.get_verse_count(bible, book, 1)
verse_count = self.plugin.manager.get_verse_count(bible, book, 1)
if verse_count == 0:
self.advancedSearchButton.setEnabled(False)
critical_error_message_box(
@ -445,18 +461,34 @@ class BibleMediaItem(MediaManagerItem):
books = []
# We have to do a 'Reference Search'.
if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference:
bibles = self.parent.manager.get_bibles()
bibles = self.plugin.manager.get_bibles()
bible = unicode(self.quickVersionComboBox.currentText())
if bible:
book_data = bibles[bible].get_books()
secondbible = unicode(self.quickSecondComboBox.currentText())
if secondbible != u'':
secondbook_data = bibles[secondbible].get_books()
book_data_temp = []
for book in book_data:
for secondbook in secondbook_data:
if book.book_reference_id == \
secondbook.book_reference_id:
book_data_temp.append(book)
book_data = book_data_temp
books = [book.name + u' ' for book in book_data]
books.sort(cmp=locale.strcoll)
add_widget_completer(books, self.quickSearchEdit)
def onQuickVersionComboBox(self):
self.updateAutoCompleter()
def onQuickSecondComboBox(self):
self.updateAutoCompleter()
def onImportClick(self):
if not hasattr(self, u'import_wizard'):
self.import_wizard = BibleImportForm(self, self.parent.manager,
self.parent)
self.import_wizard = BibleImportForm(self, self.plugin.manager,
self.plugin)
# If the import was not cancelled then reload.
if self.import_wizard.exec_():
self.reloadBibles()
@ -501,6 +533,10 @@ class BibleMediaItem(MediaManagerItem):
self.initialiseAdvancedBible(
unicode(self.advancedVersionComboBox.currentText()))
def onAdvancedSecondComboBox(self):
self.initialiseAdvancedBible(
unicode(self.advancedVersionComboBox.currentText()))
def onAdvancedBookComboBox(self):
item = int(self.advancedBookComboBox.currentIndex())
self.initialiseChapterVerse(
@ -515,7 +551,7 @@ class BibleMediaItem(MediaManagerItem):
bible = unicode(self.advancedVersionComboBox.currentText())
book = unicode(self.advancedBookComboBox.currentText())
verse_from = int(self.advancedFromVerse.currentText())
verse_count = self.parent.manager.get_verse_count(bible, book,
verse_count = self.plugin.manager.get_verse_count(bible, book,
chapter_to)
self.adjustComboBox(verse_from, verse_count,
self.advancedToVerse, True)
@ -527,7 +563,7 @@ class BibleMediaItem(MediaManagerItem):
chapter_to = int(self.advancedToChapter.currentText())
verse_from = int(self.advancedFromVerse.currentText())
verse_to = int(self.advancedToVerse.currentText())
verse_count = self.parent.manager.get_verse_count(bible, book,
verse_count = self.plugin.manager.get_verse_count(bible, book,
chapter_to)
if chapter_from == chapter_to and verse_from > verse_to:
self.adjustComboBox(verse_from, verse_count, self.advancedToVerse)
@ -539,7 +575,7 @@ class BibleMediaItem(MediaManagerItem):
book = unicode(self.advancedBookComboBox.currentText())
chapter_from = int(self.advancedFromChapter.currentText())
chapter_to = int(self.advancedToChapter.currentText())
verse_count = self.parent.manager.get_verse_count(bible, book,
verse_count = self.plugin.manager.get_verse_count(bible, book,
chapter_from)
self.adjustComboBox(1, verse_count, self.advancedFromVerse)
if chapter_from > chapter_to:
@ -599,10 +635,10 @@ class BibleMediaItem(MediaManagerItem):
range_separator + chapter_to + verse_separator + verse_to
versetext = u'%s %s' % (book, verse_range)
Receiver.send_message(u'cursor_busy')
self.search_results = self.parent.manager.get_verses(bible, versetext)
self.search_results = self.plugin.manager.get_verses(bible, versetext)
if second_bible:
self.second_search_results = self.parent.manager.get_verses(
second_bible, versetext)
self.second_search_results = self.plugin.manager.get_verses(
second_bible, versetext, bible)
if not self.advancedLockButton.isChecked():
self.listView.clear()
if self.listView.count() != 0:
@ -627,21 +663,44 @@ class BibleMediaItem(MediaManagerItem):
text = unicode(self.quickSearchEdit.text())
if self.quickSearchEdit.currentSearchType() == BibleSearch.Reference:
# We are doing a 'Reference Search'.
self.search_results = self.parent.manager.get_verses(bible, text)
self.search_results = self.plugin.manager.get_verses(bible, text)
if second_bible and self.search_results:
self.second_search_results = self.parent.manager.get_verses(
second_bible, text)
self.second_search_results = self.plugin.manager.get_verses(
second_bible, text, bible)
else:
# We are doing a 'Text Search'.
Receiver.send_message(u'cursor_busy')
bibles = self.parent.manager.get_bibles()
self.search_results = self.parent.manager.verse_search(bible,
bibles = self.plugin.manager.get_bibles()
self.search_results = self.plugin.manager.verse_search(bible,
second_bible, text)
if second_bible and self.search_results:
text = []
new_search_results = []
count = 0
passage_not_found = False
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.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 = \
bibles[second_bible].get_verses(text)
if not self.quickLockButton.isChecked():
@ -674,19 +733,19 @@ class BibleMediaItem(MediaManagerItem):
further action is saved for/in each row.
"""
verse_separator = get_reference_match(u'sep_v_display')
version = self.parent.manager.get_meta_data(bible, u'Version').value
copyright = self.parent.manager.get_meta_data(bible, u'Copyright').value
version = self.plugin.manager.get_meta_data(bible, u'Version').value
copyright = self.plugin.manager.get_meta_data(bible, u'Copyright').value
permissions = \
self.parent.manager.get_meta_data(bible, u'Permissions').value
self.plugin.manager.get_meta_data(bible, u'Permissions').value
second_version = u''
second_copyright = u''
second_permissions = u''
if second_bible:
second_version = self.parent.manager.get_meta_data(
second_version = self.plugin.manager.get_meta_data(
second_bible, u'Version').value
second_copyright = self.parent.manager.get_meta_data(
second_copyright = self.plugin.manager.get_meta_data(
second_bible, u'Copyright').value
second_permissions = self.parent.manager.get_meta_data(
second_permissions = self.plugin.manager.get_meta_data(
second_bible, u'Permissions').value
items = []
for count, verse in enumerate(search_results):
@ -713,7 +772,7 @@ class BibleMediaItem(MediaManagerItem):
log.exception(u'The second_search_results does not have as '
'many verses as the search_results.')
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,
second_version)
else:
@ -771,7 +830,7 @@ class BibleMediaItem(MediaManagerItem):
bible_text = u''
# If we are 'Verse Per Line' then force a new line.
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'.
else:
bible_text = u'%s %s&nbsp;%s\n' % (bible_text, verse_text, text)
@ -809,7 +868,8 @@ class BibleMediaItem(MediaManagerItem):
service_item.theme = None
else:
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
def formatTitle(self, start_bitem, old_bitem):
@ -879,7 +939,7 @@ class BibleMediaItem(MediaManagerItem):
# We are still in the same chapter, but a verse has been skipped.
return True
elif old_chapter + 1 == chapter and (verse != 1 or
old_verse != self.parent.manager.get_verse_count(
old_verse != self.plugin.manager.get_verse_count(
old_bible, old_book, old_chapter)):
# We are in the following chapter, but the last verse was not the
# last verse of the chapter or the current verse is not the
@ -923,7 +983,7 @@ class BibleMediaItem(MediaManagerItem):
Search for some Bible verses (by reference).
"""
bible = unicode(self.quickVersionComboBox.currentText())
search_results = self.parent.manager.get_verses(bible, string, False)
search_results = self.plugin.manager.get_verses(bible, string, False, False)
results = []
if search_results:
versetext = u' '.join([verse.text for verse in search_results])
@ -933,6 +993,6 @@ class BibleMediaItem(MediaManagerItem):
def createItemFromId(self, item_id):
item = QtGui.QListWidgetItem()
bible = unicode(self.quickVersionComboBox.currentText())
search_results = self.parent.manager.get_verses(bible, item_id, False)
search_results = self.plugin.manager.get_verses(bible, item_id, False)
items = self.buildDisplayResults(bible, u'', search_results)
return items

View File

@ -30,7 +30,7 @@ import sqlite
from openlp.core.lib import Receiver
from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.bibles.lib.db import BibleDB
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
log = logging.getLogger(__name__)
@ -46,7 +46,7 @@ class OpenLP1Bible(BibleDB):
BibleDB.__init__(self, parent, **kwargs)
self.filename = kwargs[u'filename']
def do_import(self):
def do_import(self, bible_name=None):
"""
Imports an openlp.org v1 bible.
"""
@ -57,6 +57,11 @@ class OpenLP1Bible(BibleDB):
cursor = connection.cursor()
except:
return False
#Create the bible language
language_id = self.get_language(bible_name)
if not language_id:
log.exception(u'Importing books from "%s" failed' % self.filename)
return False
# Create all books.
cursor.execute(u'SELECT id, testament_id, name, abbreviation FROM book')
books = cursor.fetchall()
@ -69,7 +74,15 @@ class OpenLP1Bible(BibleDB):
testament_id = int(book[1])
name = unicode(book[2], u'cp1252')
abbreviation = unicode(book[3], u'cp1252')
self.create_book(name, abbreviation, testament_id)
book_ref_id = self.get_book_ref_id_by_name(name, len(books),
language_id)
if not book_ref_id:
log.exception(u'Importing books from "%s" '\
'failed' % self.filename)
return False
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
db_book = self.create_book(name, book_ref_id,
book_details[u'testament_id'])
# Update the progess bar.
self.wizard.incrementProgressBar(WizardStrings.ImportingType % name)
# Import the verses for this book.
@ -83,7 +96,7 @@ class OpenLP1Bible(BibleDB):
chapter = int(verse[0])
verse_number = int(verse[1])
text = unicode(verse[2], u'cp1252')
self.create_verse(book_id, chapter, verse_number, text)
self.create_verse(db_book.id, chapter, verse_number, text)
Receiver.send_message(u'openlp_process_events')
self.session.commit()
connection.close()

View File

@ -29,7 +29,7 @@ import logging
from lxml import objectify
from openlp.core.lib import Receiver, translate
from openlp.plugins.bibles.lib.db import BibleDB
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
log = logging.getLogger(__name__)
@ -46,7 +46,7 @@ class OpenSongBible(BibleDB):
BibleDB.__init__(self, parent, **kwargs)
self.filename = kwargs['filename']
def do_import(self):
def do_import(self, bible_name=None):
"""
Loads a Bible from file.
"""
@ -62,11 +62,23 @@ class OpenSongBible(BibleDB):
file = open(self.filename, u'r')
opensong = objectify.parse(file)
bible = opensong.getroot()
language_id = self.get_language(bible_name)
if not language_id:
log.exception(u'Importing books from "%s" '\
'failed' % self.filename)
return False
for book in bible.b:
if self.stop_import_flag:
break
book_ref_id = self.get_book_ref_id_by_name(
unicode(book.attrib[u'n']), len(bible.b), language_id)
if not book_ref_id:
log.exception(u'Importing books from "%s" '\
'failed' % self.filename)
return False
book_details = BiblesResourcesDB.get_book_by_id(book_ref_id)
db_book = self.create_book(unicode(book.attrib[u'n']),
unicode(book.attrib[u'n'][:4]))
book_ref_id, book_details[u'testament_id'])
for chapter in book.c:
if self.stop_import_flag:
break

View File

@ -34,7 +34,7 @@ import re
from openlp.core.lib import Receiver, translate
from openlp.core.utils import AppLocation
from openlp.plugins.bibles.lib.db import BibleDB
from openlp.plugins.bibles.lib.db import BibleDB, BiblesResourcesDB
log = logging.getLogger(__name__)
@ -86,7 +86,7 @@ class OSISBible(BibleDB):
if fbibles:
fbibles.close()
def do_import(self):
def do_import(self, bible_name=None):
"""
Loads a Bible from file.
"""
@ -96,7 +96,6 @@ class OSISBible(BibleDB):
osis = None
success = True
last_chapter = 0
testament = 1
match_count = 0
self.wizard.incrementProgressBar(translate('BiblesPlugin.OsisImport',
'Detecting encoding (this may take a few minutes)...'))
@ -109,6 +108,11 @@ class OSISBible(BibleDB):
finally:
if detect_file:
detect_file.close()
# Set meta language_id
language_id = self.get_language(bible_name)
if not language_id:
log.exception(u'Importing books from "%s" failed' % self.filename)
return False
try:
osis = codecs.open(self.filename, u'r', details['encoding'])
repl = replacement
@ -123,13 +127,19 @@ class OSISBible(BibleDB):
verse = int(match.group(3))
verse_text = match.group(4)
if not db_book or db_book.name != self.books[book][0]:
log.debug(u'New book: "%s"', self.books[book][0])
if book == u'Matt' or book == u'Jdt':
testament += 1
log.debug(u'New book: "%s"' % self.books[book][0])
book_ref_id = self.get_book_ref_id_by_name(unicode(
self.books[book][0]), 67, language_id)
if not book_ref_id:
log.exception(u'Importing books from "%s" '\
'failed' % self.filename)
return False
book_details = BiblesResourcesDB.get_book_by_id(
book_ref_id)
db_book = self.create_book(
unicode(self.books[book][0]),
unicode(self.books[book][1]),
testament)
book_ref_id,
book_details[u'testament_id'])
if last_chapter == 0:
if book == u'Gen':
self.wizard.progressBar.setMaximum(1188)

View File

@ -1,81 +0,0 @@
João Ferreira de Almeida Atualizada,AA
التفسير التطبيقى للكتاب المقدس,ALAB
Shqip,ALB
Amplified Bible,AMP
Amuzgo de Guerrero,AMU
American Standard Version,ASV
La Bible du Semeur,BDS
Български 1940,BG1940
Български,BULG
Chinanteco de Comaltepec,CCO
Contemporary English Version,CEV
Cakchiquel Occidental,CKW
Hrvatski,CRO
Castilian,CST
聖經和合本 (简体中文),CUVS
聖經和合本 (繁体中文),CUV
Darby Translation,DARBY
Dette er Biblen på dansk,DN1933
Det Norsk Bibelselskap 1930,DNB1930
English Standard Version,ESV
GODS WORD Translation,GW
Holman Christian Standard Bible,HCSB
Kreyòl ayisyen bib,HCV
Hiligaynon Bible,HLGN
Hoffnung für Alle,HOF
Het Boek,HTB
Icelandic Bible,ICELAND
Jacalteco Oriental,JAC
Károlyi-biblia,KAR
Kekchi,KEK
21st Century King James Version,KJ21
King James Version,KJV
La Biblia de las Américas,LBLA
Levande Bibeln,LB
La Parola è Vita,LM
La Nuova Diodati,LND
Louis Segond,LSG
Luther Bibel 1545,LUTH1545
Māori Bible,MAORI
Македонски Новиот Завет,MNT
The Message,MSG
Mam de Comitancillo Central,MVC
Mam de Todos Santos Cuchumatán,MVJ
New American Standard Bible,NASB
New Century Version,NCV
Náhuatl de Guerrero,NGU
New International Reader's Version,NIRV
New International Version 1984,NIV1984
New International Version 2010,NIV
New International Version - UK,NIVUK
New King James Version,NKJV
New Living Translation,NLT
Nádej pre kazdého,NPK
Nueva Versión Internacional,NVI
O Livro,OL
Quiché Centro Occidental,QUT
Reimer 2001,REIMER
Română Cornilescu,RMNN
Новый перевод на русский язык,RUSV
Reina-Valera Antigua,RVA
Reina-Valera 1960,RVR1960
Reina-Valera 1995,RVR1995
Slovo na cestu,SNC
Ang Salita ng Diyos,SND
Swahili New Testament,SNT
Svenska 1917,SV1917
Levande Bibeln,SVL
Создать страницу,SZ
Traducción en lenguaje actual,TLA
New Romanian Translation,TLCR
Todays New International Version 2005,TNIV
Textus Receptus Stephanus 1550,TR1550
Textus Receptus Scrivener 1894,TR1894
Українська Біблія. Переклад Івана Огієнка,UKR
Uspanteco,USP
Kinh Thánh tiếng Việt 1934,VIET
Worldwide English (New Testament),WE
Codex Vaticanus Westcott-Hort 1881,WHNU
Westminster Leningrad Codex,WLC
Wycliffe New Testament,WYC
Young's Literal Translation,YLT
1 João Ferreira de Almeida Atualizada AA
2 التفسير التطبيقى للكتاب المقدس ALAB
3 Shqip ALB
4 Amplified Bible AMP
5 Amuzgo de Guerrero AMU
6 American Standard Version ASV
7 La Bible du Semeur BDS
8 Български 1940 BG1940
9 Български BULG
10 Chinanteco de Comaltepec CCO
11 Contemporary English Version CEV
12 Cakchiquel Occidental CKW
13 Hrvatski CRO
14 Castilian CST
15 聖經和合本 (简体中文) CUVS
16 聖經和合本 (繁体中文) CUV
17 Darby Translation DARBY
18 Dette er Biblen på dansk DN1933
19 Det Norsk Bibelselskap 1930 DNB1930
20 English Standard Version ESV
21 GOD’S WORD Translation GW
22 Holman Christian Standard Bible HCSB
23 Kreyòl ayisyen bib HCV
24 Hiligaynon Bible HLGN
25 Hoffnung für Alle HOF
26 Het Boek HTB
27 Icelandic Bible ICELAND
28 Jacalteco – Oriental JAC
29 Károlyi-biblia KAR
30 Kekchi KEK
31 21st Century King James Version KJ21
32 King James Version KJV
33 La Biblia de las Américas LBLA
34 Levande Bibeln LB
35 La Parola è Vita LM
36 La Nuova Diodati LND
37 Louis Segond LSG
38 Luther Bibel 1545 LUTH1545
39 Māori Bible MAORI
40 Македонски Новиот Завет MNT
41 The Message MSG
42 Mam de Comitancillo Central MVC
43 Mam de Todos Santos Cuchumatán MVJ
44 New American Standard Bible NASB
45 New Century Version NCV
46 Náhuatl de Guerrero NGU
47 New International Reader's Version NIRV
48 New International Version 1984 NIV1984
49 New International Version 2010 NIV
50 New International Version - UK NIVUK
51 New King James Version NKJV
52 New Living Translation NLT
53 Nádej pre kazdého NPK
54 Nueva Versión Internacional NVI
55 O Livro OL
56 Quiché – Centro Occidental QUT
57 Reimer 2001 REIMER
58 Română Cornilescu RMNN
59 Новый перевод на русский язык RUSV
60 Reina-Valera Antigua RVA
61 Reina-Valera 1960 RVR1960
62 Reina-Valera 1995 RVR1995
63 Slovo na cestu SNC
64 Ang Salita ng Diyos SND
65 Swahili New Testament SNT
66 Svenska 1917 SV1917
67 Levande Bibeln SVL
68 Создать страницу SZ
69 Traducción en lenguaje actual TLA
70 New Romanian Translation TLCR
71 Today’s New International Version 2005 TNIV
72 Textus Receptus Stephanus 1550 TR1550
73 Textus Receptus Scrivener 1894 TR1894
74 Українська Біблія. Переклад Івана Огієнка UKR
75 Uspanteco USP
76 Kinh Thánh tiếng Việt 1934 VIET
77 Worldwide English (New Testament) WE
78 Codex Vaticanus Westcott-Hort 1881 WHNU
79 Westminster Leningrad Codex WLC
80 Wycliffe New Testament WYC
81 Young's Literal Translation YLT

View File

@ -1,39 +0,0 @@
عربي, ARA
Bible překlad 21. století, B21
Bible du Semeur, BDS
Българската Библия, BLG
Český ekumenický překlad, CEP
Hrvatski, CRO
Священное Писание, CRS
Version La Biblia al Dia, CST
中文和合本(简体), CUVS
Bibelen på hverdagsdansk, DK
Revidierte Elberfelder, ELB
Einheitsübersetzung, EU
Gute Nachricht Bibel, GNB
Hoffnung für alle, HFA
Hungarian, HUN
Het Boek, HTB
La Parola è Vita, ITA
IBS-fordítás (Új Károli), KAR
King James Version, KJV
Luther 1984, LUT
Septuaginta, LXX
Neue Genfer Übersetzung, NGU
New International Readers Version, NIRV
New International Version, NIV
Neues Leben, NL
En Levende Bok (NOR), NOR
Nádej pre kazdého, NPK
Noua traducere în limba românã, NTR
Nueva Versión Internacional, NVI
הברית הישנה, OT
Słowo Życia, POL
O Livro, PRT
Новый перевод на русский язык, RUS
Slovo na cestu, SNC
Schlachter 2000, SLT
En Levande Bok (SWE), SVL
Today's New International Version, TNIV
Türkçe, TR
Biblia Vulgata, VUL
1 عربي ARA
2 Bible – překlad 21. století B21
3 Bible du Semeur BDS
4 Българската Библия BLG
5 Český ekumenický překlad CEP
6 Hrvatski CRO
7 Священное Писание CRS
8 Version La Biblia al Dia CST
9 中文和合本(简体) CUVS
10 Bibelen på hverdagsdansk DK
11 Revidierte Elberfelder ELB
12 Einheitsübersetzung EU
13 Gute Nachricht Bibel GNB
14 Hoffnung für alle HFA
15 Hungarian HUN
16 Het Boek HTB
17 La Parola è Vita ITA
18 IBS-fordítás (Új Károli) KAR
19 King James Version KJV
20 Luther 1984 LUT
21 Septuaginta LXX
22 Neue Genfer Übersetzung NGU
23 New International Readers Version NIRV
24 New International Version NIV
25 Neues Leben NL
26 En Levende Bok (NOR) NOR
27 Nádej pre kazdého NPK
28 Noua traducere în limba românã NTR
29 Nueva Versión Internacional NVI
30 הברית הישנה OT
31 Słowo Życia POL
32 O Livro PRT
33 Новый перевод на русский язык RUS
34 Slovo na cestu SNC
35 Schlachter 2000 SLT
36 En Levande Bok (SWE) SVL
37 Today's New International Version TNIV
38 Türkçe TR
39 Biblia Vulgata VUL

View File

@ -1,27 +0,0 @@
New American Standard,nas
American Standard Version,asv
English Standard Version,esv
New King James Version,nkj
King James Version,kjv
Holman Christian Standard Bible,csb
Third Millennium Bible,tmb
New International Version,niv
New Living Translation,nlt
New Revised Standard,nrs
Revised Standard Version,rsv
Good News Translation,gnt
Douay-Rheims Bible,rhe
The Message,msg
The Complete Jewish Bible,cjb
New Century Version,ncv
GOD'S WORD Translation,gwd
Hebrew Names Version,hnv
World English Bible,web
The Bible in Basic English,bbe
Young's Literal Translation,ylt
Today's New International Version,tnv
New International Reader's Version,nrv
The Darby Translation,dby
The Webster Bible,wbt
The Latin Vulgate,vul
Weymouth New Testament,wnt
1 New American Standard nas
2 American Standard Version asv
3 English Standard Version esv
4 New King James Version nkj
5 King James Version kjv
6 Holman Christian Standard Bible csb
7 Third Millennium Bible tmb
8 New International Version niv
9 New Living Translation nlt
10 New Revised Standard nrs
11 Revised Standard Version rsv
12 Good News Translation gnt
13 Douay-Rheims Bible rhe
14 The Message msg
15 The Complete Jewish Bible cjb
16 New Century Version ncv
17 GOD'S WORD Translation gwd
18 Hebrew Names Version hnv
19 World English Bible web
20 The Bible in Basic English bbe
21 Young's Literal Translation ylt
22 Today's New International Version tnv
23 New International Reader's Version nrv
24 The Darby Translation dby
25 The Webster Bible wbt
26 The Latin Vulgate vul
27 Weymouth New Testament wnt

View File

@ -43,13 +43,13 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
Class documentation goes here.
"""
log.info(u'Custom Editor loaded')
def __init__(self, parent, manager):
def __init__(self, mediaitem, parent, manager):
"""
Constructor
"""
QtGui.QDialog.__init__(self)
self.parent = parent
QtGui.QDialog.__init__(self, parent)
self.manager = manager
self.mediaitem = mediaitem
self.setupUi(self)
# Create other objects and forms.
self.editSlideForm = EditCustomSlideForm(self)
@ -93,6 +93,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.titleEdit.setText(u'')
self.creditEdit.setText(u'')
self.themeComboBox.setCurrentIndex(0)
self.titleEdit.setFocus(QtCore.Qt.OtherFocusReason)
else:
self.customSlide = self.manager.get_object(CustomSlide, id)
self.titleEdit.setText(self.customSlide.title)
@ -115,7 +116,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
def accept(self):
log.debug(u'accept')
if self.saveCustom():
Receiver.send_message(u'custom_load_list')
QtGui.QDialog.accept(self)
def saveCustom(self):
@ -137,7 +137,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
self.customSlide.credits = unicode(self.creditEdit.text())
self.customSlide.theme_name = unicode(self.themeComboBox.currentText())
success = self.manager.save_object(self.customSlide)
self.parent.auto_select_id = self.customSlide.id
self.mediaitem.auto_select_id = self.customSlide.id
return success
def onUpButtonClicked(self):

View File

@ -28,7 +28,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate, SpellTextEdit, build_icon
from openlp.core.lib.ui import create_accept_reject_button_box
from openlp.core.lib.ui import create_accept_reject_button_box, UiStrings
class Ui_CustomSlideEditDialog(object):
def setupUi(self, customSlideEditDialog):
@ -54,11 +54,8 @@ class Ui_CustomSlideEditDialog(object):
QtCore.QMetaObject.connectSlotsByName(customSlideEditDialog)
def retranslateUi(self, customSlideEditDialog):
self.splitButton.setText(
translate('CustomPlugin.EditCustomForm', 'Split Slide'))
self.splitButton.setToolTip(
translate('CustomPlugin.EditCustomForm', 'Split a slide into two '
'only if it does not fit on the screen as one slide.'))
self.splitButton.setText(UiStrings().Split)
self.splitButton.setToolTip(UiStrings().SplitToolTip)
self.insertButton.setText(
translate('CustomPlugin.EditCustomForm', 'Insert Slide'))
self.insertButton.setToolTip(

View File

@ -57,15 +57,16 @@ class CustomMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'custom/custom'
MediaManagerItem.__init__(self, parent, self, icon)
self.edit_custom_form = EditCustomForm(self, self.parent.manager)
MediaManagerItem.__init__(self, parent, plugin, icon)
self.edit_custom_form = EditCustomForm(self, self.plugin.formparent,
self.plugin.manager)
self.singleServiceItem = False
self.quickPreviewAllowed = True
self.hasSearch = True
# Holds information about whether the edit is remotly triggered and
# which Custom is required.
self.remoteCustom = -1
self.manager = parent.manager
self.manager = plugin.manager
def addEndHeaderBar(self):
self.addToolbarSeparator()
@ -108,7 +109,7 @@ class CustomMediaItem(MediaManagerItem):
QtCore.QObject.connect(Receiver.get_receiver(),
QtCore.SIGNAL(u'custom_edit_clear'), self.onRemoteEditClear)
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.SIGNAL(u'custom_preview'), self.onPreviewClick)
@ -128,14 +129,6 @@ class CustomMediaItem(MediaManagerItem):
self.searchTextEdit.setCurrentSearchType(QtCore.QSettings().value(
u'%s/last search type' % self.settingsSection,
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):
# Sort out what custom we want to select after loading the list.
@ -154,11 +147,20 @@ class CustomMediaItem(MediaManagerItem):
if custom_slide.id == self.auto_select_id:
self.listView.setCurrentItem(custom_name)
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):
self.edit_custom_form.loadCustom(0)
self.edit_custom_form.exec_()
self.initialise()
self.onClearTextButtonClick()
self.onSelectionChange()
def onRemoteEditClear(self):
self.remoteTriggered = None
@ -178,6 +180,8 @@ class CustomMediaItem(MediaManagerItem):
self.remoteTriggered = remote_type
self.edit_custom_form.loadCustom(custom_id, (remote_type == u'P'))
self.edit_custom_form.exec_()
self.auto_select_id = -1
self.onSearchTextButtonClick()
def onEditClick(self):
"""
@ -188,7 +192,8 @@ class CustomMediaItem(MediaManagerItem):
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.edit_custom_form.loadCustom(item_id, False)
self.edit_custom_form.exec_()
self.initialise()
self.auto_select_id = -1
self.onSearchTextButtonClick()
def onDeleteClick(self):
"""
@ -200,7 +205,7 @@ class CustomMediaItem(MediaManagerItem):
id_list = [(item.data(QtCore.Qt.UserRole)).toInt()[0]
for item in self.listView.selectedIndexes()]
for id in id_list:
self.parent.manager.delete_object(CustomSlide, id)
self.plugin.manager.delete_object(CustomSlide, id)
for row in row_list:
self.listView.takeItem(row)
@ -216,7 +221,7 @@ class CustomMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.AllowsPreview)
service_item.add_capability(ItemCapabilities.AllowsLoop)
service_item.add_capability(ItemCapabilities.AllowsVirtualSplit)
customSlide = self.parent.manager.get_object(CustomSlide, item_id)
customSlide = self.plugin.manager.get_object(CustomSlide, item_id)
title = customSlide.title
credit = customSlide.credits
service_item.edit_id = item_id
@ -248,13 +253,13 @@ class CustomMediaItem(MediaManagerItem):
search_type = self.searchTextEdit.currentSearchType()
if search_type == CustomSearch.Titles:
log.debug(u'Titles Search')
search_results = self.parent.manager.get_all_objects(CustomSlide,
search_results = self.plugin.manager.get_all_objects(CustomSlide,
CustomSlide.title.like(u'%' + self.whitespace.sub(u' ',
search_keywords) + u'%'), order_by_ref=CustomSlide.title)
self.loadList(search_results)
elif search_type == CustomSearch.Themes:
log.debug(u'Theme Search')
search_results = self.parent.manager.get_all_objects(CustomSlide,
search_results = self.plugin.manager.get_all_objects(CustomSlide,
CustomSlide.theme_name.like(u'%' + self.whitespace.sub(u' ',
search_keywords) + u'%'), order_by_ref=CustomSlide.title)
self.loadList(search_results)

View File

@ -47,7 +47,7 @@ class ImageMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'images/image'
MediaManagerItem.__init__(self, parent, self, icon)
MediaManagerItem.__init__(self, parent, plugin, icon)
self.quickPreviewAllowed = True
self.hasSearch = True
QtCore.QObject.connect(Receiver.get_receiver(),
@ -112,14 +112,14 @@ class ImageMediaItem(MediaManagerItem):
def loadList(self, list, initialLoad=False):
if not initialLoad:
self.parent.formparent.displayProgressBar(len(list))
self.plugin.formparent.displayProgressBar(len(list))
# Sort the themes by its filename considering language specific
# characters. lower() is needed for windows!
list.sort(cmp=locale.strcoll,
key=lambda filename: os.path.split(unicode(filename))[1].lower())
for imageFile in list:
if not initialLoad:
self.parent.formparent.incrementProgressBar()
self.plugin.formparent.incrementProgressBar()
filename = os.path.split(unicode(imageFile))[1]
thumb = os.path.join(self.servicePath, filename)
if os.path.exists(thumb):
@ -134,7 +134,7 @@ class ImageMediaItem(MediaManagerItem):
item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(imageFile))
self.listView.addItem(item_name)
if not initialLoad:
self.parent.formparent.finishedProgressBar()
self.plugin.formparent.finishedProgressBar()
def generateSlideData(self, service_item, item=None, xmlVersion=False):
if item:
@ -188,7 +188,7 @@ class ImageMediaItem(MediaManagerItem):
Called to reset the Live backgound with the image selected,
"""
self.resetAction.setVisible(False)
self.parent.liveController.display.resetImage()
self.plugin.liveController.display.resetImage()
def liveThemeChanged(self):
"""
@ -208,7 +208,7 @@ class ImageMediaItem(MediaManagerItem):
filename = unicode(bitem.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
(path, name) = os.path.split(filename)
self.parent.liveController.display.directImage(name, filename)
self.plugin.liveController.display.directImage(name, filename)
self.resetAction.setVisible(True)
else:
critical_error_message_box(UiStrings().LiveBGError,

View File

@ -50,7 +50,7 @@ class MediaMediaItem(MediaManagerItem):
self.background = False
self.PreviewFunction = QtGui.QPixmap(
u':/media/media_video.png').toImage()
MediaManagerItem.__init__(self, parent, self, icon)
MediaManagerItem.__init__(self, parent, plugin, icon)
self.singleServiceItem = False
self.hasSearch = True
self.mediaObject = None
@ -65,8 +65,8 @@ class MediaMediaItem(MediaManagerItem):
self.onNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media')
self.onNewFileMasks = unicode(translate('MediaPlugin.MediaItem',
'Videos (%s);;Audio (%s);;%s (*)')) % (
u' '.join(self.parent.video_extensions_list),
u' '.join(self.parent.audio_extensions_list), UiStrings().AllFiles)
u' '.join(self.plugin.video_extensions_list),
u' '.join(self.plugin.audio_extensions_list), UiStrings().AllFiles)
self.replaceAction.setText(UiStrings().ReplaceBG)
self.replaceAction.setToolTip(UiStrings().ReplaceLiveBG)
self.resetAction.setText(UiStrings().ResetBG)
@ -95,7 +95,7 @@ class MediaMediaItem(MediaManagerItem):
Called to reset the Live backgound with the media selected,
"""
self.resetAction.setVisible(False)
self.parent.liveController.display.resetVideo()
self.plugin.liveController.display.resetVideo()
def videobackgroundReplaced(self):
"""
@ -114,7 +114,7 @@ class MediaMediaItem(MediaManagerItem):
filename = unicode(item.data(QtCore.Qt.UserRole).toString())
if os.path.exists(filename):
(path, name) = os.path.split(filename)
self.parent.liveController.display.video(filename, 0, True)
self.plugin.liveController.display.video(filename, 0, True)
self.resetAction.setVisible(True)
else:
critical_error_message_box(UiStrings().LiveBGError,

View File

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

View File

@ -46,14 +46,14 @@ class PresentationMediaItem(MediaManagerItem):
"""
log.info(u'Presentations Media Item loaded')
def __init__(self, parent, icon, title, controllers):
def __init__(self, parent, plugin, icon, controllers):
"""
Constructor. Setup defaults
"""
self.controllers = controllers
self.IconPath = u'presentations/presentation'
self.Automatic = u''
MediaManagerItem.__init__(self, parent, self, icon)
MediaManagerItem.__init__(self, parent, plugin, icon)
self.message_listener = MessageListener(self)
self.hasSearch = True
QtCore.QObject.connect(Receiver.get_receiver(),
@ -82,7 +82,7 @@ class PresentationMediaItem(MediaManagerItem):
for type in types:
if fileType.find(type) == -1:
fileType += u'*.%s ' % type
self.parent.serviceManager.supportedSuffixes(type)
self.plugin.serviceManager.supportedSuffixes(type)
self.onNewFileMasks = unicode(translate('PresentationPlugin.MediaItem',
'Presentations (%s)')) % fileType
@ -161,14 +161,14 @@ class PresentationMediaItem(MediaManagerItem):
titles = [os.path.split(file)[1] for file in currlist]
Receiver.send_message(u'cursor_busy')
if not initialLoad:
self.parent.formparent.displayProgressBar(len(files))
self.plugin.formparent.displayProgressBar(len(files))
# Sort the themes by its filename considering language specific
# characters. lower() is needed for windows!
files.sort(cmp=locale.strcoll,
key=lambda filename: os.path.split(unicode(filename))[1].lower())
for file in files:
if not initialLoad:
self.parent.formparent.incrementProgressBar()
self.plugin.formparent.incrementProgressBar()
if currlist.count(file) > 0:
continue
filename = os.path.split(unicode(file))[1]
@ -208,7 +208,7 @@ class PresentationMediaItem(MediaManagerItem):
self.listView.addItem(item_name)
Receiver.send_message(u'cursor_normal')
if not initialLoad:
self.parent.formparent.finishedProgressBar()
self.plugin.formparent.finishedProgressBar()
def onDeleteClick(self):
"""

View File

@ -77,7 +77,7 @@ class PresentationPlugin(Plugin):
try:
self.controllers[controller].start_process()
except:
log.exception(u'Failed to start controller process')
log.warn(u'Failed to start controller process')
self.controllers[controller].available = False
self.mediaItem.buildFileMaskString()
@ -99,7 +99,7 @@ class PresentationPlugin(Plugin):
Create the Media Manager List
"""
return PresentationMediaItem(
self, self.icon, self.name, self.controllers)
self.mediadock.media_dock, self, self.icon, self.controllers)
def registerControllers(self, controller):
"""
@ -128,7 +128,7 @@ class PresentationPlugin(Plugin):
try:
__import__(modulename, globals(), locals(), [])
except ImportError:
log.exception(u'Failed to import %s on path %s',
log.warn(u'Failed to import %s on path %s',
modulename, path)
controller_classes = PresentationController.__subclasses__()
for controller_class in controller_classes:

View File

@ -27,91 +27,109 @@
-->
<head>
<meta charset="utf-8" />
<title>OpenLP 2.0 Remote</title>
<title>${app_title}</title>
<link rel="stylesheet" href="/files/jquery.mobile.css" />
<link rel="stylesheet" href="/files/openlp.css" />
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/openlp.js"></script>
<script type="text/javascript" src="/files/jquery.mobile.js"></script>
<script type="text/javascript">
translationStrings = {
"go_live": "${go_live}",
"add_to_service": "${add_to_service}",
"no_results": "${no_results}",
"back": "${back}"
}
</script>
</head>
<body>
<div data-role="page" id="home">
<div data-role="header">
<h1>OpenLP 2.0 Remote</h1>
<h1>${app_title}</h1>
</div>
<div data-role="content">
<div data-role="controlgroup">
<a href="#service-manager" data-role="button" data-icon="arrow-r" data-iconpos="right">Service Manager</a>
<a href="#slide-controller" data-role="button" data-icon="arrow-r" data-iconpos="right">Slide Controller</a>
<a href="#alerts" data-role="button" data-icon="arrow-r" data-iconpos="right">Alerts</a>
<a href="#search" data-role="button" data-icon="arrow-r" data-iconpos="right">Search</a>
<a href="#service-manager" data-role="button" data-icon="arrow-r" data-iconpos="right">${service_manager}</a>
<a href="#slide-controller" data-role="button" data-icon="arrow-r" data-iconpos="right">${slide_controller}</a>
<a href="#alerts" data-role="button" data-icon="arrow-r" data-iconpos="right">${alerts}</a>
<a href="#search" data-role="button" data-icon="arrow-r" data-iconpos="right">${search}</a>
</div>
</div>
</div>
<div data-role="page" id="service-manager">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Service Manager</h1>
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">Refresh</a>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${service_manager}</h1>
<a href="#" id="service-refresh" data-role="button" data-icon="refresh">${refresh}</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
</ul>
</div>
<div data-role="footer" data-theme="b" class="ui-bar">
<a href="#" id="service-blank" data-role="button" data-icon="blank">Blank</a>
<a href="#" id="service-unblank" data-role="button" data-icon="unblank">Show</a>
<a href="#" id="service-previous" data-role="button" data-icon="arrow-l">Prev</a>
<a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
<a href="#" id="service-blank" data-role="button" data-icon="blank">${blank}</a>
<a href="#" id="service-unblank" data-role="button" data-icon="unblank">${show}</a>
<a href="#" id="service-previous" data-role="button" data-icon="arrow-l">${prev}</a>
<a href="#" id="service-next" data-role="button" data-icon="arrow-r" data-iconpos="right">${next}</a>
</div>
</div>
<div data-role="page" id="slide-controller">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Slide Controller</h1>
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">Refresh</a>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${slide_controller}</h1>
<a href="#" id="controller-refresh" data-role="button" data-icon="refresh">${refresh}</a>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true">
</ul>
</div>
<div data-role="footer" data-theme="b" class="ui-bar">
<a href="#" id="controller-blank" data-role="button" data-icon="blank">Blank</a>
<a href="#" id="controller-unblank" data-role="button" data-icon="unblank">Show</a>
<a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">Prev</a>
<a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">Next</a>
<a href="#" id="controller-blank" data-role="button" data-icon="blank">${blank}</a>
<a href="#" id="controller-unblank" data-role="button" data-icon="unblank">${show}</a>
<a href="#" id="controller-previous" data-role="button" data-icon="arrow-l">${prev}</a>
<a href="#" id="controller-next" data-role="button" data-icon="arrow-r" data-iconpos="right">${next}</a>
</div>
</div>
<div data-role="page" id="alerts">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Alerts</h1>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${alerts}</h1>
</div>
<div data-role="content">
<div data-role="fieldcontain">
<label for="alert-text">Text:</label>
<label for="alert-text">${text}:</label>
<input type="text" name="alert-text" id="alert-text" value="" />
</div>
<a href="#" id="alert-submit" data-role="button">Show Alert</a>
<a href="#" id="alert-submit" data-role="button">${show_alert}</a>
</div>
</div>
<div data-role="page" id="search">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>Search</h1>
<a href="#" data-rel="back" data-icon="arrow-l">${back}</a>
<h1>${search}</h1>
</div>
<div data-role="content">
<div data-role="fieldcontain">
<label for="search-plugin">Search:</label>
<label for="search-plugin">${search}:</label>
<select name="search-plugin" id="search-plugin" data-native-menu="false"></select>
</div>
<div data-role="fieldcontain">
<label for="search-text">Text:</label>
<label for="search-text">${text}:</label>
<input type="search" name="search-text" id="search-text" value="" />
</div>
<a href="#" id="search-submit" data-role="button">Search</a>
<a href="#" id="search-submit" data-role="button">${search}</a>
<ul data-role="listview" data-inset="true">
</div>
</div>
<div data-role="page" id="options">
<div data-role="header" data-position="inline" data-theme="b">
<h1>${options}</h1>
</div>
<div data-role="content">
<input type="hidden" id="selected-item" value="" />
<a href="#" id="go-live" data-role="button">${go_live}</a>
<a href="#" id="add-to-service" data-role="button">${add_to_service}</a>
</div>
</div>
</body>
</html>

0
openlp/plugins/remotes/html/json2.js Executable file → Normal file
View File

View File

@ -47,7 +47,7 @@ window.OpenLP = {
var select = $("#search-plugin");
select.html("");
$.each(data.results.items, function (idx, value) {
select.append("<option value='" + value + "'>" + value + "</option>");
select.append("<option value='" + value[0] + "'>" + value[1] + "</option>");
});
select.selectmenu("refresh");
}
@ -215,16 +215,15 @@ window.OpenLP = {
var ul = $("#search > div[data-role=content] > ul[data-role=listview]");
ul.html("");
if (data.results.items.length == 0) {
var li = $("<li data-icon=\"false\">").text('No results');
var li = $("<li data-icon=\"false\">").text(translationStrings["no_results"]);
ul.append(li);
}
else {
$.each(data.results.items, function (idx, value) {
var item = $("<li>").text(value[1]);
var golive = $("<a href=\"#\">Go Live</a>").attr("value", value[0]).click(OpenLP.goLive);
var additem = $("<a href=\"#\">Add To Service</a>").attr("value", value[0]).click(OpenLP.addToService);
item.append($("<ul>").append($("<li>").append(golive)).append($("<li>").append(additem)));
ul.append(item);
ul.append($("<li>").append($("<a>").attr("href", "#options")
.attr("data-rel", "dialog").attr("data-transition", "pop")
.attr("value", value[0]).click(OpenLP.showOptions)
.text(value[1])));
});
}
ul.listview("refresh");
@ -232,19 +231,23 @@ window.OpenLP = {
);
return false;
},
showOptions: function (event) {
var element = OpenLP.getElement(event);
console.log(element);
$("#selected-item").val(element.attr("value"));
},
goLive: function (event) {
var item = OpenLP.getElement(event);
var id = item.attr("value");
var id = $("#selected-item").val();
var text = JSON.stringify({"request": {"id": id}});
$.getJSON(
"/api/" + $("#search-plugin").val() + "/live",
{"data": text})
$.mobile.changePage("slide-controller");
{"data": text}
);
$.mobile.changePage("#slide-controller");
return false;
},
addToService: function (event) {
var item = OpenLP.getElement(event);
var id = item.attr("value");
var id = $("#selected-item").val();
var text = JSON.stringify({"request": {"id": id}});
$.getJSON(
"/api/" + $("#search-plugin").val() + "/add",
@ -253,6 +256,7 @@ window.OpenLP = {
history.back();
}
);
$("#options").dialog("close");
return false;
}
}
@ -274,6 +278,8 @@ $("#controller-unblank").live("click", OpenLP.unblankDisplay);
$("#alert-submit").live("click", OpenLP.showAlert);
// Search
$("#search-submit").live("click", OpenLP.search);
$("#go-live").live("click", OpenLP.goLive);
$("#add-to-service").live("click", OpenLP.addToService);
// Poll the server twice a second to get any updates.
OpenLP.getSearchablePlugins();
$.ajaxSetup({ cache: false });

View File

@ -6,8 +6,8 @@
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Jeffrey Smith, Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode #
# Woldsund #
# --------------------------------------------------------------------------- #
@ -27,12 +27,13 @@
-->
<head>
<meta charset="utf-8" />
<title>OpenLP 2.0 Stage View</title>
<title>${stage_title}</title>
<link rel="stylesheet" href="/files/stage.css" />
<script type="text/javascript" src="/files/jquery.js"></script>
<script type="text/javascript" src="/files/stage.js"></script>
</head>
<body>
<input type="hidden" id="next-text" value="${next}" />
<div id="right">
<div id="clock"></div>
<div id="notes"></div>

View File

@ -100,24 +100,24 @@ window.OpenLP = {
$("#tag" + OpenLP.currentTags[OpenLP.currentSlide]).addClass("currenttag");
var slide = OpenLP.currentSlides[OpenLP.currentSlide];
var text = slide["text"];
text = text.replace(/\n/g, '<br />');
text = text.replace(/\n/g, "<br />");
$("#currentslide").html(text);
text = "";
if (OpenLP.currentSlide < OpenLP.currentSlides.length - 1) {
for (var idx = OpenLP.currentSlide + 1; idx < OpenLP.currentSlides.length; idx++) {
if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1])
text = text + '<p class="nextslide">';
text = text + "<p class=\"nextslide\">";
text = text + OpenLP.currentSlides[idx]["text"];
if (OpenLP.currentTags[idx] != OpenLP.currentTags[idx - 1])
text = text + '</p>';
text = text + "</p>";
else
text = text + '<br />';
text = text + "<br />";
}
text = text.replace(/\n/g, '<br />');
text = text.replace(/\n/g, "<br />");
$("#nextslide").html(text);
}
else {
text = '<p class="nextslide">Next: ' + OpenLP.nextSong + '</p>';
text = "<p class=\"nextslide\">" + $("#next-text").val() + ": " + OpenLP.nextSong + "</p>";
$("#nextslide").html(text);
}
},

View File

@ -115,7 +115,6 @@ import logging
import os
import urlparse
import re
from pprint import pformat
try:
import json
@ -123,10 +122,11 @@ except ImportError:
import simplejson as json
from PyQt4 import QtCore, QtNetwork
from mako.template import Template
from openlp.core.lib import Receiver, PluginStatus
from openlp.core.lib import Receiver, PluginStatus, StringContent
from openlp.core.ui import HideMode
from openlp.core.utils import AppLocation
from openlp.core.utils import AppLocation, translate
log = logging.getLogger(__name__)
@ -154,12 +154,12 @@ class HttpServer(object):
e.g. http://localhost:4316/send/slidecontroller_live_next
http://localhost:4316/send/alerts_text?q=your%20alert%20text
"""
def __init__(self, parent):
def __init__(self, plugin):
"""
Initialise the httpserver, and start the server
"""
log.debug(u'Initialise httpserver')
self.parent = parent
self.plugin = plugin
self.html_dir = os.path.join(
AppLocation.get_directory(AppLocation.PluginsDir),
u'remotes', u'html')
@ -176,10 +176,10 @@ class HttpServer(object):
"""
log.debug(u'Start TCP server')
port = QtCore.QSettings().value(
self.parent.settingsSection + u'/port',
self.plugin.settingsSection + u'/port',
QtCore.QVariant(4316)).toInt()[0]
address = QtCore.QSettings().value(
self.parent.settingsSection + u'/ip address',
self.plugin.settingsSection + u'/ip address',
QtCore.QVariant(u'0.0.0.0')).toString()
self.server = QtNetwork.QTcpServer()
self.server.listen(QtNetwork.QHostAddress(address), port)
@ -261,10 +261,11 @@ class HttpConnection(object):
self.ready_read)
QtCore.QObject.connect(self.socket, QtCore.SIGNAL(u'disconnected()'),
self.disconnected)
self.translate()
def _get_service_items(self):
service_items = []
service_manager = self.parent.parent.serviceManager
service_manager = self.parent.plugin.serviceManager
if self.parent.current_item:
cur_uuid = self.parent.current_item._uuid
else:
@ -280,6 +281,31 @@ class HttpConnection(object):
})
return service_items
def translate(self):
"""
Translate various strings in the mobile app.
"""
self.template_vars = {
'app_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Remote'),
'stage_title': translate('RemotePlugin.Mobile', 'OpenLP 2.0 Stage View'),
'service_manager': translate('RemotePlugin.Mobile', 'Service Manager'),
'slide_controller': translate('RemotePlugin.Mobile', 'Slide Controller'),
'alerts': translate('RemotePlugin.Mobile', 'Alerts'),
'search': translate('RemotePlugin.Mobile', 'Search'),
'back': translate('RemotePlugin.Mobile', 'Back'),
'refresh': translate('RemotePlugin.Mobile', 'Refresh'),
'blank': translate('RemotePlugin.Mobile', 'Blank'),
'show': translate('RemotePlugin.Mobile', 'Show'),
'prev': translate('RemotePlugin.Mobile', 'Prev'),
'next': translate('RemotePlugin.Mobile', 'Next'),
'text': translate('RemotePlugin.Mobile', 'Text'),
'show_alert': translate('RemotePlugin.Mobile', 'Show Alert'),
'go_live': translate('RemotePlugin.Mobile', 'Go Live'),
'add_to_service': translate('RemotePlugin.Mobile', 'Add To Service'),
'no_results': translate('RemotePlugin.Mobile', 'No Results'),
'options': translate('RemotePlugin.Mobile', 'Options')
}
def ready_read(self):
"""
Data has been sent from the client. Respond to it
@ -327,8 +353,11 @@ class HttpConnection(object):
if not path.startswith(self.parent.html_dir):
return HttpResponse(code=u'404 Not Found')
ext = os.path.splitext(filename)[1]
html = None
if ext == u'.html':
mimetype = u'text/html'
variables = self.template_vars
html = Template(filename=path, input_encoding=u'utf-8', output_encoding=u'utf-8').render(**variables)
elif ext == u'.css':
mimetype = u'text/css'
elif ext == u'.js':
@ -343,6 +372,9 @@ class HttpConnection(object):
mimetype = u'text/plain'
file_handle = None
try:
if html:
content = html
else:
file_handle = open(path, u'rb')
log.debug(u'Opened %s' % path)
content = file_handle.read()
@ -457,10 +489,11 @@ class HttpConnection(object):
"""
if action == u'search':
searches = []
for plugin in self.parent.parent.pluginManager.plugins:
for plugin in self.parent.plugin.pluginManager.plugins:
if plugin.status == PluginStatus.Active and \
plugin.mediaItem and plugin.mediaItem.hasSearch:
searches.append(plugin.name)
searches.append([plugin.name, unicode(
plugin.textStrings[StringContent.Name][u'plural'])])
return HttpResponse(
json.dumps({u'results': {u'items': searches}}),
{u'Content-Type': u'application/json'})
@ -473,10 +506,10 @@ class HttpConnection(object):
The plugin name to search in.
"""
text = json.loads(self.url_params[u'data'][0])[u'request'][u'text']
plugin = self.parent.parent.pluginManager.get_plugin_by_name(type)
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and \
plugin.mediaItem and plugin.mediaItem.hasSearch:
results =plugin.mediaItem.search(text)
results = plugin.mediaItem.search(text)
else:
results = []
return HttpResponse(
@ -488,7 +521,7 @@ class HttpConnection(object):
Go live on an item of type ``type``.
"""
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
plugin = self.parent.parent.pluginManager.get_plugin_by_name(type)
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
plugin.mediaItem.goLive(id)
@ -497,7 +530,7 @@ class HttpConnection(object):
Add item of type ``type`` to the end of the service
"""
id = json.loads(self.url_params[u'data'][0])[u'request'][u'id']
plugin = self.parent.parent.pluginManager.get_plugin_by_name(type)
plugin = self.parent.plugin.pluginManager.get_plugin_by_name(type)
if plugin.status == PluginStatus.Active and plugin.mediaItem:
item_id = plugin.mediaItem.createItemFromId(id)
plugin.mediaItem.addToService(item_id)

View File

@ -47,12 +47,12 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
"""
log.info(u'%s EditSongForm loaded', __name__)
def __init__(self, parent, manager):
def __init__(self, mediaitem, parent, manager):
"""
Constructor
"""
QtGui.QDialog.__init__(self, parent)
self.parent = parent
self.mediaitem = mediaitem
self.song = None
# can this be automated?
self.width = 400
@ -90,7 +90,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.onVerseListViewPressed)
QtCore.QObject.connect(self.themeAddButton,
QtCore.SIGNAL(u'clicked()'),
self.parent.parent.renderer.theme_manager.onAddTheme)
self.mediaitem.plugin.renderer.theme_manager.onAddTheme)
QtCore.QObject.connect(self.maintenanceButton,
QtCore.SIGNAL(u'clicked()'), self.onMaintenanceButtonClicked)
QtCore.QObject.connect(Receiver.get_receiver(),
@ -649,7 +649,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
text = unicode(self.songBookComboBox.currentText())
if item == 0 and text:
temp_song_book = text
self.parent.song_maintenance_form.exec_()
self.mediaitem.song_maintenance_form.exec_()
self.loadAuthors()
self.loadBooks()
self.loadTopics()
@ -696,7 +696,6 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.clearCaches()
if self._validate_song():
self.saveSong()
Receiver.send_message(u'songs_load_list')
self.song = None
QtGui.QDialog.accept(self)
@ -755,7 +754,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.song.topics.append(self.manager.get_object(Topic, topicId))
clean_song(self.manager, self.song)
self.manager.save_object(self.song)
self.parent.auto_select_id = self.song.id
self.mediaitem.auto_select_id = self.song.id
def _processLyrics(self):
"""

View File

@ -28,7 +28,7 @@
from PyQt4 import QtCore, QtGui
from openlp.core.lib import build_icon, translate, SpellTextEdit
from openlp.core.lib.ui import create_accept_reject_button_box
from openlp.core.lib.ui import create_accept_reject_button_box, UiStrings
from openlp.plugins.songs.lib import VerseType
class Ui_EditVerseDialog(object):
@ -89,11 +89,8 @@ class Ui_EditVerseDialog(object):
VerseType.TranslatedNames[VerseType.Ending])
self.verseTypeComboBox.setItemText(VerseType.Other,
VerseType.TranslatedNames[VerseType.Other])
self.splitButton.setText(
translate('SongsPlugin.EditVerseForm', '&Split'))
self.splitButton.setToolTip(
translate('SongsPlugin.EditVerseForm', 'Split a slide into two '
'only if it does not fit on the screen as one slide.'))
self.splitButton.setText(UiStrings().Split)
self.splitButton.setToolTip(UiStrings().SplitToolTip)
self.insertButton.setText(
translate('SongsPlugin.EditVerseForm', '&Insert'))
self.insertButton.setToolTip(

View File

@ -297,7 +297,7 @@ class SongImportForm(OpenLPWizard):
self.songsOfFellowshipDisabledLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'The Songs of '
'Fellowship importer has been disabled because OpenLP cannot '
'find OpenOffice.org on your computer.'))
'access OpenOffice or LibreOffice.'))
self.genericAddButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.genericRemoveButton.setText(
@ -305,7 +305,7 @@ class SongImportForm(OpenLPWizard):
self.genericDisabledLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'The generic document/'
'presentation importer has been disabled because OpenLP cannot '
'find OpenOffice.org on your computer.'))
'access OpenOffice or LibreOffice.'))
self.easiSlidesFilenameLabel.setText(
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.easiSlidesBrowseButton.setText(UiStrings().Browse)
@ -772,9 +772,9 @@ class SongImportForm(OpenLPWizard):
SettingsManager.get_last_dir(self.plugin.settingsSection, 1))
if not filename:
return
file = codecs.open(filename, u'w', u'utf-8')
file.write(self.errorReportTextEdit.toPlainText())
file.close()
report_file = codecs.open(filename, u'w', u'utf-8')
report_file.write(self.errorReportTextEdit.toPlainText())
report_file.close()
def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False,
single_select=False):

View File

@ -32,6 +32,9 @@ from openlp.core.lib import translate
from db import Author
from ui import SongStrings
WHITESPACE = re.compile(r'[\W_]+', re.UNICODE)
APOSTROPHE = re.compile(u'[\'`ʻ]', re.UNICODE)
class VerseType(object):
"""
VerseType provides an enumeration for the tags that may be associated
@ -246,6 +249,12 @@ def retrieve_windows_encoding(recommendation=None):
return None
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):
"""
Cleans the search title, rebuilds the search lyrics, adds a default author
@ -262,20 +271,22 @@ def clean_song(manager, song):
if song.alternate_title is None:
song.alternate_title = u''
song.alternate_title = song.alternate_title.strip()
whitespace = re.compile(r'\W+', re.UNICODE)
song.search_title = (whitespace.sub(u' ', song.title).strip() + u'@' +
whitespace.sub(u' ', song.alternate_title).strip()).strip().lower()
# Remove the old "language" attribute from lyrics tag (prior to 1.9.5). This
# is not very important, but this keeps the database clean. This can be
# removed when everybody has cleaned his songs.
song.lyrics = song.lyrics.replace(u'<lyrics language="en">', u'<lyrics>')
song.search_title = clean_string(song.title) + u'@' + \
clean_string(song.alternate_title)
# Only do this, if we the song is a 1.9.4 song (or older).
if song.lyrics.find(u'<lyrics language="en">') != -1:
# Remove the old "language" attribute from lyrics tag (prior to 1.9.5).
# This is not very important, but this keeps the database clean. This
# can be removed when everybody has cleaned his songs.
song.lyrics = song.lyrics.replace(
u'<lyrics language="en">', u'<lyrics>')
verses = SongXML().get_verses(song.lyrics)
lyrics = u' '.join([whitespace.sub(u' ', verse[1]) for verse in verses])
song.search_lyrics = lyrics.lower()
song.search_lyrics = u' '.join([clean_string(verse[1])
for verse in verses])
# We need a new and clean SongXML instance.
sxml = SongXML()
# Rebuild the song's verses, to remove any wrong verse names (for example
# translated ones), which might have been added prior to 1.9.5.
# Rebuild the song's verses, to remove any wrong verse names (for
# example translated ones), which might have been added prior to 1.9.5.
# List for later comparison.
compare_order = []
for verse in verses:
@ -300,9 +311,11 @@ def clean_song(manager, song):
order = []
new_order = []
for verse_def in order:
verse_type = VerseType.Tags[VerseType.from_loose_input(verse_def[0])]
verse_type = VerseType.Tags[
VerseType.from_loose_input(verse_def[0])]
if len(verse_def) > 1:
new_order.append((u'%s%s' % (verse_type, verse_def[1:])).upper())
new_order.append(
(u'%s%s' % (verse_type, verse_def[1:])).upper())
else:
new_order.append(verse_type.upper())
song.verse_order = u' '.join(new_order)
@ -311,6 +324,11 @@ def clean_song(manager, song):
if order not in compare_order:
song.verse_order = u''
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.
if not song.authors:
name = SongStrings.AuthorUnknown

View File

@ -165,7 +165,7 @@ def init_schema(url):
Column(u'id', types.Integer, primary_key=True),
Column(u'first_name', types.Unicode(128)),
Column(u'last_name', types.Unicode(128)),
Column(u'display_name', types.Unicode(255), nullable=False)
Column(u'display_name', types.Unicode(255), index=True, nullable=False)
)
# Definition of the "media_files" table
@ -186,7 +186,7 @@ def init_schema(url):
songs_table = Table(u'songs', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'song_book_id', types.Integer,
ForeignKey(u'song_books.id'), default=0),
ForeignKey(u'song_books.id'), default=None),
Column(u'title', types.Unicode(255), nullable=False),
Column(u'alternate_title', types.Unicode(255)),
Column(u'lyrics', types.UnicodeText, nullable=False),
@ -203,7 +203,7 @@ def init_schema(url):
# Definition of the "topics" table
topics_table = Table(u'topics', metadata,
Column(u'id', types.Integer, primary_key=True),
Column(u'name', types.Unicode(128), nullable=False)
Column(u'name', types.Unicode(128), index=True, nullable=False)
)
# Definition of the "authors_songs" table
@ -230,27 +230,6 @@ def init_schema(url):
ForeignKey(u'topics.id'), primary_key=True)
)
# Define table indexes
Index(u'authors_id', authors_table.c.id)
Index(u'authors_display_name_id', authors_table.c.display_name,
authors_table.c.id)
Index(u'media_files_id', media_files_table.c.id)
Index(u'song_books_id', song_books_table.c.id)
Index(u'songs_id', songs_table.c.id)
Index(u'topics_id', topics_table.c.id)
Index(u'authors_songs_author', authors_songs_table.c.author_id,
authors_songs_table.c.song_id)
Index(u'authors_songs_song', authors_songs_table.c.song_id,
authors_songs_table.c.author_id)
Index(u'media_files_songs_file', media_files_songs_table.c.media_file_id,
media_files_songs_table.c.song_id)
Index(u'media_files_songs_song', media_files_songs_table.c.song_id,
media_files_songs_table.c.media_file_id)
Index(u'topics_song_topic', songs_topics_table.c.topic_id,
songs_topics_table.c.song_id)
Index(u'topics_song_song', songs_topics_table.c.song_id,
songs_topics_table.c.topic_id)
mapper(Author, authors_table)
mapper(Book, song_books_table)
mapper(MediaFile, media_files_table)

View File

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

View File

@ -27,6 +27,8 @@
"""
The :mod:`importer` modules provides the general song import functionality.
"""
import logging
from opensongimport import OpenSongImport
from easislidesimport import EasiSlidesImport
from olpimport import OpenLPSongImport
@ -38,20 +40,24 @@ from songbeamerimport import SongBeamerImport
from songshowplusimport import SongShowPlusImport
from foilpresenterimport import FoilPresenterImport
# Imports that might fail
log = logging.getLogger(__name__)
try:
from olp1import import OpenLP1SongImport
HAS_OPENLP1 = True
except ImportError:
log.exception('Error importing %s', 'OpenLP1SongImport')
HAS_OPENLP1 = False
try:
from sofimport import SofImport
HAS_SOF = True
except ImportError:
log.exception('Error importing %s', 'SofImport')
HAS_SOF = False
try:
from oooimport import OooImport
HAS_OOO = True
except ImportError:
log.exception('Error importing %s', 'OooImport')
HAS_OOO = False
class SongFormat(object):

View File

@ -27,6 +27,7 @@
import logging
import locale
import re
from PyQt4 import QtCore, QtGui
from sqlalchemy.sql import or_
@ -37,7 +38,8 @@ from openlp.core.lib.searchedit import SearchEdit
from openlp.core.lib.ui import UiStrings
from openlp.plugins.songs.forms import EditSongForm, SongMaintenanceForm, \
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.ui import SongStrings
@ -62,12 +64,13 @@ class SongMediaItem(MediaManagerItem):
def __init__(self, parent, plugin, icon):
self.IconPath = u'songs/song'
MediaManagerItem.__init__(self, parent, self, icon)
self.edit_song_form = EditSongForm(self, self.parent.manager)
self.openLyrics = OpenLyrics(self.parent.manager)
MediaManagerItem.__init__(self, parent, plugin, icon)
self.edit_song_form = EditSongForm(self, self.plugin.formparent,
self.plugin.manager)
self.openLyrics = OpenLyrics(self.plugin.manager)
self.singleServiceItem = False
self.song_maintenance_form = SongMaintenanceForm(
self.parent.manager, self)
self.plugin.manager, self)
# Holds information about whether the edit is remotly triggered and
# which Song is required.
self.remoteSong = -1
@ -178,34 +181,35 @@ class SongMediaItem(MediaManagerItem):
self.displayResultsSong(search_results)
elif search_type == SongSearch.Titles:
log.debug(u'Titles Search')
search_results = self.parent.manager.get_all_objects(Song,
Song.search_title.like(u'%' + self.whitespace.sub(u' ',
search_keywords.lower()) + u'%'))
search_results = self.plugin.manager.get_all_objects(Song,
Song.search_title.like(u'%' + clean_string(search_keywords) +
u'%'))
self.displayResultsSong(search_results)
elif search_type == SongSearch.Lyrics:
log.debug(u'Lyrics Search')
search_results = self.parent.manager.get_all_objects(Song,
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'))
search_results = self.plugin.manager.get_all_objects(Song,
Song.search_lyrics.like(u'%' + clean_string(search_keywords) +
u'%'))
self.displayResultsSong(search_results)
elif search_type == SongSearch.Authors:
log.debug(u'Authors Search')
search_results = self.parent.manager.get_all_objects(Author,
search_results = self.plugin.manager.get_all_objects(Author,
Author.display_name.like(u'%' + search_keywords + u'%'),
Author.display_name.asc())
self.displayResultsAuthor(search_results)
elif search_type == SongSearch.Themes:
log.debug(u'Theme Search')
search_results = self.parent.manager.get_all_objects(Song,
Song.theme_name.like(u'%' + self.whitespace.sub(u' ',
search_keywords) + u'%'))
search_results = self.plugin.manager.get_all_objects(Song,
Song.theme_name.like(u'%' + search_keywords + u'%'))
self.displayResultsSong(search_results)
self.check_search_result()
def searchEntire(self, search_keywords):
return self.parent.manager.get_all_objects(Song,
or_(Song.search_title.like(u'%' + self.whitespace.sub(u' ',
search_keywords.lower()) + u'%'),
Song.search_lyrics.like(u'%' + search_keywords.lower() + u'%'),
return self.plugin.manager.get_all_objects(Song,
or_(Song.search_title.like(u'%' + clean_string(search_keywords)
+ u'%'),
Song.search_lyrics.like(u'%' + clean_string(search_keywords)
+ u'%'),
Song.comments.like(u'%' + search_keywords.lower() + u'%')))
def onSongListLoad(self):
@ -225,7 +229,7 @@ class SongMediaItem(MediaManagerItem):
if self.editItem and self.updateServiceOnEdit and \
not self.remoteTriggered:
item = self.buildServiceItem(self.editItem)
self.parent.serviceManager.replaceServiceItem(item)
self.plugin.serviceManager.replaceServiceItem(item)
self.onRemoteEditClear()
self.onSearchTextButtonClick()
log.debug(u'onSongListLoad - finished')
@ -286,18 +290,21 @@ class SongMediaItem(MediaManagerItem):
def onImportClick(self):
if not hasattr(self, u'import_wizard'):
self.import_wizard = SongImportForm(self, self.parent)
self.import_wizard = SongImportForm(self, self.plugin)
if self.import_wizard.exec_() == QtGui.QDialog.Accepted:
Receiver.send_message(u'songs_load_list')
def onExportClick(self):
export_wizard = SongExportForm(self, self.parent)
export_wizard = SongExportForm(self, self.plugin)
export_wizard.exec_()
def onNewClick(self):
log.debug(u'onNewClick')
self.edit_song_form.newSong()
self.edit_song_form.exec_()
self.onClearTextButtonClick()
self.onSelectionChange()
self.auto_select_id = -1
def onSongMaintenanceClick(self):
self.song_maintenance_form.exec_()
@ -316,12 +323,14 @@ class SongMediaItem(MediaManagerItem):
log.debug(u'onRemoteEdit %s' % message)
remote_type, song_id = message.split(u':')
song_id = int(song_id)
valid = self.parent.manager.get_object(Song, song_id)
valid = self.plugin.manager.get_object(Song, song_id)
if valid:
self.remoteSong = song_id
self.remoteTriggered = remote_type
self.edit_song_form.loadSong(song_id, (remote_type == u'P'))
self.edit_song_form.exec_()
self.auto_select_id = -1
self.onSongListLoad()
def onEditClick(self):
"""
@ -333,6 +342,8 @@ class SongMediaItem(MediaManagerItem):
item_id = (self.editItem.data(QtCore.Qt.UserRole)).toInt()[0]
self.edit_song_form.loadSong(item_id, False)
self.edit_song_form.exec_()
self.auto_select_id = -1
self.onSongListLoad()
self.editItem = None
def onDeleteClick(self):
@ -352,7 +363,7 @@ class SongMediaItem(MediaManagerItem):
return
for item in items:
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
self.parent.manager.delete_object(Song, item_id)
self.plugin.manager.delete_object(Song, item_id)
self.onSearchTextButtonClick()
def generateSlideData(self, service_item, item=None, xmlVersion=False):
@ -364,7 +375,7 @@ class SongMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.OnLoadUpdate)
service_item.add_capability(ItemCapabilities.AddIfNewItem)
service_item.add_capability(ItemCapabilities.AllowsVirtualSplit)
song = self.parent.manager.get_object(Song, item_id)
song = self.plugin.manager.get_object(Song, item_id)
service_item.theme = song.theme_name
service_item.edit_id = item_id
if song.lyrics.startswith(u'<?xml version='):
@ -448,12 +459,12 @@ class SongMediaItem(MediaManagerItem):
# that the search title (data_string[u'title']) is probably wrong.
# We add "@" to search title and hope that we do not add any
# duplicate. This should work for songs without alternate title.
search_results = self.parent.manager.get_all_objects(Song,
search_results = self.plugin.manager.get_all_objects(Song,
Song.search_title == (re.compile(r'\W+', re.UNICODE).sub(u' ',
item.data_string[u'title'].strip()) + u'@').strip().lower(),
Song.search_title.asc())
else:
search_results = self.parent.manager.get_all_objects(Song,
search_results = self.plugin.manager.get_all_objects(Song,
Song.search_title == item.data_string[u'title'],
Song.search_title.asc())
author_list = item.data_string[u'authors'].split(u', ')

View File

@ -30,6 +30,7 @@ import os
from PyQt4 import QtCore
from openlp.core.utils import get_uno_command, get_uno_instance
from openlp.core.lib import translate
from songimport import SongImport
log = logging.getLogger(__name__)
@ -39,8 +40,10 @@ if os.name == u'nt':
PAGE_BEFORE = 4
PAGE_AFTER = 5
PAGE_BOTH = 6
NoConnectException = Exception
else:
import uno
from com.sun.star.connection import NoConnectException
from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH
class OooImport(SongImport):
@ -57,7 +60,17 @@ class OooImport(SongImport):
self.process_started = False
def do_import(self):
if not isinstance(self.import_source, list):
return
try:
self.start_ooo()
except NoConnectException as exc:
self.log_error(
self.import_source[0],
translate('SongsPlugin.SongImport',
'Cannot access OpenOffice or LibreOffice'))
log.error(exc)
return
self.import_wizard.progressBar.setMaximum(len(self.import_source))
for filename in self.import_source:
if self.stop_import_flag:
@ -68,6 +81,13 @@ class OooImport(SongImport):
if self.document:
self.process_ooo_document()
self.close_ooo_file()
else:
self.log_error(self.filepath,
translate('SongsPlugin.SongImport',
'Unable to open file'))
else:
self.log_error(self.filepath,
translate('SongsPlugin.SongImport', 'File not found'))
self.close_ooo()
def process_ooo_document(self):
@ -99,13 +119,16 @@ class OooImport(SongImport):
while uno_instance is None and loop < 5:
try:
uno_instance = get_uno_instance(resolver)
except:
except NoConnectException:
log.exception("Failed to resolve uno connection")
self.start_ooo_process()
loop += 1
else:
manager = uno_instance.ServiceManager
self.desktop = manager.createInstanceWithContext(
"com.sun.star.frame.Desktop", uno_instance)
return
raise
def start_ooo_process(self):
try:
@ -145,8 +168,8 @@ class OooImport(SongImport):
else:
self.import_wizard.incrementProgressBar(
u'Processing file ' + filepath, 0)
except:
log.exception("open_ooo_file failed")
except AttributeError:
log.exception("open_ooo_file failed: %s", url)
return
def close_ooo_file(self):

View File

@ -31,21 +31,27 @@
# http://www.oooforum.org/forum/viewtopic.phtml?t=14409
# http://wiki.services.openoffice.org/wiki/Python
import logging
import os
import re
from oooimport import OooImport
log = logging.getLogger(__name__)
if os.name == u'nt':
BOLD = 150.0
ITALIC = 2
from oooimport import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH
RuntimeException = Exception
else:
try:
from com.sun.star.awt.FontWeight import BOLD
from com.sun.star.awt.FontSlant import ITALIC
from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, \
PAGE_BOTH
from com.sun.star.uno import RuntimeException
except ImportError:
pass
@ -86,6 +92,7 @@ class SofImport(OooImport):
"""
self.blanklines = 0
self.new_song()
try:
paragraphs = self.document.getText().createEnumeration()
while paragraphs.hasMoreElements():
if self.stop_import_flag:
@ -93,9 +100,10 @@ class SofImport(OooImport):
paragraph = paragraphs.nextElement()
if paragraph.supportsService("com.sun.star.text.Paragraph"):
self.process_paragraph(paragraph)
if self.song:
self.finish()
self.song = False
except RuntimeException as exc:
log.exception(u'Error processing file: %s', exc)
if not self.finish():
self.log_error(self.filepath)
def process_paragraph(self, paragraph):
"""

View File

@ -514,7 +514,7 @@ class OpenLyrics(object):
``song``
The song object.
"""
song.song_book_id = 0
song.song_book_id = None
song.song_number = u''
if hasattr(properties, u'songbooks'):
for songbook in properties.songbooks.songbook:

View File

@ -62,44 +62,44 @@ class SongUsagePlugin(Plugin):
"""
log.info(u'add tools menu')
self.toolsMenu = tools_menu
self.SongUsageMenu = QtGui.QMenu(tools_menu)
self.SongUsageMenu.setObjectName(u'SongUsageMenu')
self.SongUsageMenu.setTitle(translate(
self.songUsageMenu = QtGui.QMenu(tools_menu)
self.songUsageMenu.setObjectName(u'songUsageMenu')
self.songUsageMenu.setTitle(translate(
'SongUsagePlugin', '&Song Usage Tracking'))
# SongUsage Delete
self.SongUsageDelete = base_action(tools_menu, u'SongUsageDelete')
self.SongUsageDelete.setText(translate('SongUsagePlugin',
self.songUsageDelete = base_action(tools_menu, u'songUsageDelete')
self.songUsageDelete.setText(translate('SongUsagePlugin',
'&Delete Tracking Data'))
self.SongUsageDelete.setStatusTip(translate('SongUsagePlugin',
self.songUsageDelete.setStatusTip(translate('SongUsagePlugin',
'Delete song usage data up to a specified date.'))
# SongUsage Report
self.SongUsageReport = base_action(tools_menu, u'SongUsageReport')
self.SongUsageReport.setText(
self.songUsageReport = base_action(tools_menu, u'songUsageReport')
self.songUsageReport.setText(
translate('SongUsagePlugin', '&Extract Tracking Data'))
self.SongUsageReport.setStatusTip(
self.songUsageReport.setStatusTip(
translate('SongUsagePlugin', 'Generate a report on song usage.'))
# SongUsage activation
self.SongUsageStatus = shortcut_action(tools_menu, u'SongUsageStatus',
self.songUsageStatus = shortcut_action(tools_menu, u'songUsageStatus',
[QtCore.Qt.Key_F4], self.toggleSongUsageState, checked=False)
self.SongUsageStatus.setText(translate(
self.songUsageStatus.setText(translate(
'SongUsagePlugin', 'Toggle Tracking'))
self.SongUsageStatus.setStatusTip(translate('SongUsagePlugin',
self.songUsageStatus.setStatusTip(translate('SongUsagePlugin',
'Toggle the tracking of song usage.'))
#Add Menus together
self.toolsMenu.addAction(self.SongUsageMenu.menuAction())
self.SongUsageMenu.addAction(self.SongUsageStatus)
self.SongUsageMenu.addSeparator()
self.SongUsageMenu.addAction(self.SongUsageDelete)
self.SongUsageMenu.addAction(self.SongUsageReport)
self.toolsMenu.addAction(self.songUsageMenu.menuAction())
self.songUsageMenu.addAction(self.songUsageStatus)
self.songUsageMenu.addSeparator()
self.songUsageMenu.addAction(self.songUsageDelete)
self.songUsageMenu.addAction(self.songUsageReport)
# Signals and slots
QtCore.QObject.connect(self.SongUsageStatus,
QtCore.QObject.connect(self.songUsageStatus,
QtCore.SIGNAL(u'visibilityChanged(bool)'),
self.SongUsageStatus.setChecked)
QtCore.QObject.connect(self.SongUsageDelete,
self.songUsageStatus.setChecked)
QtCore.QObject.connect(self.songUsageDelete,
QtCore.SIGNAL(u'triggered()'), self.onSongUsageDelete)
QtCore.QObject.connect(self.SongUsageReport,
QtCore.QObject.connect(self.songUsageReport,
QtCore.SIGNAL(u'triggered()'), self.onSongUsageReport)
self.SongUsageMenu.menuAction().setVisible(False)
self.songUsageMenu.menuAction().setVisible(False)
def initialise(self):
log.info(u'SongUsage Initialising')
@ -110,20 +110,20 @@ class SongUsagePlugin(Plugin):
self.SongUsageActive = QtCore.QSettings().value(
self.settingsSection + u'/active',
QtCore.QVariant(False)).toBool()
self.SongUsageStatus.setChecked(self.SongUsageActive)
self.songUsageStatus.setChecked(self.SongUsageActive)
action_list = ActionList.get_instance()
action_list.add_action(self.SongUsageDelete,
action_list.add_action(self.songUsageDelete,
translate('SongUsagePlugin', 'Song Usage'))
action_list.add_action(self.SongUsageReport,
action_list.add_action(self.songUsageReport,
translate('SongUsagePlugin', 'Song Usage'))
action_list.add_action(self.SongUsageStatus,
action_list.add_action(self.songUsageStatus,
translate('SongUsagePlugin', 'Song Usage'))
if self.manager is None:
self.manager = Manager(u'songusage', init_schema)
self.SongUsagedeleteform = SongUsageDeleteForm(self.manager,
self.songUsageDeleteForm = SongUsageDeleteForm(self.manager,
self.formparent)
self.SongUsagedetailform = SongUsageDetailForm(self, self.formparent)
self.SongUsageMenu.menuAction().setVisible(True)
self.songUsageDetailForm = SongUsageDetailForm(self, self.formparent)
self.songUsageMenu.menuAction().setVisible(True)
def finalise(self):
"""
@ -132,13 +132,13 @@ class SongUsagePlugin(Plugin):
log.info(u'Plugin Finalise')
self.manager.finalise()
Plugin.finalise(self)
self.SongUsageMenu.menuAction().setVisible(False)
self.songUsageMenu.menuAction().setVisible(False)
action_list = ActionList.get_instance()
action_list.remove_action(self.SongUsageDelete,
action_list.remove_action(self.songUsageDelete,
translate('SongUsagePlugin', 'Song Usage'))
action_list.remove_action(self.SongUsageReport,
action_list.remove_action(self.songUsageReport,
translate('SongUsagePlugin', 'Song Usage'))
action_list.remove_action(self.SongUsageStatus,
action_list.remove_action(self.songUsageStatus,
translate('SongUsagePlugin', 'Song Usage'))
#stop any events being processed
self.SongUsageActive = False
@ -160,17 +160,15 @@ class SongUsagePlugin(Plugin):
song_usage_item.title = audit[0]
song_usage_item.copyright = audit[2]
song_usage_item.ccl_number = audit[3]
song_usage_item.authors = u''
for author in audit[1]:
song_usage_item.authors += author + u' '
song_usage_item.authors = u' '.join(audit[1])
self.manager.save_object(song_usage_item)
def onSongUsageDelete(self):
self.SongUsagedeleteform.exec_()
self.songUsageDeleteForm.exec_()
def onSongUsageReport(self):
self.SongUsagedetailform.initialise()
self.SongUsagedetailform.exec_()
self.songUsageDetailForm.initialise()
self.songUsageDetailForm.exec_()
def about(self):
about_text = translate('SongUsagePlugin', '<strong>SongUsage Plugin'

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

View File

@ -24,6 +24,7 @@
<qresource prefix="bibles">
<file>bibles_search_text.png</file>
<file>bibles_search_reference.png</file>
<file>bibles_upgrade_alert.png</file>
<file>bibles_search_unlock.png</file>
<file>bibles_search_lock.png</file>
</qresource>

View File

@ -2,7 +2,6 @@
Categories=AudioVideo;
Comment[de]=
Comment=
Encoding=UTF-8
Exec=openlp %F
GenericName[de]=Church lyrics projection
GenericName=Church lyrics projection
@ -13,7 +12,6 @@ Name=OpenLP
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=

View File

@ -102,6 +102,13 @@ psvince.dll
the install will fail. The dll can be obtained from here:
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
@ -194,7 +201,8 @@ def write_version_file():
code = bzr.wait()
if code != 0:
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)
f = open(os.path.join(dist_path, u'.version'), u'w')
f.write(versionstring)