diff --git a/openlp.pyw b/openlp.pyw index 017e12774..8d20080c9 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -194,7 +194,10 @@ class OpenLP(QtGui.QApplication): # now kill the splashscreen self.splash.finish(self.mainWindow) self.mainWindow.repaint() - VersionThread(self.mainWindow, app_version).start() + update_check = QtCore.QSettings().value( + u'general/update check', QtCore.QVariant(True)).toBool() + if update_check: + VersionThread(self.mainWindow, app_version).start() return self.exec_() def hookException(self, exctype, value, traceback): @@ -280,4 +283,4 @@ if __name__ == u'__main__': """ Instantiate and run the application. """ - main() \ No newline at end of file + main() diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 76d7c0617..33280f83b 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -315,7 +315,7 @@ def check_directory_exists(dir): ``dir`` Theme directory to make sure exists """ - log.debug(u'check_directory_exists') + log.debug(u'check_directory_exists %s' % dir) if not os.path.exists(dir): os.makedirs(dir) diff --git a/openlp/core/lib/htmlbuilder.py b/openlp/core/lib/htmlbuilder.py index 86056f4b5..ea830855c 100644 --- a/openlp/core/lib/htmlbuilder.py +++ b/openlp/core/lib/htmlbuilder.py @@ -314,7 +314,7 @@ body { """ -def build_html(item, screen, alert, islive): +def build_html(item, screen, alert, islive, background): """ Build the full web paged structure for display @@ -332,7 +332,9 @@ def build_html(item, screen, alert, islive): theme = item.themedata webkitvers = webkit_version() # Image generated and poked in - if item.bg_image_bytes: + if background: + image = u'src="data:image/png;base64,%s"' % background + elif item.bg_image_bytes: image = u'src="data:image/png;base64,%s"' % item.bg_image_bytes else: image = u'style="display:none;"' diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 5799a3f41..9565a9b37 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -98,13 +98,9 @@ class MediaManagerItem(QtGui.QWidget): visible_title = self.plugin.getString(StringContent.VisibleName) self.title = unicode(visible_title[u'title']) self.settingsSection = self.plugin.name.lower() - if isinstance(icon, QtGui.QIcon): - self.icon = icon - elif isinstance(icon, basestring): - self.icon.addPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(icon)), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - else: - self.icon = None + self.icon = None + if icon: + self.icon = build_icon(icon) self.toolbar = None self.remoteTriggered = None self.serviceItemIconName = None diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 276563eba..c74b89144 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -59,6 +59,7 @@ class ItemCapabilities(object): OnLoadUpdate = 8 AddIfNewItem = 9 ProvidesOwnDisplay = 10 + AllowsDetailedTitleDisplay = 11 class ServiceItem(object): @@ -314,6 +315,20 @@ class ServiceItem(object): path, text_image[u'title'], text_image[u'image'] ) self._new_item() + def get_display_title(self): + """ + Returns the title of the service item. + """ + if self.is_text(): + return self.title + else: + if ItemCapabilities.AllowsDetailedTitleDisplay in self.capabilities: + return self._raw_frames[0][u'title'] + elif len(self._raw_frames) > 1: + return self.title + else: + return self._raw_frames[0][u'title'] + def merge(self, other): """ Updates the _uuid with the value from the original one diff --git a/openlp/core/lib/spelltextedit.py b/openlp/core/lib/spelltextedit.py index 82391a0b3..44180a25c 100644 --- a/openlp/core/lib/spelltextedit.py +++ b/openlp/core/lib/spelltextedit.py @@ -47,13 +47,16 @@ class SpellTextEdit(QtGui.QPlainTextEdit): # Default dictionary based on the current locale. if ENCHANT_AVAILABLE: try: - self.dict = enchant.Dict() + self.dictionary = enchant.Dict() except DictNotFoundError: - self.dict = enchant.Dict(u'en_US') + self.dictionary = enchant.Dict(u'en_US') self.highlighter = Highlighter(self.document()) - self.highlighter.setDict(self.dict) + self.highlighter.spellingDictionary = self.dictionary def mousePressEvent(self, event): + """ + Handle mouse clicks within the text edit region. + """ if event.button() == QtCore.Qt.RightButton: # Rewrite the mouse event to a left button event so the cursor is # moved to the location of the pointer. @@ -63,6 +66,9 @@ class SpellTextEdit(QtGui.QPlainTextEdit): QtGui.QPlainTextEdit.mousePressEvent(self, event) def contextMenuEvent(self, event): + """ + Provide the context menu for the text edit region. + """ popupMenu = self.createStandardContextMenu() # Select the word under the cursor. cursor = self.textCursor() @@ -74,10 +80,10 @@ class SpellTextEdit(QtGui.QPlainTextEdit): # suggestions if it is. if ENCHANT_AVAILABLE and self.textCursor().hasSelection(): text = unicode(self.textCursor().selectedText()) - if not self.dict.check(text): + if not self.dictionary.check(text): spell_menu = QtGui.QMenu(translate('OpenLP.SpellTextEdit', 'Spelling Suggestions')) - for word in self.dict.suggest(text): + for word in self.dictionary.suggest(text): action = SpellAction(word, spell_menu) action.correct.connect(self.correctWord) spell_menu.addAction(action) @@ -126,28 +132,32 @@ class SpellTextEdit(QtGui.QPlainTextEdit): cursor.insertText(html[u'start tag']) cursor.insertText(html[u'end tag']) -class Highlighter(QtGui.QSyntaxHighlighter): +class Highlighter(QtGui.QSyntaxHighlighter): + """ + Provides a text highlighter for pointing out spelling errors in text. + """ WORDS = u'(?iu)[\w\']+' def __init__(self, *args): QtGui.QSyntaxHighlighter.__init__(self, *args) - self.dict = None - - def setDict(self, dict): - self.dict = dict + self.spellingDictionary = None def highlightBlock(self, text): - if not self.dict: + """ + Highlight misspelt words in a block of text + """ + if not self.spellingDictionary: return text = unicode(text) - format = QtGui.QTextCharFormat() - format.setUnderlineColor(QtCore.Qt.red) - format.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline) + charFormat = QtGui.QTextCharFormat() + charFormat.setUnderlineColor(QtCore.Qt.red) + charFormat.setUnderlineStyle(QtGui.QTextCharFormat.SpellCheckUnderline) for word_object in re.finditer(self.WORDS, text): - if not self.dict.check(word_object.group()): + if not self.spellingDictionary.check(word_object.group()): self.setFormat(word_object.start(), - word_object.end() - word_object.start(), format) + word_object.end() - word_object.start(), charFormat) + class SpellAction(QtGui.QAction): """ diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 773637481..edace883f 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -113,6 +113,9 @@ class GeneralTab(SettingsTab): self.showSplashCheckBox = QtGui.QCheckBox(self.startupGroupBox) self.showSplashCheckBox.setObjectName(u'showSplashCheckBox') self.startupLayout.addWidget(self.showSplashCheckBox) + self.checkForUpdatesCheckBox = QtGui.QCheckBox(self.startupGroupBox) + self.checkForUpdatesCheckBox.setObjectName(u'checkForUpdatesCheckBox') + self.startupLayout.addWidget(self.checkForUpdatesCheckBox) self.leftLayout.addWidget(self.startupGroupBox) self.settingsGroupBox = QtGui.QGroupBox(self.leftColumn) self.settingsGroupBox.setObjectName(u'settingsGroupBox') @@ -249,6 +252,8 @@ class GeneralTab(SettingsTab): 'Automatically open the last service')) self.showSplashCheckBox.setText( translate('OpenLP.GeneralTab', 'Show the splash screen')) + self.checkForUpdatesCheckBox.setText( + translate('OpenLP.GeneralTab', 'Check for updates to OpenLP')) self.settingsGroupBox.setTitle( translate('OpenLP.GeneralTab', 'Application Settings')) self.saveCheckServiceCheckBox.setText(translate('OpenLP.GeneralTab', @@ -317,6 +322,8 @@ class GeneralTab(SettingsTab): QtCore.QVariant(False)).toBool()) self.showSplashCheckBox.setChecked(settings.value(u'show splash', QtCore.QVariant(True)).toBool()) + self.checkForUpdatesCheckBox.setChecked(settings.value(u'update check', + QtCore.QVariant(True)).toBool()) self.autoPreviewCheckBox.setChecked(settings.value(u'auto preview', QtCore.QVariant(False)).toBool()) self.timeoutSpinBox.setValue(settings.value(u'loop delay', @@ -363,6 +370,8 @@ class GeneralTab(SettingsTab): QtCore.QVariant(self.autoOpenCheckBox.isChecked())) settings.setValue(u'show splash', QtCore.QVariant(self.showSplashCheckBox.isChecked())) + settings.setValue(u'update check', + QtCore.QVariant(self.checkForUpdatesCheckBox.isChecked())) settings.setValue(u'save prompt', QtCore.QVariant(self.saveCheckServiceCheckBox.isChecked())) settings.setValue(u'auto preview', diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index b371d951e..3dfde8640 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -67,6 +67,7 @@ class MainDisplay(DisplayWidget): self.isLive = live self.alertTab = None self.hideMode = None + self.override = {} mainIcon = build_icon(u':/icon/openlp-logo-16x16.png') self.setWindowIcon(mainIcon) self.retranslateUi() @@ -111,7 +112,7 @@ class MainDisplay(DisplayWidget): self.page = self.webView.page() self.frame = self.page.mainFrame() QtCore.QObject.connect(self.webView, - QtCore.SIGNAL(u'loadFinished(bool)'), self.isLoaded) + QtCore.SIGNAL(u'loadFinished(bool)'), self.isWebLoaded) self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.frame.setScrollBarPolicy(QtCore.Qt.Vertical, @@ -137,14 +138,14 @@ class MainDisplay(DisplayWidget): painter_image.begin(initialFrame) painter_image.fillRect(initialFrame.rect(), QtCore.Qt.white) painter_image.drawImage( - (self.screens.current[u'size'].width() - + (self.screens.current[u'size'].width() - splash_image.width()) / 2, (self.screens.current[u'size'].height() - splash_image.height()) / 2, splash_image) serviceItem = ServiceItem() serviceItem.bg_image_bytes = image_to_byte(initialFrame) self.webView.setHtml(build_html(serviceItem, self.screen, - self.parent.alertTab, self.isLive)) + self.parent.alertTab, self.isLive, None)) self.initialFrame = True # To display or not to display? if not self.screen[u'primary']: @@ -162,7 +163,7 @@ class MainDisplay(DisplayWidget): """ log.debug(u'text to display') # Wait for the webview to update before displaying text. - while not self.loaded: + while not self.webLoaded: Receiver.send_message(u'openlp_process_events') self.frame.evaluateJavaScript(u'show_text("%s")' % \ slide.replace(u'\\', u'\\\\').replace(u'\"', u'\\\"')) @@ -204,14 +205,17 @@ class MainDisplay(DisplayWidget): """ self.imageManager.add_image(name, path) self.image(name) + if hasattr(self, u'serviceItem'): + self.override[u'image'] = name + self.override[u'theme'] = self.serviceItem.themedata.theme_name def image(self, name): """ - Add an image as the background. The image is converted to a bytestream - on route. + Add an image as the background. The image has already been added + to the cache. `Image` - The Image to be displayed can be QImage or QPixmap + The name of the image to be displayed """ log.debug(u'image to display') image = self.imageManager.get_image_bytes(name) @@ -244,6 +248,7 @@ class MainDisplay(DisplayWidget): self.displayImage(self.serviceItem.bg_image_bytes) else: self.displayImage(None) + self.override = {} # Update the preview frame. Receiver.send_message(u'maindisplay_active') @@ -260,6 +265,7 @@ class MainDisplay(DisplayWidget): self.phononActive = False else: self.frame.evaluateJavaScript(u'show_video("close");') + self.override = {} # Update the preview frame. Receiver.send_message(u'maindisplay_active') @@ -313,7 +319,10 @@ class MainDisplay(DisplayWidget): Loads and starts a video to run with the option of sound """ log.debug(u'video') - self.loaded = True + self.webLoaded = True + # We are running a background theme + self.override[u'theme'] = u'' + self.override[u'video'] = True vol = float(volume)/float(10) if isBackground or not self.usePhonon: js = u'show_video("init", "%s", %s, true); show_video("play");' % \ @@ -333,12 +342,12 @@ class MainDisplay(DisplayWidget): Receiver.send_message(u'maindisplay_active') return self.preview() - def isLoaded(self): + def isWebLoaded(self): """ Called by webView event to show display is fully loaded """ - log.debug(u'loaded') - self.loaded = True + log.debug(u'Webloaded') + self.webLoaded = True def preview(self): """ @@ -357,7 +366,7 @@ class MainDisplay(DisplayWidget): Receiver.send_message(u'openlp_process_events') # Wait for the webview to update before geting the preview. # Important otherwise first preview will miss the background ! - while not self.loaded: + while not self.webLoaded: Receiver.send_message(u'openlp_process_events') # if was hidden keep it hidden if self.isLive: @@ -379,18 +388,32 @@ class MainDisplay(DisplayWidget): HTML to the display """ log.debug(u'buildHtml') - self.loaded = False + self.webLoaded = False self.initialFrame = False self.serviceItem = serviceItem + background = None + # We have an image override so keep the image till the theme changes + if self.override: + # We have an video override so allow it to be stopped + if u'video' in self.override: + Receiver.send_message(u'video_background_replaced') + self.override = {} + elif self.override[u'theme'] != \ + serviceItem.themedata.theme_name: + Receiver.send_message(u'live_theme_changed') + self.override = {} + else: + background = self.imageManager. \ + get_image_bytes(self.override[u'image']) if self.serviceItem.themedata.background_filename: self.serviceItem.bg_image_bytes = self.imageManager. \ get_image_bytes(self.serviceItem.themedata.theme_name) html = build_html(self.serviceItem, self.screen, self.parent.alertTab, - self.isLive) + self.isLive, background) log.debug(u'buildHtml - pre setHtml') self.webView.setHtml(html) log.debug(u'buildHtml - post setHtml') - if serviceItem.foot_text and serviceItem.foot_text: + if serviceItem.foot_text: self.footer(serviceItem.foot_text) # if was hidden keep it hidden if self.hideMode and self.isLive: diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index db9d4f9d5..d8bedade3 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -563,10 +563,10 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.ServiceManagerContents.onLoadServiceClicked) QtCore.QObject.connect(self.FileSaveItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onSaveServiceClicked) + self.ServiceManagerContents.saveFile) QtCore.QObject.connect(self.FileSaveAsItem, QtCore.SIGNAL(u'triggered()'), - self.ServiceManagerContents.onSaveServiceAsClicked) + self.ServiceManagerContents.saveFileAs) # i18n set signals for languages QtCore.QObject.connect(self.AutoLanguageItem, QtCore.SIGNAL(u'toggled(bool)'), self.setAutoLanguage) @@ -807,15 +807,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): Hook to close the main window and display windows on exit """ if self.ServiceManagerContents.isModified(): - ret = QtGui.QMessageBox.question(self, - translate('OpenLP.MainWindow', 'Save Changes to Service?'), - translate('OpenLP.MainWindow', 'Your service has changed. ' - 'Do you want to save those changes?'), - QtGui.QMessageBox.StandardButtons( - QtGui.QMessageBox.Cancel | - QtGui.QMessageBox.Discard | - QtGui.QMessageBox.Save), - QtGui.QMessageBox.Save) + ret = self.ServiceManagerContents.saveModifiedService() if ret == QtGui.QMessageBox.Save: if self.ServiceManagerContents.saveFile(): self.cleanUp() @@ -847,7 +839,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.cleanUp() event.accept() - def cleanUp(self): """ Runs all the cleanup code before OpenLP shuts down diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index b9f9fe53d..22a873855 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -108,7 +108,7 @@ class ServiceManager(QtGui.QWidget): translate('OpenLP.ServiceManager', 'Save Service'), u':/general/general_save.png', translate('OpenLP.ServiceManager', 'Save this service'), - self.onSaveServiceClicked) + self.saveFile) self.toolbar.addSeparator() self.themeLabel = QtGui.QLabel(translate('OpenLP.ServiceManager', 'Theme:'), self) @@ -178,8 +178,8 @@ class ServiceManager(QtGui.QWidget): translate('OpenLP.ServiceManager', 'Move &down'), None, translate('OpenLP.ServiceManager', - 'Moves the selection up the window.'), - self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Up) + 'Moves the selection down the window.'), + self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Down) self.serviceManagerList.down.setVisible(False) self.serviceManagerList.up = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move up'), @@ -361,12 +361,7 @@ class ServiceManager(QtGui.QWidget): Create a new service. """ if self.isModified(): - result = QtGui.QMessageBox.question(self.mainwindow, - translate('OpenLP.ServiceManager', 'Save Changes'), - translate('OpenLP.ServiceManager', 'The current service has ' - 'been modified, would you like to save it?'), - QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | - QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) + result = self.saveModifiedService() if result == QtGui.QMessageBox.Cancel: return False elif result == QtGui.QMessageBox.Save: @@ -376,12 +371,7 @@ class ServiceManager(QtGui.QWidget): def onLoadServiceClicked(self): if self.isModified(): - result = QtGui.QMessageBox.question(self.mainwindow, - translate('OpenLP.ServiceManager', 'Save Changes'), - translate('OpenLP.ServiceManager', 'The current service has ' - 'been modified, would you like to save it?'), - QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | - QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) + result = self.saveModifiedService() if result == QtGui.QMessageBox.Cancel: return False elif result == QtGui.QMessageBox.Save: @@ -397,11 +387,13 @@ class ServiceManager(QtGui.QWidget): split_filename(fileName)[0]) self.loadFile(fileName) - def onSaveServiceClicked(self): - self.saveFile() - - def onSaveServiceAsClicked(self): - self.saveFileAs() + def saveModifiedService(self): + return QtGui.QMessageBox.question(self.mainwindow, + translate('OpenLP.ServiceManager', 'Modified Service'), + translate('OpenLP.ServiceManager', 'The current service has ' + 'been modified. Would you like to save this service?'), + QtGui.QMessageBox.Save | QtGui.QMessageBox.Discard | + QtGui.QMessageBox.Cancel, QtGui.QMessageBox.Save) def onRecentServiceClicked(self): sender = self.sender() @@ -603,7 +595,7 @@ class ServiceManager(QtGui.QWidget): if self.serviceNoteForm.exec_(): self.serviceItems[item][u'service_item'].notes = \ self.serviceNoteForm.textEdit.toPlainText() - self.repaintServiceList(item, 0) + self.repaintServiceList(item, -1) def onServiceItemEditForm(self): item = self.findServiceItem()[0] @@ -615,8 +607,7 @@ class ServiceManager(QtGui.QWidget): def nextItem(self): """ - Called by the SlideController to select the - next service item + Called by the SlideController to select the next service item. """ if len(self.serviceManagerList.selectedItems()) == 0: return @@ -634,8 +625,7 @@ class ServiceManager(QtGui.QWidget): def previousItem(self): """ - Called by the SlideController to select the - previous service item + Called by the SlideController to select the previous service item. """ if len(self.serviceManagerList.selectedItems()) == 0: return @@ -654,13 +644,13 @@ class ServiceManager(QtGui.QWidget): def onSetItem(self, message): """ - Called by a signal to select a specific item + Called by a signal to select a specific item. """ self.setItem(int(message[0])) def setItem(self, index): """ - Makes a specific item in the service live + Makes a specific item in the service live. """ if index >= 0 and index < self.serviceManagerList.topLevelItemCount: item = self.serviceManagerList.topLevelItem(index) @@ -669,8 +659,7 @@ class ServiceManager(QtGui.QWidget): def onMoveSelectionUp(self): """ - Moves the selection up the window - Called by the up arrow + Moves the selection up the window. Called by the up arrow. """ serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList) tempItem = None @@ -695,8 +684,7 @@ class ServiceManager(QtGui.QWidget): def onMoveSelectionDown(self): """ - Moves the selection down the window - Called by the down arrow + Moves the selection down the window. Called by the down arrow. """ serviceIterator = QtGui.QTreeWidgetItemIterator(self.serviceManagerList) firstItem = None @@ -718,7 +706,7 @@ class ServiceManager(QtGui.QWidget): def onCollapseAll(self): """ - Collapse all the service items + Collapse all the service items. """ for item in self.serviceItems: item[u'expanded'] = False @@ -726,15 +714,15 @@ class ServiceManager(QtGui.QWidget): def collapsed(self, item): """ - Record if an item is collapsed - Used when repainting the list to get the correct state + Record if an item is collapsed. Used when repainting the list to get the + correct state. """ pos = item.data(0, QtCore.Qt.UserRole).toInt()[0] self.serviceItems[pos -1 ][u'expanded'] = False def onExpandAll(self): """ - Collapse all the service items + Collapse all the service items. """ for item in self.serviceItems: item[u'expanded'] = True @@ -742,70 +730,68 @@ class ServiceManager(QtGui.QWidget): def expanded(self, item): """ - Record if an item is collapsed - Used when repainting the list to get the correct state + Record if an item is collapsed. Used when repainting the list to get the + correct state. """ pos = item.data(0, QtCore.Qt.UserRole).toInt()[0] self.serviceItems[pos -1 ][u'expanded'] = True def onServiceTop(self): """ - Move the current ServiceItem to the top of the list + Move the current ServiceItem to the top of the list. """ - item, count = self.findServiceItem() + item, child = self.findServiceItem() if item < len(self.serviceItems) and item is not -1: temp = self.serviceItems[item] self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(0, temp) - self.repaintServiceList(0, count) + self.repaintServiceList(0, child) self.setModified(True) def onServiceUp(self): """ - Move the current ServiceItem up in the list - Note move up means move to top of area ie 0. + Move the current ServiceItem one position up in the list. """ - item, count = self.findServiceItem() + item, child = self.findServiceItem() if item > 0: temp = self.serviceItems[item] self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(item - 1, temp) - self.repaintServiceList(item - 1, count) + self.repaintServiceList(item - 1, child) self.setModified(True) def onServiceDown(self): """ - Move the current ServiceItem down in the list - Note move down means move to bottom of area i.e len(). + Move the current ServiceItem one position down in the list. """ - item, count = self.findServiceItem() + item, child = self.findServiceItem() if item < len(self.serviceItems) and item is not -1: temp = self.serviceItems[item] self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(item + 1, temp) - self.repaintServiceList(item + 1, count) + self.repaintServiceList(item + 1, child) self.setModified(True) def onServiceEnd(self): """ - Move the current ServiceItem to the bottom of the list + Move the current ServiceItem to the bottom of the list. """ - item, count = self.findServiceItem() + item, child = self.findServiceItem() if item < len(self.serviceItems) and item is not -1: temp = self.serviceItems[item] self.serviceItems.remove(self.serviceItems[item]) self.serviceItems.insert(len(self.serviceItems), temp) - self.repaintServiceList(len(self.serviceItems) - 1, count) + self.repaintServiceList(len(self.serviceItems) - 1, child) self.setModified(True) def onDeleteFromService(self): """ - Remove the current ServiceItem from the list + Remove the current ServiceItem from the list. """ item = self.findServiceItem()[0] - if item is not -1: + if item != -1: self.serviceItems.remove(self.serviceItems[item]) - self.repaintServiceList(0, 0) + self.repaintServiceList(item - 1, -1) self.setModified(True) def repaintServiceList(self, serviceItem, serviceItemChild): @@ -847,7 +833,7 @@ class ServiceManager(QtGui.QWidget): else: treewidgetitem.setIcon(0, build_icon(u':/general/general_delete.png')) - treewidgetitem.setText(0, serviceitem.title) + treewidgetitem.setText(0, serviceitem.get_display_title()) treewidgetitem.setToolTip(0, serviceitem.notes) treewidgetitem.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(item[u'order'])) @@ -867,7 +853,7 @@ class ServiceManager(QtGui.QWidget): def validateItem(self, serviceItem): """ Validates the service item and if the suffix matches an accepted - one it allows the item to be displayed + one it allows the item to be displayed. """ if serviceItem.is_command(): type = serviceItem._raw_frames[0][u'title'].split(u'.')[1] @@ -876,7 +862,7 @@ class ServiceManager(QtGui.QWidget): def cleanUp(self): """ - Empties the servicePath of temporary files + Empties the servicePath of temporary files. """ for file in os.listdir(self.servicePath): file_path = os.path.join(self.servicePath, file) @@ -884,7 +870,7 @@ class ServiceManager(QtGui.QWidget): def onThemeComboBoxSelected(self, currentIndex): """ - Set the theme for the current service + Set the theme for the current service. """ log.debug(u'onThemeComboBoxSelected') self.service_theme = unicode(self.themeComboBox.currentText()) @@ -967,12 +953,12 @@ class ServiceManager(QtGui.QWidget): # if not passed set to config value if expand is None: expand = self.expandTabs - sitem = self.findServiceItem()[0] item.render() if replace: + sitem, child = self.findServiceItem() item.merge(self.serviceItems[sitem][u'service_item']) self.serviceItems[sitem][u'service_item'] = item - self.repaintServiceList(sitem, 0) + self.repaintServiceList(sitem, child) self.mainwindow.liveController.replaceServiceManagerItem(item) else: # nothing selected for dnd @@ -981,17 +967,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}) else: self.serviceItems.append({u'service_item': item, u'order': len(self.serviceItems) + 1, - u'expanded':expand}) - self.repaintServiceList(len(self.serviceItems) + 1, 0) + u'expanded': expand}) + self.repaintServiceList(len(self.serviceItems) - 1, -1) else: self.serviceItems.insert(self.dropPosition, {u'service_item': item, u'order': self.dropPosition, - u'expanded':expand}) - self.repaintServiceList(self.dropPosition, 0) + u'expanded': expand}) + self.repaintServiceList(self.dropPosition, -1) # if rebuilding list make sure live is fixed. if rebuild: self.mainwindow.liveController.replaceServiceManagerItem(item) @@ -1002,15 +988,15 @@ class ServiceManager(QtGui.QWidget): """ Send the current item to the Preview slide controller """ - item, count = self.findServiceItem() + item, child = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: self.mainwindow.previewController.addServiceManagerItem( - self.serviceItems[item][u'service_item'], count) + self.serviceItems[item][u'service_item'], child) else: criticalErrorMessageBox( translate('OpenLP.ServiceManager', 'Missing Display Handler'), translate('OpenLP.ServiceManager', 'Your item cannot be ' - 'displayed as there is no handler to display it')) + 'displayed as there is no handler to display it')) def getServiceItem(self): """ @@ -1026,10 +1012,10 @@ class ServiceManager(QtGui.QWidget): """ Send the current item to the Live slide controller """ - item, count = self.findServiceItem() + item, child = self.findServiceItem() if self.serviceItems[item][u'service_item'].is_valid: self.mainwindow.liveController.addServiceManagerItem( - self.serviceItems[item][u'service_item'], count) + self.serviceItems[item][u'service_item'], child) if QtCore.QSettings().value( self.mainwindow.generalSettingsSection + u'/auto preview', QtCore.QVariant(False)).toBool(): @@ -1060,26 +1046,26 @@ class ServiceManager(QtGui.QWidget): def findServiceItem(self): """ - Finds a ServiceItem in the list and returns the position of the - serviceitem and its selected child item. For example, if the third child - item (in the Slidecontroller known as slide) in the second service item - is selected this will return:: + Finds the selected ServiceItem in the list and returns the position of + the serviceitem and its selected child item. For example, if the third + child item (in the Slidecontroller known as slide) in the second service + item is selected this will return:: (1, 2) """ items = self.serviceManagerList.selectedItems() - pos = 0 - count = -1 + serviceItem = 0 + serviceItemChild = -1 for item in items: parentitem = item.parent() if parentitem is None: - pos = item.data(0, QtCore.Qt.UserRole).toInt()[0] + serviceItem = item.data(0, QtCore.Qt.UserRole).toInt()[0] else: - pos = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] - count = item.data(0, QtCore.Qt.UserRole).toInt()[0] - # adjust for zero based arrays - pos = pos - 1 - return pos, count + serviceItem = parentitem.data(0, QtCore.Qt.UserRole).toInt()[0] + serviceItemChild = item.data(0, QtCore.Qt.UserRole).toInt()[0] + # Adjust for zero based arrays. + serviceItem -= 1 + return serviceItem, serviceItemChild def dragEnterEvent(self, event): """ @@ -1105,7 +1091,7 @@ class ServiceManager(QtGui.QWidget): item = self.serviceManagerList.itemAt(event.pos()) # ServiceManager started the drag and drop if plugin == u'ServiceManager': - startpos, startCount = self.findServiceItem() + startpos, child = self.findServiceItem() # If no items selected if startpos == -1: return @@ -1116,7 +1102,7 @@ class ServiceManager(QtGui.QWidget): serviceItem = self.serviceItems[startpos] self.serviceItems.remove(serviceItem) self.serviceItems.insert(endpos, serviceItem) - self.repaintServiceList(endpos, startCount) + self.repaintServiceList(endpos, child) else: # we are not over anything so drop replace = False @@ -1182,15 +1168,15 @@ class ServiceManager(QtGui.QWidget): def listRequest(self, message=None): data = [] - curindex = self.findServiceItem()[0] - if curindex >= 0 and curindex < len(self.serviceItems): - curitem = self.serviceItems[curindex] + item = self.findServiceItem()[0] + if item >= 0 and item < len(self.serviceItems): + curitem = self.serviceItems[item] else: curitem = None for item in self.serviceItems: service_item = item[u'service_item'] data_item = {} - data_item[u'title'] = unicode(service_item.title) + data_item[u'title'] = unicode(service_item.get_display_title()) data_item[u'plugin'] = unicode(service_item.name) data_item[u'notes'] = unicode(service_item.notes) data_item[u'selected'] = (item == curitem) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 7266d197c..916bf68c3 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -119,6 +119,8 @@ class SlideController(QtGui.QWidget): self.previewListWidget.isLive = self.isLive self.previewListWidget.setObjectName(u'PreviewListWidget') self.previewListWidget.setSelectionBehavior(1) + self.previewListWidget.setSelectionMode( + QtGui.QAbstractItemView.SingleSelection) self.previewListWidget.setEditTriggers( QtGui.QAbstractItemView.NoEditTriggers) self.previewListWidget.setHorizontalScrollBarPolicy( diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 2db76063c..43f1034f4 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -55,7 +55,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): self.thememanager = parent self.setupUi(self) self.registerFields() - self.accepted = False self.updateThemeAllowed = True QtCore.QObject.connect(self.backgroundComboBox, QtCore.SIGNAL(u'currentIndexChanged(int)'), @@ -120,14 +119,12 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): QtCore.QObject.connect(self.mainFontComboBox, QtCore.SIGNAL(u'activated(int)'), self.calculateLines) - QtCore.QObject.connect(self, QtCore.SIGNAL(u'accepted()'), self.accept) def setDefaults(self): """ Set up display at start of theme edit. """ self.restart() - self.accepted = False self.setBackgroundPageValues() self.setMainAreaPageValues() self.setFooterAreaPageValues() @@ -250,25 +247,27 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Change state as Outline check box changed """ - if state == QtCore.Qt.Checked: - self.theme.font_main_outline = True - else: - self.theme.font_main_outline = False - self.outlineColorButton.setEnabled(self.theme.font_main_outline) - self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline) - self.calculateLines() + if self.updateThemeAllowed: + if state == QtCore.Qt.Checked: + self.theme.font_main_outline = True + else: + self.theme.font_main_outline = False + self.outlineColorButton.setEnabled(self.theme.font_main_outline) + self.outlineSizeSpinBox.setEnabled(self.theme.font_main_outline) + self.calculateLines() def onShadowCheckCheckBoxStateChanged(self, state): """ Change state as Shadow check box changed """ - if state == QtCore.Qt.Checked: - self.theme.font_main_shadow = True - else: - self.theme.font_main_shadow = False - self.shadowColorButton.setEnabled(self.theme.font_main_shadow) - self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow) - self.calculateLines() + if self.updateThemeAllowed: + if state == QtCore.Qt.Checked: + self.theme.font_main_shadow = True + else: + self.theme.font_main_shadow = False + self.shadowColorButton.setEnabled(self.theme.font_main_shadow) + self.shadowSizeSpinBox.setEnabled(self.theme.font_main_shadow) + self.calculateLines() def onMainPositionCheckBoxStateChanged(self, value): """ @@ -446,9 +445,10 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Background gradient Combo box has changed. """ - self.theme.background_direction = \ - BackgroundGradientType.to_string(index) - self.setBackgroundPageValues() + if self.updateThemeAllowed: + self.theme.background_direction = \ + BackgroundGradientType.to_string(index) + self.setBackgroundPageValues() def onColorButtonClicked(self): """ @@ -560,13 +560,8 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): """ Lets save the them as Finish has been pressed """ - # Some reason getting double submission. - # Hack to stop it for now. - if self.accepted: - return # Save the theme name - self.theme.theme_name = \ - unicode(self.field(u'name').toString()) + self.theme.theme_name = unicode(self.field(u'name').toString()) if not self.theme.theme_name: criticalErrorMessageBox( translate('OpenLP.ThemeForm', 'Theme Name Missing'), @@ -590,7 +585,6 @@ class ThemeForm(QtGui.QWizard, Ui_ThemeWizard): if not self.edit_mode and \ not self.thememanager.checkIfThemeExists(self.theme.theme_name): return - self.accepted = True self.thememanager.saveTheme(self.theme, saveFrom, saveTo) return QtGui.QDialog.accept(self) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 9dd133852..37cbd7a63 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -137,10 +137,7 @@ class AppLocation(object): os.path.split(openlp.__file__)[0]) return os.path.join(app_path, u'i18n') else: - return _get_os_dir_path(u'openlp', - os.path.join(os.getenv(u'HOME'), u'Library', - u'Application Support', u'openlp'), - None, os.path.join(os.getenv(u'HOME'), u'.openlp'), dir_type) + return _get_os_dir_path(dir_type) @staticmethod def get_data_path(): @@ -163,17 +160,18 @@ class AppLocation(object): os.makedirs(path) return path -def _get_os_dir_path(win_option, darwin_option, base_dir_option, - non_base_dir_option, dir_type=1): +def _get_os_dir_path(dir_type): """ Return a path based on which OS and environment we are running in. """ if sys.platform == u'win32': - return os.path.join(os.getenv(u'APPDATA'), win_option) + return os.path.join(os.getenv(u'APPDATA'), u'openlp') elif sys.platform == u'darwin': if dir_type == AppLocation.DataDir: - return os.path.join(darwin_option, u'Data') - return darwin_option + return os.path.join(os.getenv(u'HOME'), u'Library', + u'Application Support', u'openlp', u'Data') + return os.path.join(os.getenv(u'HOME'), u'Library', + u'Application Support', u'openlp') else: if XDG_BASE_AVAILABLE: if dir_type == AppLocation.ConfigDir: @@ -183,7 +181,7 @@ def _get_os_dir_path(win_option, darwin_option, base_dir_option, elif dir_type == AppLocation.CacheDir: return os.path.join(BaseDirectory.xdg_cache_home, u'openlp') else: - return non_base_dir_option + return os.path.join(os.getenv(u'HOME'), u'.openlp') def _get_frozen_path(frozen_option, non_frozen_option): """ diff --git a/openlp/plugins/alerts/alertsplugin.py b/openlp/plugins/alerts/alertsplugin.py index 61be922d5..443ec1e84 100644 --- a/openlp/plugins/alerts/alertsplugin.py +++ b/openlp/plugins/alerts/alertsplugin.py @@ -45,15 +45,14 @@ class AlertsPlugin(Plugin): self.icon = build_icon(u':/plugins/plugin_alerts.png') self.alertsmanager = AlertsManager(self) self.manager = Manager(u'alerts', init_schema) - visible_name = self.getString(StringContent.VisibleName) - self.alertForm = AlertForm(self, visible_name[u'title']) + self.visible_name = self.getString(StringContent.VisibleName) + self.alertForm = AlertForm(self) def getSettingsTab(self): """ Return the settings tab for the Alerts plugin """ - visible_name = self.getString(StringContent.VisibleName) - self.alertsTab = AlertsTab(self, visible_name[u'title']) + self.alertsTab = AlertsTab(self, self.visible_name[u'title']) return self.alertsTab def addToolsMenuItem(self, tools_menu): diff --git a/openlp/plugins/alerts/forms/alertform.py b/openlp/plugins/alerts/forms/alertform.py index 1d6a566fd..f1a0f7fea 100644 --- a/openlp/plugins/alerts/forms/alertform.py +++ b/openlp/plugins/alerts/forms/alertform.py @@ -35,7 +35,7 @@ class AlertForm(QtGui.QDialog, Ui_AlertDialog): """ Provide UI for the alert system """ - def __init__(self, plugin, visible_title): + def __init__(self, plugin): """ Initialise the alert form """ diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index d3f41804b..3e43d19aa 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -124,9 +124,12 @@ 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.onBooksBrowseButtonClicked) + self.onCsvBooksBrowseButtonClicked) QtCore.QObject.connect(self.csvVersesButton, QtCore.SIGNAL(u'clicked()'), self.onCsvVersesBrowseButtonClicked) @@ -187,6 +190,18 @@ 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() @@ -213,7 +228,7 @@ class BibleImportForm(OpenLPWizard): self.csvLayout.addRow(self.csvVersesLabel, self.csvVersesLayout) self.csvSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) - self.csvLayout.setItem(2, QtGui.QFormLayout.LabelRole, self.csvSpacer) + self.csvLayout.setItem(3, QtGui.QFormLayout.LabelRole, self.csvSpacer) self.selectStack.addWidget(self.csvWidget) self.openSongWidget = QtGui.QWidget(self.selectPage) self.openSongWidget.setObjectName(u'OpenSongWidget') @@ -389,6 +404,8 @@ class BibleImportForm(OpenLPWizard): translate('BiblesPlugin.ImportWizardForm', 'File location:')) self.osisFileLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'File location:')) + self.csvTestamentsLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Testaments location:')) self.csvBooksLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Books location:')) self.csvVersesLabel.setText( @@ -478,7 +495,16 @@ class BibleImportForm(OpenLPWizard): self.osisFileEdit.setFocus() return False elif self.field(u'source_format').toInt()[0] == BibleFormat.CSV: - if not self.field(u'csv_booksfile').toString(): + if not self.field(u'csv_testamentsfile').toString(): + answer = criticalErrorMessageBox(translate( + 'BiblesPlugin.ImportWizardForm', 'No Testaments File'), + 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 + elif not self.field(u'csv_booksfile').toString(): criticalErrorMessageBox( translate('BiblesPlugin.ImportWizardForm', 'Invalid Books File'), @@ -572,7 +598,15 @@ class BibleImportForm(OpenLPWizard): translate('BiblesPlugin.ImportWizardForm', 'Open OSIS File'), self.osisFileEdit) - def onBooksBrowseButtonClicked(self): + def onCsvTestamentsBrowseButtonClicked(self): + """ + Show the file open dialog for the testaments CSV file. + """ + self.getFileName(translate('BiblesPlugin.ImportWizardForm', + 'Open Testaments CSV File'), self.csvTestamentsEdit, u'%s (*.csv)' + % translate('BiblesPlugin.ImportWizardForm', 'CSV File')) + + def onCsvBooksBrowseButtonClicked(self): """ Show the file open dialog for the books CSV file. """ @@ -613,12 +647,14 @@ 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) self.selectPage.registerField(u'web_location', self.webSourceComboBox) - self.selectPage.registerField(u'web_biblename', - self.webTranslationComboBox) + self.selectPage.registerField( + u'web_biblename', self.webTranslationComboBox) self.selectPage.registerField(u'proxy_server', self.webServerEdit) self.selectPage.registerField(u'proxy_username', self.webUserEdit) self.selectPage.registerField(u'proxy_password', self.webPasswordEdit) @@ -641,6 +677,7 @@ 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('')) @@ -770,7 +807,8 @@ class BibleImportForm(OpenLPWizard): elif bible_type == BibleFormat.CSV: # Import a CSV bible. importer = self.manager.import_bible(BibleFormat.CSV, - name=license_version, + name=license_version, testamentsfile=unicode( + self.field(u'csv_testamentsfile').toString()), booksfile=unicode(self.field(u'csv_booksfile').toString()), versefile=unicode(self.field(u'csv_versefile').toString()) ) @@ -795,8 +833,7 @@ class BibleImportForm(OpenLPWizard): bible = \ self.web_bible_list[WebDownload.Bibleserver][bible_version] importer = self.manager.import_bible( - BibleFormat.WebDownload, - name=license_version, + BibleFormat.WebDownload, name=license_version, download_source=WebDownload.get_name(download_location), download_name=bible, proxy_server=unicode(self.field(u'proxy_server').toString()), diff --git a/openlp/plugins/bibles/lib/csvbible.py b/openlp/plugins/bibles/lib/csvbible.py index 8959167a6..fd987dfdf 100644 --- a/openlp/plugins/bibles/lib/csvbible.py +++ b/openlp/plugins/bibles/lib/csvbible.py @@ -23,7 +23,45 @@ # with this program; if not, write to the Free Software Foundation, Inc., 59 # # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### +""" +The :mod:`cvsbible` modules provides a facility to import bibles from a set of +CSV files. +The module expects two mandatory files containing the books and the verses and +will accept an optional third file containing the testaments. + +The format of the testament file is: + + , + + For example: + + 1,Old Testament + 2,New Testament + +The format of the books file is: + + ,,, + + For example + + 1,1,Genesis,Gen + 2,1,Exodus,Exod + ... + 40,2,Matthew,Matt + +The format of the verses file is: + + ,,, + + For example: + + 1,1,1,"In the beginning God created the heaven and the earth." + 1,1,2,"And the earth was without form, and void; and darkness...." + +All CSV files are expected to use a comma (',') as the delimeter and double +quotes ('"') as the quote symbol. +""" import logging import chardet import csv @@ -31,7 +69,7 @@ import csv from PyQt4 import QtCore from openlp.core.lib import Receiver, translate -from openlp.plugins.bibles.lib.db import BibleDB +from openlp.plugins.bibles.lib.db import BibleDB, Testament log = logging.getLogger(__name__) @@ -39,68 +77,113 @@ class CSVBible(BibleDB): """ This class provides a specialisation for importing of CSV Bibles. """ - def __init__(self, parent, **kwargs): """ - Loads a Bible from a pair of CVS files passed in + Loads a Bible from a set of CVS files. This class assumes the files contain all the information and a clean bible is being loaded. """ 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'] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) + 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): + """ + Import the bible books and verses. + """ + self.wizard.progressBar.setValue(0) + self.wizard.progressBar.setMinimum(0) + self.wizard.progressBar.setMaximum(66) success = True books_file = None - book_ptr = None - verse_file = None + book_list = {} # Populate the Tables try: + details = get_file_encoding(self.booksfile) books_file = open(self.booksfile, 'r') - dialect = csv.Sniffer().sniff(books_file.read(1024)) - books_file.seek(0) - books_reader = csv.reader(books_file, dialect) + books_reader = csv.reader(books_file, delimiter=',', quotechar='"') for line in books_reader: - # cancel pressed if self.stop_import_flag: break - details = chardet.detect(line[1]) - self.create_book(unicode(line[1], details['encoding']), - line[2], int(line[0])) - Receiver.send_message(u'openlp_process_events') + self.wizard.incrementProgressBar(unicode( + translate('BibleDB.Wizard', 'Importing books... %s')) % + unicode(line[2], details['encoding'])) + self.create_book(unicode(line[2], details['encoding']), + unicode(line[3], details['encoding']), int(line[1])) + book_list[int(line[0])] = unicode(line[2], details['encoding']) + Receiver.send_message(u'openlp_process_events') except (IOError, IndexError): log.exception(u'Loading books from file failed') success = False finally: if books_file: books_file.close() - if not success: + if self.stop_import_flag or not success: return False + self.wizard.progressBar.setValue(0) + self.wizard.progressBar.setMaximum(67) + verse_file = None try: - verse_file = open(self.versesfile, 'r') - dialect = csv.Sniffer().sniff(verse_file.read(1024)) - verse_file.seek(0) - verse_reader = csv.reader(verse_file, dialect) + book_ptr = None + details = get_file_encoding(self.versesfile) + verse_file = open(self.versesfile, 'rb') + verse_reader = csv.reader(verse_file, delimiter=',', quotechar='"') for line in verse_reader: if self.stop_import_flag: - # cancel pressed break - details = chardet.detect(line[3]) - if book_ptr != line[0]: - book = self.get_book(line[0]) + if book_ptr != book_list[int(line[0])]: + book = self.get_book(book_list[int(line[0])]) book_ptr = book.name self.wizard.incrementProgressBar(unicode(translate( - 'BiblesPlugin.CSVImport', 'Importing %s %s...', - 'Importing ...')) % - (book.name, int(line[1]))) + 'BibleDB.Wizard', 'Importing verses from %s...', + 'Importing verses from ...')) % book.name) self.session.commit() self.create_verse(book.id, line[1], line[2], unicode(line[3], details['encoding'])) - Receiver.send_message(u'openlp_process_events') + self.wizard.incrementProgressBar(translate('BibleDB.Wizard', + 'Importing verses... done.')) + Receiver.send_message(u'openlp_process_events') self.session.commit() except IOError: log.exception(u'Loading verses from file failed') @@ -112,3 +195,18 @@ class CSVBible(BibleDB): return False else: return success + +def get_file_encoding(filename): + """ + Utility function to get the file encoding. + """ + detect_file = None + try: + detect_file = open(filename, 'r') + details = chardet.detect(detect_file.read(1024)) + except IOError: + log.exception(u'Error detecting file encoding') + finally: + if detect_file: + detect_file.close() + return details diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index f442a9cd6..a9444d88b 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -206,10 +206,16 @@ 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')) - return self.name def create_book(self, name, abbrev, testament=1): """ diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index 63c6954fb..85204ac7a 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -92,7 +92,7 @@ class BibleFormat(object): return None @staticmethod - def list(): + def get_formats_list(): """ Return a list of the supported Bible formats. """ diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index f5e7b3966..614990654 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -254,9 +254,6 @@ class BibleMediaItem(MediaManagerItem): QtCore.QObject.connect(self.quickSearchEdit, QtCore.SIGNAL(u'returnPressed()'), self.onQuickSearchButton) - def addListViewToToolBar(self): - MediaManagerItem.addListViewToToolBar(self) - def configUpdated(self): log.debug(u'configUpdated') if QtCore.QSettings().value(self.settingsSection + u'/second bibles', diff --git a/openlp/plugins/bibles/resources/bibleserver.csv b/openlp/plugins/bibles/resources/bibleserver.csv index c0d109f97..942d43116 100644 --- a/openlp/plugins/bibles/resources/bibleserver.csv +++ b/openlp/plugins/bibles/resources/bibleserver.csv @@ -19,7 +19,7 @@ IBS-fordítás (Új Károli), KAR King James Version, KJV Luther 1984, LUT Septuaginta, LXX -Neue Genfer Übersetzung, NGÜ +Neue Genfer Übersetzung, NGU New International Readers Version, NIRV New International Version, NIV Neues Leben, NL diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index 304773ea5..9b8115956 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -68,9 +68,6 @@ class CustomMediaItem(MediaManagerItem): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'custom_preview'), self.onPreviewClick) - def requiredIcons(self): - MediaManagerItem.requiredIcons(self) - def initialise(self): self.loadCustomListView(self.manager.get_all_objects( CustomSlide, order_by_ref=CustomSlide.title)) @@ -182,4 +179,4 @@ class CustomMediaItem(MediaManagerItem): else: raw_footer.append(u'') service_item.raw_footer = raw_footer - return True \ No newline at end of file + return True diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index bd84219fb..73f5b80f0 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -31,7 +31,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ ItemCapabilities, SettingsManager, translate, check_item_selected, \ - check_directory_exists + check_directory_exists, Receiver from openlp.core.ui import criticalErrorMessageBox from openlp.core.utils import AppLocation, delete_file, get_images_filter @@ -44,7 +44,6 @@ class ImageListView(BaseListWithDnD): self.PluginName = u'Images' BaseListWithDnD.__init__(self, parent) - class ImageMediaItem(MediaManagerItem): """ This is the custom media manager item for images. @@ -57,6 +56,8 @@ class ImageMediaItem(MediaManagerItem): # be instanced by the base MediaManagerItem. self.ListViewWithDnD_class = ImageListView MediaManagerItem.__init__(self, parent, self, icon) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'live_theme_changed'), self.liveThemeChanged) def retranslateUi(self): self.OnNewPrompt = translate('ImagePlugin.MediaItem', @@ -95,7 +96,6 @@ class ImageMediaItem(MediaManagerItem): def addListViewToToolBar(self): MediaManagerItem.addListViewToToolBar(self) - self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.listView.addAction(self.replaceAction) def addEndHeaderBar(self): @@ -193,6 +193,12 @@ class ImageMediaItem(MediaManagerItem): self.resetAction.setVisible(False) self.parent.liveController.display.resetImage() + def liveThemeChanged(self): + """ + Triggered by the change of theme in the slide controller + """ + self.resetAction.setVisible(False) + def onReplaceClick(self): """ Called to replace Live backgound with the image selected. @@ -213,6 +219,3 @@ class ImageMediaItem(MediaManagerItem): unicode(translate('ImagePlugin.MediaItem', 'There was a problem replacing your background, ' 'the image file "%s" no longer exists.')) % filename) - - def onPreviewClick(self): - MediaManagerItem.onPreviewClick(self) diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 121fa80a0..e7beb81a9 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -30,7 +30,7 @@ import os from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, BaseListWithDnD, build_icon, \ - ItemCapabilities, SettingsManager, translate, check_item_selected + ItemCapabilities, SettingsManager, translate, check_item_selected, Receiver from openlp.core.ui import criticalErrorMessageBox log = logging.getLogger(__name__) @@ -58,6 +58,9 @@ class MediaMediaItem(MediaManagerItem): MediaManagerItem.__init__(self, parent, self, icon) self.singleServiceItem = False self.serviceItemIconName = u':/media/image_clapperboard.png' + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'video_background_replaced'), + self.videobackgroundReplaced) def retranslateUi(self): self.OnNewPrompt = translate('MediaPlugin.MediaItem', 'Select Media') @@ -81,7 +84,6 @@ class MediaMediaItem(MediaManagerItem): def addListViewToToolBar(self): MediaManagerItem.addListViewToToolBar(self) - self.listView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) self.listView.addAction(self.replaceAction) def addEndHeaderBar(self): @@ -99,6 +101,12 @@ class MediaMediaItem(MediaManagerItem): self.resetAction.setVisible(False) self.parent.liveController.display.resetVideo() + def videobackgroundReplaced(self): + """ + Triggered by main display on change of serviceitem + """ + self.resetAction.setVisible(False) + def onReplaceClick(self): """ Called to replace Live backgound with the media selected. diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 6ca67c2ae..f12d36dc8 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -171,11 +171,11 @@ class ImpressController(PresentationController): desktop = self.get_com_desktop() #Sometimes we get a failure and desktop is None if not desktop: - log.exception(u'Failed to terminate OpenOffice') + log.exception(u'Failed to find an OpenOffice desktop to terminate') return docs = desktop.getComponents() if docs.hasElements(): - log.debug(u'OpenOffice not terminated') + log.debug(u'OpenOffice not terminated as docs are still open') else: try: desktop.terminate() diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index e72d97be1..43cb3dab0 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -250,6 +250,7 @@ class PresentationMediaItem(MediaManagerItem): service_item.title = unicode(self.displayTypeComboBox.currentText()) service_item.shortname = unicode(self.displayTypeComboBox.currentText()) service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) + service_item.add_capability(ItemCapabilities.AllowsDetailedTitleDisplay) shortname = service_item.shortname if shortname: for item in items: diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index 93a01623e..6613a050b 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -278,117 +278,129 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def onAuthorEditButtonClick(self): author_id = self._getCurrentItemId(self.authorsListWidget) - if author_id != -1: - author = self.manager.get_object(Author, author_id) - self.authorform.setAutoDisplayName(False) - self.authorform.firstNameEdit.setText(author.first_name) - self.authorform.lastNameEdit.setText(author.last_name) - self.authorform.displayEdit.setText(author.display_name) - # Save the author's first and last name as well as the display name - # for the case that they have to be restored. - temp_first_name = author.first_name - temp_last_name = author.last_name - temp_display_name = author.display_name - if self.authorform.exec_(False): - author.first_name = unicode( - self.authorform.firstNameEdit.text()) - author.last_name = unicode(self.authorform.lastNameEdit.text()) - author.display_name = unicode( - self.authorform.displayEdit.text()) - if self.checkAuthor(author, True): - if self.manager.save_object(author): - self.resetAuthors() - Receiver.send_message(u'songs_load_list') - else: - criticalErrorMessageBox( - message=translate('SongsPlugin.SongMaintenanceForm', - 'Could not save your changes.')) - elif criticalErrorMessageBox(message=unicode(translate( - 'SongsPlugin.SongMaintenanceForm', 'The author %s already ' - 'exists. Would you like to make songs with author %s use ' - 'the existing author %s?')) % (author.display_name, - temp_display_name, author.display_name), - parent=self, question=True) == QtGui.QMessageBox.Yes: - self.mergeAuthors(author) + if author_id == -1: + return + author = self.manager.get_object(Author, author_id) + self.authorform.setAutoDisplayName(False) + self.authorform.firstNameEdit.setText(author.first_name) + self.authorform.lastNameEdit.setText(author.last_name) + self.authorform.displayEdit.setText(author.display_name) + # Save the author's first and last name as well as the display name + # for the case that they have to be restored. + temp_first_name = author.first_name + temp_last_name = author.last_name + temp_display_name = author.display_name + if self.authorform.exec_(False): + author.first_name = unicode( + self.authorform.firstNameEdit.text()) + author.last_name = unicode(self.authorform.lastNameEdit.text()) + author.display_name = unicode( + self.authorform.displayEdit.text()) + if self.checkAuthor(author, True): + if self.manager.save_object(author): self.resetAuthors() Receiver.send_message(u'songs_load_list') else: - # We restore the author's old first and last name as well as - # his display name. - author.first_name = temp_first_name - author.last_name = temp_last_name - author.display_name = temp_display_name criticalErrorMessageBox( message=translate('SongsPlugin.SongMaintenanceForm', - 'Could not save your modified author, because the ' - 'author already exists.')) + 'Could not save your changes.')) + elif criticalErrorMessageBox(message=unicode(translate( + 'SongsPlugin.SongMaintenanceForm', 'The author %s already ' + 'exists. Would you like to make songs with author %s use ' + 'the existing author %s?')) % (author.display_name, + temp_display_name, author.display_name), + parent=self, question=True) == QtGui.QMessageBox.Yes: + Receiver.send_message(u'cursor_busy') + Receiver.send_message(u'openlp_process_events') + self.mergeAuthors(author) + self.resetAuthors() + Receiver.send_message(u'songs_load_list') + Receiver.send_message(u'cursor_normal') + else: + # We restore the author's old first and last name as well as + # his display name. + author.first_name = temp_first_name + author.last_name = temp_last_name + author.display_name = temp_display_name + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', + 'Could not save your modified author, because the ' + 'author already exists.')) def onTopicEditButtonClick(self): topic_id = self._getCurrentItemId(self.topicsListWidget) - if topic_id != -1: - topic = self.manager.get_object(Topic, topic_id) - self.topicform.nameEdit.setText(topic.name) - # Save the topic's name for the case that he has to be restored. - temp_name = topic.name - if self.topicform.exec_(False): - topic.name = unicode(self.topicform.nameEdit.text()) - if self.checkTopic(topic, True): - if self.manager.save_object(topic): - self.resetTopics() - else: - criticalErrorMessageBox( - message=translate('SongsPlugin.SongMaintenanceForm', - 'Could not save your changes.')) - elif criticalErrorMessageBox( - message=unicode(translate('SongsPlugin.SongMaintenanceForm', - 'The topic %s already exists. Would you like to make songs ' - 'with topic %s use the existing topic %s?')) % (topic.name, - temp_name, topic.name), - parent=self, question=True) == QtGui.QMessageBox.Yes: - self.mergeTopics(topic) + if topic_id == -1: + return + topic = self.manager.get_object(Topic, topic_id) + self.topicform.nameEdit.setText(topic.name) + # Save the topic's name for the case that he has to be restored. + temp_name = topic.name + if self.topicform.exec_(False): + topic.name = unicode(self.topicform.nameEdit.text()) + if self.checkTopic(topic, True): + if self.manager.save_object(topic): self.resetTopics() else: - # We restore the topics's old name. - topic.name = temp_name criticalErrorMessageBox( message=translate('SongsPlugin.SongMaintenanceForm', - 'Could not save your modified topic, because it ' - 'already exists.')) + 'Could not save your changes.')) + elif criticalErrorMessageBox( + message=unicode(translate('SongsPlugin.SongMaintenanceForm', + 'The topic %s already exists. Would you like to make songs ' + 'with topic %s use the existing topic %s?')) % (topic.name, + temp_name, topic.name), + parent=self, question=True) == QtGui.QMessageBox.Yes: + Receiver.send_message(u'cursor_busy') + Receiver.send_message(u'openlp_process_events') + self.mergeTopics(topic) + self.resetTopics() + Receiver.send_message(u'cursor_normal') + else: + # We restore the topics's old name. + topic.name = temp_name + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', + 'Could not save your modified topic, because it ' + 'already exists.')) def onBookEditButtonClick(self): book_id = self._getCurrentItemId(self.booksListWidget) - if book_id != -1: - book = self.manager.get_object(Book, book_id) - if book.publisher is None: - book.publisher = u'' - self.bookform.nameEdit.setText(book.name) - self.bookform.publisherEdit.setText(book.publisher) - # Save the book's name and publisher for the case that they have to - # be restored. - temp_name = book.name - temp_publisher = book.publisher - if self.bookform.exec_(False): - book.name = unicode(self.bookform.nameEdit.text()) - book.publisher = unicode(self.bookform.publisherEdit.text()) - if self.checkBook(book, True): - if self.manager.save_object(book): - self.resetBooks() - else: - criticalErrorMessageBox( - message=translate('SongsPlugin.SongMaintenanceForm', - 'Could not save your changes.')) - elif criticalErrorMessageBox( - message=unicode(translate('SongsPlugin.SongMaintenanceForm', - 'The book %s already exists. Would you like to make songs ' - 'with book %s use the existing book %s?')) % (book.name, - temp_name, book.name), - parent=self, question=True) == QtGui.QMessageBox.Yes: - self.mergeBooks(book) + if book_id == -1: + return + book = self.manager.get_object(Book, book_id) + if book.publisher is None: + book.publisher = u'' + self.bookform.nameEdit.setText(book.name) + self.bookform.publisherEdit.setText(book.publisher) + # Save the book's name and publisher for the case that they have to + # be restored. + temp_name = book.name + temp_publisher = book.publisher + if self.bookform.exec_(False): + book.name = unicode(self.bookform.nameEdit.text()) + book.publisher = unicode(self.bookform.publisherEdit.text()) + if self.checkBook(book, True): + if self.manager.save_object(book): self.resetBooks() else: - # We restore the book's old name and publisher. - book.name = temp_name - book.publisher = temp_publisher + criticalErrorMessageBox( + message=translate('SongsPlugin.SongMaintenanceForm', + 'Could not save your changes.')) + elif criticalErrorMessageBox( + message=unicode(translate('SongsPlugin.SongMaintenanceForm', + 'The book %s already exists. Would you like to make songs ' + 'with book %s use the existing book %s?')) % (book.name, + temp_name, book.name), + parent=self, question=True) == QtGui.QMessageBox.Yes: + Receiver.send_message(u'cursor_busy') + Receiver.send_message(u'openlp_process_events') + self.mergeBooks(book) + self.resetBooks() + Receiver.send_message(u'cursor_normal') + else: + # We restore the book's old name and publisher. + book.name = temp_name + book.publisher = temp_publisher def mergeAuthors(self, old_author): """ diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 64523fd3a..84e7a3841 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -314,11 +314,11 @@ class EasiSlidesImport(SongImport): pass def _listHas(self, lst, subitems): - for i in subitems: - if type(lst) == type({}) and lst.has_key(i): - lst = lst[i] - elif type(lst) == type([]) and i in lst: - lst = lst[i] + for subitem in subitems: + if isinstance(lst, dict) and lst.has_key(subitem): + lst = lst[subitem] + elif isinstance(lst, list) and subitem in lst: + lst = lst[subitem] else: return False return True diff --git a/openlp/plugins/songs/lib/importer.py b/openlp/plugins/songs/lib/importer.py index 91d3d7e6f..6f566ff4f 100644 --- a/openlp/plugins/songs/lib/importer.py +++ b/openlp/plugins/songs/lib/importer.py @@ -105,7 +105,7 @@ class SongFormat(object): return None @staticmethod - def list(): + def get_formats_list(): """ Return a list of the supported song formats. """ diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 625f99f18..dc51f97f5 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -68,9 +68,6 @@ class SongMediaItem(MediaManagerItem): self.editItem = None self.whitespace = re.compile(r'\W+', re.UNICODE) - def requiredIcons(self): - MediaManagerItem.requiredIcons(self) - def addEndHeaderBar(self): self.addToolbarSeparator() ## Song Maintenance Button ## diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index 45d1ce5b9..32315130a 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -66,31 +66,34 @@ class OooImport(SongImport): QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) def do_import(self): - self.abort = False + self.stop_import_flag = False self.import_wizard.progressBar.setMaximum(0) self.start_ooo() for filename in self.filenames: - if self.abort: + if self.stop_import_flag: self.import_wizard.incrementProgressBar(u'Import cancelled', 0) return filename = unicode(filename) if os.path.isfile(filename): self.open_ooo_file(filename) if self.document: - if self.document.supportsService( - "com.sun.star.presentation.PresentationDocument"): - self.process_pres() - if self.document.supportsService( - "com.sun.star.text.TextDocument"): - self.process_doc() + self.process_ooo_document() self.close_ooo_file() self.close_ooo() self.import_wizard.progressBar.setMaximum(1) self.import_wizard.incrementProgressBar(u'', 1) return True - def stop_import(self): - self.abort = True + def process_ooo_document(self): + """ + Handle the import process for OpenOffice files. This method facilitates + allowing subclasses to handle specific types of OpenOffice files. + """ + if self.document.supportsService( + "com.sun.star.presentation.PresentationDocument"): + self.process_pres() + if self.document.supportsService("com.sun.star.text.TextDocument"): + self.process_doc() def start_ooo(self): """ @@ -180,7 +183,7 @@ class OooImport(SongImport): slides = doc.getDrawPages() text = u'' for slide_no in range(slides.getCount()): - if self.abort: + if self.stop_import_flag: self.import_wizard.incrementProgressBar(u'Import cancelled', 0) return slide = slides.getByIndex(slide_no) diff --git a/openlp/plugins/songs/lib/sofimport.py b/openlp/plugins/songs/lib/sofimport.py index 8475b0824..cfb80caa3 100644 --- a/openlp/plugins/songs/lib/sofimport.py +++ b/openlp/plugins/songs/lib/sofimport.py @@ -39,9 +39,7 @@ from oooimport import OooImport if os.name == u'nt': BOLD = 150.0 ITALIC = 2 - PAGE_BEFORE = 4 - PAGE_AFTER = 5 - PAGE_BOTH = 6 + from oooimport import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH else: try: from com.sun.star.awt.FontWeight import BOLD @@ -75,23 +73,11 @@ class SofImport(OooImport): """ OooImport.__init__(self, master_manager, **kwargs) - def do_import(self): - self.abort = False - self.start_ooo() - for filename in self.filenames: - if self.abort: - self.import_wizard.incrementProgressBar(u'Import cancelled', 0) - return - filename = unicode(filename) - if os.path.isfile(filename): - self.open_ooo_file(filename) - if self.document: - self.process_sof_file() - self.close_ooo_file() - self.close_ooo() - self.import_wizard.progressBar.setMaximum(1) - self.import_wizard.incrementProgressBar(u'', 1) - return True + def process_ooo_document(self): + """ + Handle the import process for SoF files. + """ + self.process_sof_file() def process_sof_file(self): """ @@ -101,7 +87,7 @@ class SofImport(OooImport): self.new_song() paragraphs = self.document.getText().createEnumeration() while paragraphs.hasMoreElements(): - if self.abort: + if self.stop_import_flag: self.import_wizard.incrementProgressBar(u'Import cancelled', 0) return paragraph = paragraphs.nextElement() @@ -318,7 +304,6 @@ class SofImport(OooImport): self.currentverse = u'' self.is_chorus = False - def uncap_text(self, text): """ Words in the title are in all capitals, so we lowercase them. diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index cab0aacf6..592aa7ac1 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -227,7 +227,7 @@ class SongImport(QtCore.QObject): self.versecounts[versetag[0]] = int(versetag[1:]) self.verses.append([versetag, versetext.rstrip(), lang]) self.verse_order_list.append(versetag) - if versetag.startswith(u'V') and self.contains_verse(u'C1'): + if versetag.startswith(u'V') and u'C1' in self.verse_order_list: self.verse_order_list.append(u'C1') def repeat_verse(self): @@ -236,9 +236,6 @@ class SongImport(QtCore.QObject): """ self.verse_order_list.append(self.verse_order_list[-1]) - def contains_verse(self, versetag): - return versetag in self.verse_order_list - def check_complete(self): """ Check the mandatory fields are entered (i.e. title and a verse) diff --git a/openlp/plugins/songusage/forms/songusagedeleteform.py b/openlp/plugins/songusage/forms/songusagedeleteform.py index f83ec8c82..c03fe15a3 100644 --- a/openlp/plugins/songusage/forms/songusagedeleteform.py +++ b/openlp/plugins/songusage/forms/songusagedeleteform.py @@ -26,7 +26,7 @@ from PyQt4 import QtGui -from openlp.core.lib import translate +from openlp.core.lib import translate, Receiver from openlp.plugins.songusage.lib.db import SongUsageItem from songusagedeletedialog import Ui_SongUsageDeleteDialog @@ -55,4 +55,9 @@ class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog): deleteDate = self.deleteCalendar.selectedDate().toPyDate() self.manager.delete_all_objects(SongUsageItem, SongUsageItem.usagedate <= deleteDate) - self.close() \ No newline at end of file + Receiver.send_message(u'openlp_information_message', { + u'title': translate('SongUsagePlugin.SongUsageDeleteForm', + 'Deletion Successful'), + u'message': translate('SongUsagePlugin.SongUsageDeleteForm', + 'All requested data has been deleted successfully. ')}) + self.close() diff --git a/openlp/plugins/songusage/forms/songusagedetaildialog.py b/openlp/plugins/songusage/forms/songusagedetaildialog.py index 9383e147d..ec1f69d7e 100644 --- a/openlp/plugins/songusage/forms/songusagedetaildialog.py +++ b/openlp/plugins/songusage/forms/songusagedetaildialog.py @@ -60,10 +60,12 @@ class Ui_SongUsageDetailDialog(object): self.horizontalLayout.setObjectName(u'horizontalLayout') self.fileLineEdit = QtGui.QLineEdit(self.fileGroupBox) self.fileLineEdit.setObjectName(u'fileLineEdit') + self.fileLineEdit.setReadOnly(True) + self.fileLineEdit.setEnabled(False) self.horizontalLayout.addWidget(self.fileLineEdit) self.saveFilePushButton = QtGui.QPushButton(self.fileGroupBox) self.saveFilePushButton.setIcon( - build_icon(u':/general/general_load.png')) + build_icon(u':/general/general_open.png')) self.saveFilePushButton.setObjectName(u'saveFilePushButton') self.horizontalLayout.addWidget(self.saveFilePushButton) self.verticalLayout4.addLayout(self.horizontalLayout) @@ -96,4 +98,4 @@ class Ui_SongUsageDetailDialog(object): translate('SongUsagePlugin.SongUsageDetailForm', 'to')) self.fileGroupBox.setTitle( translate('SongUsagePlugin.SongUsageDetailForm', - 'Report Location')) \ No newline at end of file + 'Report Location')) diff --git a/openlp/plugins/songusage/forms/songusagedetailform.py b/openlp/plugins/songusage/forms/songusagedetailform.py index 8588ddcff..ff8ec4858 100644 --- a/openlp/plugins/songusage/forms/songusagedetailform.py +++ b/openlp/plugins/songusage/forms/songusagedetailform.py @@ -30,7 +30,8 @@ import os from PyQt4 import QtCore, QtGui from sqlalchemy.sql import and_ -from openlp.core.lib import SettingsManager, translate +from openlp.core.lib import SettingsManager, translate, Receiver, \ + check_directory_exists from openlp.plugins.songusage.lib.db import SongUsageItem from songusagedetaildialog import Ui_SongUsageDetailDialog @@ -51,49 +52,74 @@ class SongUsageDetailForm(QtGui.QDialog, Ui_SongUsageDetailDialog): self.setupUi(self) def initialise(self): + """ + We need to set up the screen + """ year = QtCore.QDate().currentDate().year() if QtCore.QDate().currentDate().month() < 9: year -= 1 - toDate = QtCore.QDate(year, 8, 31) - fromDate = QtCore.QDate(year - 1, 9, 1) + toDate = QtCore.QSettings().value( + u'songusage/to date', + QtCore.QVariant(QtCore.QDate(year, 8, 31))).toDate() + fromDate = QtCore.QSettings().value( + u'songusage/from date', + QtCore.QVariant(QtCore.QDate(year - 1, 9, 1))).toDate() self.fromDate.setSelectedDate(fromDate) self.toDate.setSelectedDate(toDate) self.fileLineEdit.setText( SettingsManager.get_last_dir(self.plugin.settingsSection, 1)) def defineOutputLocation(self): + """ + Triggered when the Directory selection button is pressed + """ path = QtGui.QFileDialog.getExistingDirectory(self, translate('SongUsagePlugin.SongUsageDetailForm', 'Output File Location'), SettingsManager.get_last_dir(self.plugin.settingsSection, 1)) path = unicode(path) - if path != u'': + if path: SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1) self.fileLineEdit.setText(path) def accept(self): - log.debug(u'Detailed report generated') + """ + Ok was pressed so lets save the data and run the report + """ + log.debug(u'accept') + path = unicode(self.fileLineEdit.text()) + check_directory_exists(path) filename = unicode(translate('SongUsagePlugin.SongUsageDetailForm', 'usage_detail_%s_%s.txt')) % ( self.fromDate.selectedDate().toString(u'ddMMyyyy'), self.toDate.selectedDate().toString(u'ddMMyyyy')) + QtCore.QSettings().setValue(u'songusage/from date', + QtCore.QVariant(self.fromDate.selectedDate())) + QtCore.QSettings().setValue(u'songusage/to date', + QtCore.QVariant(self.toDate.selectedDate())) usage = self.plugin.manager.get_all_objects( SongUsageItem, and_( SongUsageItem.usagedate >= self.fromDate.selectedDate().toPyDate(), SongUsageItem.usagedate < self.toDate.selectedDate().toPyDate()), [SongUsageItem.usagedate, SongUsageItem.usagetime]) - outname = os.path.join(unicode(self.fileLineEdit.text()), filename) - file = None + outname = os.path.join(path, filename) + fileHandle = None try: - file = open(outname, u'w') + fileHandle = open(outname, u'w') for instance in usage: record = u'\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n' % ( instance.usagedate, instance.usagetime, instance.title, instance.copyright, instance.ccl_number, instance.authors) - file.write(record) + fileHandle.write(record.encode(u'utf-8')) + Receiver.send_message(u'openlp_information_message', { + u'title': translate('SongUsagePlugin.SongUsageDetailForm', + 'Report Creation'), + u'message': unicode(translate( + 'SongUsagePlugin.SongUsageDetailForm', 'Report \n%s \n' + 'has been successfully created. ')) % outname}) except IOError: log.exception(u'Failed to write out song usage records') finally: - if file: - file.close() + if fileHandle: + fileHandle.close() self.close()