forked from openlp/openlp
r1615
This commit is contained in:
commit
221b64a272
7
documentation/manual.txt
Normal file
7
documentation/manual.txt
Normal 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.
|
@ -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_()
|
||||
|
||||
|
@ -32,8 +32,9 @@ import os
|
||||
|
||||
from PyQt4 import QtCore
|
||||
from sqlalchemy import create_engine, MetaData
|
||||
from sqlalchemy.exceptions import InvalidRequestError
|
||||
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))
|
||||
|
@ -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:
|
||||
|
@ -90,11 +90,10 @@ 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
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
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()
|
||||
@ -112,13 +111,10 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
self.requiredIcons()
|
||||
self.setupUi()
|
||||
self.retranslateUi()
|
||||
self.autoSelectItem = None
|
||||
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)
|
||||
QtCore.QObject.connect(Receiver.get_receiver(),
|
||||
QtCore.SIGNAL(u'%s_set_autoselect_item' % self.parent.name.lower()),
|
||||
self.setAutoSelectItem)
|
||||
|
||||
def requiredIcons(self):
|
||||
"""
|
||||
@ -458,7 +454,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):
|
||||
@ -475,13 +472,10 @@ 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()
|
||||
|
||||
def setAutoSelectItem(self, itemToSelect=None):
|
||||
self.autoSelectItem = itemToSelect
|
||||
|
||||
def onLiveClick(self):
|
||||
"""
|
||||
Send an item live by building a service item then adding that service
|
||||
@ -503,7 +497,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()
|
||||
@ -533,7 +527,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):
|
||||
@ -546,14 +540,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
|
||||
@ -567,8 +561,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:
|
||||
@ -617,6 +611,16 @@ class MediaManagerItem(QtGui.QWidget):
|
||||
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
return item_id
|
||||
|
||||
def save_auto_select_id(self):
|
||||
"""
|
||||
Sorts out, what item to select after loading a list.
|
||||
"""
|
||||
# The item to select has not been set.
|
||||
if self.auto_select_id == -1:
|
||||
item = self.listView.currentItem()
|
||||
if item:
|
||||
self.auto_select_id = item.data(QtCore.Qt.UserRole).toInt()[0]
|
||||
|
||||
def search(self, string):
|
||||
"""
|
||||
Performs a plugin specific search for items containing ``string``
|
||||
|
@ -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.
|
||||
|
@ -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,7 @@ class Renderer(object):
|
||||
"""
|
||||
log.debug(u'Update Display')
|
||||
self._calculate_default(self.screens.current[u'size'])
|
||||
self.display = MainDisplay(self, self.image_manager, False)
|
||||
self.display = MainDisplay(None, self.image_manager, False)
|
||||
self.display.setup()
|
||||
self.bg_frame = None
|
||||
self.theme_data = None
|
||||
|
@ -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''))
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -223,9 +223,9 @@ class GeneralTab(SettingsTab):
|
||||
self.autoPreviewCheckBox.setText(translate('OpenLP.GeneralTab',
|
||||
'Automatically preview next item in service'))
|
||||
self.enableLoopCheckBox.setText(translate('OpenLP.GeneralTab',
|
||||
'Enable slide loop'))
|
||||
'Enable slide wrap-around'))
|
||||
self.timeoutLabel.setText(translate('OpenLP.GeneralTab',
|
||||
'Slide loop delay:'))
|
||||
'Timed slide interval:'))
|
||||
self.timeoutSpinBox.setSuffix(translate('OpenLP.GeneralTab', ' sec'))
|
||||
self.ccliGroupBox.setTitle(
|
||||
translate('OpenLP.GeneralTab', 'CCLI Details'))
|
||||
|
@ -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()
|
||||
@ -149,7 +148,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
|
||||
|
@ -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)
|
||||
@ -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',
|
||||
|
@ -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(
|
||||
|
@ -56,7 +56,9 @@ http://doc.trolltech.com/4.7/richtext-html-subset.html#css-properties
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.itemText {}
|
||||
.itemText {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.itemFooter {
|
||||
font-size: 8px;
|
||||
@ -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():
|
||||
|
@ -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' % number)
|
||||
# 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()
|
||||
|
@ -676,8 +676,18 @@ class ServiceManager(QtGui.QWidget):
|
||||
.is_capable(ItemCapabilities.AllowsVariableStartTime):
|
||||
self.timeAction.setVisible(True)
|
||||
self.themeMenu.menuAction().setVisible(False)
|
||||
if serviceItem[u'service_item'].is_text():
|
||||
# Set up the theme menu.
|
||||
if serviceItem[u'service_item'].is_text() and \
|
||||
self.mainwindow.renderer.theme_level == ThemeLevel.Song:
|
||||
self.themeMenu.menuAction().setVisible(True)
|
||||
# The service item does not have a theme, check the "Default".
|
||||
if serviceItem[u'service_item'].theme is None:
|
||||
themeAction = self.themeMenu.defaultAction()
|
||||
else:
|
||||
themeAction = self.themeMenu.findChild(
|
||||
QtGui.QAction, serviceItem[u'service_item'].theme)
|
||||
if themeAction is not None:
|
||||
themeAction.setChecked(True)
|
||||
action = self.menu.exec_(self.serviceManagerList.mapToGlobal(point))
|
||||
|
||||
def onServiceItemNoteForm(self):
|
||||
@ -949,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)
|
||||
@ -1020,16 +1031,34 @@ 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)
|
||||
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):
|
||||
@ -1059,7 +1088,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
|
||||
|
||||
@ -1087,17 +1116,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:
|
||||
@ -1280,16 +1309,33 @@ class ServiceManager(QtGui.QWidget):
|
||||
self.themeComboBox.clear()
|
||||
self.themeMenu.clear()
|
||||
self.themeComboBox.addItem(u'')
|
||||
themeGroup = QtGui.QActionGroup(self.themeMenu)
|
||||
themeGroup.setExclusive(True)
|
||||
themeGroup.setObjectName(u'themeGroup')
|
||||
# Create a "Default" theme, which allows the user to reset the item's
|
||||
# theme to the service theme or global theme.
|
||||
defaultTheme = context_menu_action(self.themeMenu, None,
|
||||
UiStrings().Default, self.onThemeChangeAction)
|
||||
defaultTheme.setCheckable(True)
|
||||
self.themeMenu.setDefaultAction(defaultTheme)
|
||||
themeGroup.addAction(defaultTheme)
|
||||
context_menu_separator(self.themeMenu)
|
||||
for theme in theme_list:
|
||||
self.themeComboBox.addItem(theme)
|
||||
context_menu_action(self.themeMenu, None, theme,
|
||||
themeAction = context_menu_action(self.themeMenu, None, theme,
|
||||
self.onThemeChangeAction)
|
||||
themeAction.setObjectName(theme)
|
||||
themeAction.setCheckable(True)
|
||||
themeGroup.addAction(themeAction)
|
||||
find_and_set_in_combo_box(self.themeComboBox, self.service_theme)
|
||||
self.mainwindow.renderer.set_service_theme(self.service_theme)
|
||||
self.regenerateServiceItems()
|
||||
|
||||
def onThemeChangeAction(self):
|
||||
theme = unicode(self.sender().text())
|
||||
theme = unicode(self.sender().objectName())
|
||||
# No object name means that the "Default" theme is supposed to be used.
|
||||
if not theme:
|
||||
theme = None
|
||||
item = self.findServiceItem()[0]
|
||||
self.serviceItems[item][u'service_item'].theme = theme
|
||||
self.regenerateServiceItems()
|
||||
|
@ -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,12 @@ class SlideController(QtGui.QWidget):
|
||||
"""
|
||||
QtGui.QWidget.__init__(self, parent)
|
||||
self.isLive = isLive
|
||||
self.parent = parent
|
||||
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'
|
||||
]
|
||||
@ -140,19 +138,20 @@ class SlideController(QtGui.QWidget):
|
||||
self.previousItem = self.toolbar.addToolbarButton(
|
||||
translate('OpenLP.SlideController', 'Previous Slide'),
|
||||
u':/slides/slide_previous.png',
|
||||
translate('OpenLP.SlideController', 'Move to previous'),
|
||||
translate('OpenLP.SlideController', 'Move to previous.'),
|
||||
self.onSlideSelectedPrevious,
|
||||
shortcuts=[QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp],
|
||||
context=QtCore.Qt.WidgetWithChildrenShortcut)
|
||||
self.nextItem = self.toolbar.addToolbarButton(
|
||||
translate('OpenLP.SlideController', 'Next Slide'),
|
||||
u':/slides/slide_next.png',
|
||||
translate('OpenLP.SlideController', 'Move to next'),
|
||||
translate('OpenLP.SlideController', 'Move to next.'),
|
||||
self.onSlideSelectedNext,
|
||||
shortcuts=[QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown],
|
||||
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,65 +179,72 @@ 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', 'Start continuous loop'),
|
||||
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 continuous loop'),
|
||||
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)
|
||||
self.delaySpinBox.setSuffix(UiStrings().Seconds)
|
||||
self.delaySpinBox.setToolTip(translate('OpenLP.SlideController',
|
||||
'Delay between slides in seconds'))
|
||||
'Delay between slides in seconds.'))
|
||||
else:
|
||||
self.toolbar.addToolbarButton(
|
||||
# Does not need translating - control string.
|
||||
u'Go Live', u':/general/general_live.png',
|
||||
translate('OpenLP.SlideController', 'Move to live'),
|
||||
translate('OpenLP.SlideController', 'Move to live.'),
|
||||
self.onGoLive)
|
||||
self.toolbar.addToolbarButton(
|
||||
# Does not need translating - control string.
|
||||
u'Add to Service', u':/general/general_add.png',
|
||||
translate('OpenLP.SlideController', 'Add to Service'),
|
||||
translate('OpenLP.SlideController', 'Add to Service.'),
|
||||
self.onPreviewAddToService)
|
||||
self.toolbar.addToolbarSeparator(u'Close Separator')
|
||||
self.toolbar.addToolbarButton(
|
||||
# Does not need translating - control string.
|
||||
u'Edit Song', u':/general/general_edit.png',
|
||||
translate('OpenLP.SlideController',
|
||||
'Edit and reload song preview'),
|
||||
'Edit and reload song preview.'),
|
||||
self.onEditSong)
|
||||
self.controllerLayout.addWidget(self.toolbar)
|
||||
# Build a Media ToolBar
|
||||
self.mediabar = OpenLPToolbar(self)
|
||||
self.mediabar.addToolbarButton(
|
||||
u'Media Start', u':/slides/media_playback_start.png',
|
||||
translate('OpenLP.SlideController', 'Start playing media'),
|
||||
translate('OpenLP.SlideController', 'Start playing media.'),
|
||||
self.onMediaPlay)
|
||||
self.mediabar.addToolbarButton(
|
||||
u'Media Pause', u':/slides/media_playback_pause.png',
|
||||
translate('OpenLP.SlideController', 'Start playing media'),
|
||||
translate('OpenLP.SlideController', 'Start playing media.'),
|
||||
self.onMediaPause)
|
||||
self.mediabar.addToolbarButton(
|
||||
u'Media Stop', u':/slides/media_playback_stop.png',
|
||||
translate('OpenLP.SlideController', 'Start playing media'),
|
||||
translate('OpenLP.SlideController', 'Start playing media.'),
|
||||
self.onMediaStop)
|
||||
if self.isLive:
|
||||
# Build the Song Toolbar
|
||||
@ -321,7 +327,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)'),
|
||||
@ -461,7 +466,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 +501,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 +589,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 +623,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 +633,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 +734,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 +742,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 +772,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 +793,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 +814,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()
|
||||
|
||||
@ -841,6 +841,11 @@ class SlideController(QtGui.QWidget):
|
||||
Receiver.send_message(u'%s_unblank'
|
||||
% self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
else:
|
||||
if hide_mode:
|
||||
Receiver.send_message(u'maindisplay_hide', hide_mode)
|
||||
else:
|
||||
Receiver.send_message(u'maindisplay_show')
|
||||
|
||||
def hidePlugin(self, hide):
|
||||
"""
|
||||
@ -859,6 +864,11 @@ class SlideController(QtGui.QWidget):
|
||||
Receiver.send_message(u'%s_unblank'
|
||||
% self.serviceItem.name.lower(),
|
||||
[self.serviceItem, self.isLive])
|
||||
else:
|
||||
if hide:
|
||||
Receiver.send_message(u'maindisplay_hide', HideMode.Screen)
|
||||
else:
|
||||
Receiver.send_message(u'maindisplay_show')
|
||||
|
||||
def onSlideSelected(self, start=False):
|
||||
"""
|
||||
@ -933,7 +943,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.
|
||||
"""
|
||||
@ -946,8 +956,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
|
||||
@ -967,8 +980,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
|
||||
@ -996,11 +1009,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()
|
||||
@ -1012,8 +1025,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):
|
||||
"""
|
||||
@ -1022,15 +1033,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):
|
||||
"""
|
||||
@ -1044,7 +1079,9 @@ class SlideController(QtGui.QWidget):
|
||||
"""
|
||||
From the preview display request the Item to be added to service
|
||||
"""
|
||||
self.parent.serviceManagerContents.addServiceItem(self.serviceItem)
|
||||
if self.serviceItem:
|
||||
self.parent().serviceManagerContents.addServiceItem(
|
||||
self.serviceItem)
|
||||
|
||||
def onGoLiveClick(self):
|
||||
"""
|
||||
@ -1072,7 +1109,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):
|
||||
|
@ -57,8 +57,6 @@ class ThemeManager(QtGui.QWidget):
|
||||
self.settingsSection = u'themes'
|
||||
self.themeForm = ThemeForm(self)
|
||||
self.fileRenameForm = FileRenameForm(self)
|
||||
self.serviceComboBox = \
|
||||
self.mainwindow.serviceManagerContents.themeComboBox
|
||||
# start with the layout
|
||||
self.layout = QtGui.QVBoxLayout(self)
|
||||
self.layout.setSpacing(0)
|
||||
|
@ -145,10 +145,8 @@ class ThemesTab(SettingsTab):
|
||||
def save(self):
|
||||
settings = QtCore.QSettings()
|
||||
settings.beginGroup(self.settingsSection)
|
||||
settings.setValue(u'theme level',
|
||||
QtCore.QVariant(self.theme_level))
|
||||
settings.setValue(u'global theme',
|
||||
QtCore.QVariant(self.global_theme))
|
||||
settings.setValue(u'theme level', QtCore.QVariant(self.theme_level))
|
||||
settings.setValue(u'global theme', QtCore.QVariant(self.global_theme))
|
||||
settings.endGroup()
|
||||
self.mainwindow.renderer.set_global_theme(
|
||||
self.global_theme, self.theme_level)
|
||||
@ -186,8 +184,7 @@ class ThemesTab(SettingsTab):
|
||||
self.settingsSection + u'/global theme',
|
||||
QtCore.QVariant(u'')).toString())
|
||||
self.DefaultComboBox.clear()
|
||||
for theme in theme_list:
|
||||
self.DefaultComboBox.addItem(theme)
|
||||
self.DefaultComboBox.addItems(theme_list)
|
||||
find_and_set_in_combo_box(self.DefaultComboBox, self.global_theme)
|
||||
self.mainwindow.renderer.set_global_theme(
|
||||
self.global_theme, self.theme_level)
|
||||
|
@ -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 = {}
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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']
|
||||
|
@ -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()
|
||||
|
785
openlp/plugins/bibles/forms/bibleupgradeform.py
Normal file
785
openlp/plugins/bibles/forms/bibleupgradeform.py
Normal file
@ -0,0 +1,785 @@
|
||||
# -*- 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)
|
||||
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)
|
114
openlp/plugins/bibles/forms/booknamedialog.py
Normal file
114
openlp/plugins/bibles/forms/booknamedialog.py
Normal 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'))
|
123
openlp/plugins/bibles/forms/booknameform.py
Normal file
123
openlp/plugins/bibles/forms/booknameform.py
Normal 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)
|
84
openlp/plugins/bibles/forms/languagedialog.py
Normal file
84
openlp/plugins/bibles/forms/languagedialog.py
Normal 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:'))
|
72
openlp/plugins/bibles/forms/languageform.py
Normal file
72
openlp/plugins/bibles/forms/languageform.py
Normal 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)
|
@ -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):
|
||||
|
@ -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,9 +459,9 @@ 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(Book.book_reference_id==book_id)\
|
||||
.filter(Verse.chapter==chapter)\
|
||||
.count()
|
||||
if not count:
|
||||
@ -430,6 +469,39 @@ class BibleDB(QtCore.QObject, Manager):
|
||||
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,591 @@ 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
|
||||
|
@ -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(' |<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):
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
@ -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)
|
||||
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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
GOD’S 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
|
||||
Today’s 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
|
|
BIN
openlp/plugins/bibles/resources/bibles_resources.sqlite
Normal file
BIN
openlp/plugins/bibles/resources/bibles_resources.sqlite
Normal file
Binary file not shown.
@ -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,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
|
|
Binary file not shown.
@ -27,8 +27,6 @@
|
||||
|
||||
import logging
|
||||
|
||||
from forms import EditCustomForm
|
||||
|
||||
from openlp.core.lib import Plugin, StringContent, build_icon, translate
|
||||
from openlp.core.lib.db import Manager
|
||||
from openlp.plugins.custom.lib import CustomMediaItem, CustomTab
|
||||
@ -52,7 +50,6 @@ class CustomPlugin(Plugin):
|
||||
CustomMediaItem, CustomTab)
|
||||
self.weight = -5
|
||||
self.manager = Manager(u'custom', init_schema)
|
||||
self.edit_custom_form = EditCustomForm(self)
|
||||
self.icon_path = u':/plugins/plugin_custom.png'
|
||||
self.icon = build_icon(self.icon_path)
|
||||
|
||||
|
@ -43,13 +43,13 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
Class documentation goes here.
|
||||
"""
|
||||
log.info(u'Custom Editor loaded')
|
||||
def __init__(self, parent):
|
||||
def __init__(self, mediaitem, parent, manager):
|
||||
"""
|
||||
Constructor
|
||||
"""
|
||||
QtGui.QDialog.__init__(self)
|
||||
self.parent = parent
|
||||
self.manager = self.parent.manager
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.manager = manager
|
||||
self.mediaitem = mediaitem
|
||||
self.setupUi(self)
|
||||
# Create other objects and forms.
|
||||
self.editSlideForm = EditCustomSlideForm(self)
|
||||
@ -115,9 +115,6 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
def accept(self):
|
||||
log.debug(u'accept')
|
||||
if self.saveCustom():
|
||||
Receiver.send_message(u'custom_set_autoselect_item',
|
||||
self.customSlide.title)
|
||||
Receiver.send_message(u'custom_load_list')
|
||||
QtGui.QDialog.accept(self)
|
||||
|
||||
def saveCustom(self):
|
||||
@ -138,7 +135,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog):
|
||||
self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8')
|
||||
self.customSlide.credits = unicode(self.creditEdit.text())
|
||||
self.customSlide.theme_name = unicode(self.themeComboBox.currentText())
|
||||
return self.manager.save_object(self.customSlide)
|
||||
success = self.manager.save_object(self.customSlide)
|
||||
self.mediaitem.auto_select_id = self.customSlide.id
|
||||
return success
|
||||
|
||||
def onUpButtonClicked(self):
|
||||
selectedRow = self.slideListView.currentRow()
|
||||
|
@ -35,6 +35,7 @@ from openlp.core.lib import MediaManagerItem, Receiver, ItemCapabilities, \
|
||||
check_item_selected, translate
|
||||
from openlp.core.lib.searchedit import SearchEdit
|
||||
from openlp.core.lib.ui import UiStrings
|
||||
from openlp.plugins.custom.forms import EditCustomForm
|
||||
from openlp.plugins.custom.lib import CustomXMLParser
|
||||
from openlp.plugins.custom.lib.db import CustomSlide
|
||||
|
||||
@ -56,14 +57,16 @@ class CustomMediaItem(MediaManagerItem):
|
||||
|
||||
def __init__(self, parent, plugin, icon):
|
||||
self.IconPath = u'custom/custom'
|
||||
MediaManagerItem.__init__(self, parent, self, icon)
|
||||
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()
|
||||
@ -106,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)
|
||||
|
||||
@ -126,16 +129,10 @@ 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.
|
||||
self.save_auto_select_id()
|
||||
self.listView.clear()
|
||||
# Sort the customs by its title considering language specific
|
||||
# characters. lower() is needed for windows!
|
||||
@ -146,33 +143,45 @@ class CustomMediaItem(MediaManagerItem):
|
||||
custom_name.setData(
|
||||
QtCore.Qt.UserRole, QtCore.QVariant(custom_slide.id))
|
||||
self.listView.addItem(custom_name)
|
||||
# Auto-select the item if name has been set
|
||||
if custom_slide.title == self.autoSelectItem:
|
||||
# Auto-select the custom.
|
||||
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.parent.edit_custom_form.loadCustom(0)
|
||||
self.parent.edit_custom_form.exec_()
|
||||
self.initialise()
|
||||
self.edit_custom_form.loadCustom(0)
|
||||
self.edit_custom_form.exec_()
|
||||
self.onClearTextButtonClick()
|
||||
self.onSelectionChange()
|
||||
|
||||
def onRemoteEditClear(self):
|
||||
self.remoteTriggered = None
|
||||
self.remoteCustom = -1
|
||||
|
||||
def onRemoteEdit(self, customid):
|
||||
def onRemoteEdit(self, message):
|
||||
"""
|
||||
Called by ServiceManager or SlideController by event passing
|
||||
the Song Id in the payload along with an indicator to say which
|
||||
the custom Id in the payload along with an indicator to say which
|
||||
type of display is required.
|
||||
"""
|
||||
fields = customid.split(u':')
|
||||
valid = self.manager.get_object(CustomSlide, fields[1])
|
||||
remote_type, custom_id = message.split(u':')
|
||||
custom_id = int(custom_id)
|
||||
valid = self.manager.get_object(CustomSlide, custom_id)
|
||||
if valid:
|
||||
self.remoteCustom = fields[1]
|
||||
self.remoteTriggered = fields[0]
|
||||
self.parent.edit_custom_form.loadCustom(fields[1],
|
||||
(fields[0] == u'P'))
|
||||
self.parent.edit_custom_form.exec_()
|
||||
self.remoteCustom = custom_id
|
||||
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):
|
||||
"""
|
||||
@ -181,9 +190,10 @@ class CustomMediaItem(MediaManagerItem):
|
||||
if check_item_selected(self.listView, UiStrings().SelectEdit):
|
||||
item = self.listView.currentItem()
|
||||
item_id = (item.data(QtCore.Qt.UserRole)).toInt()[0]
|
||||
self.parent.edit_custom_form.loadCustom(item_id, False)
|
||||
self.parent.edit_custom_form.exec_()
|
||||
self.initialise()
|
||||
self.edit_custom_form.loadCustom(item_id, False)
|
||||
self.edit_custom_form.exec_()
|
||||
self.auto_select_id = -1
|
||||
self.onSearchTextButtonClick()
|
||||
|
||||
def onDeleteClick(self):
|
||||
"""
|
||||
@ -195,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)
|
||||
|
||||
@ -203,7 +213,6 @@ class CustomMediaItem(MediaManagerItem):
|
||||
self.searchTextEdit.setFocus()
|
||||
|
||||
def generateSlideData(self, service_item, item=None, xmlVersion=False):
|
||||
raw_slides = []
|
||||
raw_footer = []
|
||||
slide = None
|
||||
theme = None
|
||||
@ -212,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
|
||||
@ -221,8 +230,7 @@ class CustomMediaItem(MediaManagerItem):
|
||||
service_item.theme = theme
|
||||
customXML = CustomXMLParser(customSlide.text)
|
||||
verseList = customXML.get_verses()
|
||||
for verse in verseList:
|
||||
raw_slides.append(verse[1])
|
||||
raw_slides = [verse[1] for verse in verseList]
|
||||
service_item.title = title
|
||||
for slide in raw_slides:
|
||||
service_item.add_from_text(slide[:30], slide)
|
||||
@ -245,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)
|
||||
@ -260,7 +268,7 @@ class CustomMediaItem(MediaManagerItem):
|
||||
def onSearchTextEditChanged(self, text):
|
||||
"""
|
||||
If search as type enabled invoke the search on each key press.
|
||||
If the Title is being searched do not start till 2 characters
|
||||
If the Title is being searched do not start until 2 characters
|
||||
have been entered.
|
||||
"""
|
||||
search_length = 2
|
||||
@ -283,8 +291,5 @@ class CustomMediaItem(MediaManagerItem):
|
||||
func.lower(CustomSlide.text).like(u'%' +
|
||||
string.lower() + u'%')),
|
||||
order_by_ref=CustomSlide.title)
|
||||
results = []
|
||||
for custom in search_results:
|
||||
results.append([custom.id, custom.title])
|
||||
return results
|
||||
return [[custom.id, custom.title] for custom in search_results]
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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:
|
||||
|
@ -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
0
openlp/plugins/remotes/html/json2.js
Executable file → Normal 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 });
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
@ -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,7 +506,7 @@ 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)
|
||||
@ -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)
|
||||
|
@ -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,9 +696,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
|
||||
self.clearCaches()
|
||||
if self._validate_song():
|
||||
self.saveSong()
|
||||
Receiver.send_message(u'songs_set_autoselect_item',
|
||||
unicode(self.titleEdit.text()))
|
||||
Receiver.send_message(u'songs_load_list')
|
||||
self.song = None
|
||||
QtGui.QDialog.accept(self)
|
||||
|
||||
def saveSong(self, preview=False):
|
||||
@ -756,8 +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)
|
||||
if not preview:
|
||||
self.song = None
|
||||
self.mediaitem.auto_select_id = self.song.id
|
||||
|
||||
def _processLyrics(self):
|
||||
"""
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
@ -197,13 +197,13 @@ def init_schema(url):
|
||||
Column(u'song_number', types.Unicode(64)),
|
||||
Column(u'theme_name', types.Unicode(128)),
|
||||
Column(u'search_title', types.Unicode(255), index=True, nullable=False),
|
||||
Column(u'search_lyrics', types.UnicodeText, index=True, nullable=False)
|
||||
Column(u'search_lyrics', types.UnicodeText, nullable=False)
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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,13 +229,14 @@ 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')
|
||||
|
||||
def displayResultsSong(self, searchresults):
|
||||
log.debug(u'display results Song')
|
||||
self.save_auto_select_id()
|
||||
self.listView.clear()
|
||||
# Sort the songs by its title considering language specific characters.
|
||||
# lower() is needed for windows!
|
||||
@ -245,8 +250,9 @@ class SongMediaItem(MediaManagerItem):
|
||||
song_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(song.id))
|
||||
self.listView.addItem(song_name)
|
||||
# Auto-select the item if name has been set
|
||||
if song.title == self.autoSelectItem :
|
||||
if song.id == self.auto_select_id:
|
||||
self.listView.setCurrentItem(song_name)
|
||||
self.auto_select_id = -1
|
||||
|
||||
def displayResultsAuthor(self, searchresults):
|
||||
log.debug(u'display results Author')
|
||||
@ -284,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_()
|
||||
@ -314,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):
|
||||
"""
|
||||
@ -331,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):
|
||||
@ -350,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):
|
||||
@ -362,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='):
|
||||
@ -446,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', ')
|
||||
@ -487,7 +500,4 @@ class SongMediaItem(MediaManagerItem):
|
||||
Search for some songs
|
||||
"""
|
||||
search_results = self.searchEntire(string)
|
||||
results = []
|
||||
for song in search_results:
|
||||
results.append([song.id, song.title])
|
||||
return results
|
||||
return [[song.id, song.title] for song in search_results]
|
||||
|
@ -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',
|
||||
'Unable to open OpenOffice.org 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):
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -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:
|
||||
|
@ -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'
|
||||
|
BIN
resources/images/bibles_upgrade_alert.png
Normal file
BIN
resources/images/bibles_upgrade_alert.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 762 B |
@ -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>
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user