diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index ce0907fbb..276563eba 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -243,7 +243,7 @@ class ServiceItem(object): file to represent this item. """ service_header = { - u'name': self.name.lower(), + u'name': self.name, u'plugin': self.name, u'theme': self.theme, u'title': self.title, @@ -392,10 +392,16 @@ class ServiceItem(object): """ Returns the title of the raw frame """ - return self._raw_frames[row][u'title'] + try: + return self._raw_frames[row][u'title'] + except IndexError: + return u'' def get_frame_path(self, row=0): """ Returns the path of the raw frame """ - return self._raw_frames[row][u'path'] + try: + return self._raw_frames[row][u'path'] + except IndexError: + return u'' diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index 35b62ddda..70517b34d 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -261,7 +261,7 @@ class ThemeXML(object): def add_font(self, name, color, size, override, fonttype=u'main', bold=u'False', italics=u'False', line_adjustment=0, xpos=0, ypos=0, width=0, height=0 , outline=u'False', - outline_color=u'#ffffff', outline_pixel=2, shadow=u'False', + outline_color=u'#ffffff', outline_pixel=2, shadow=u'False', shadow_color=u'#ffffff', shadow_pixel=5): """ Add a Font. diff --git a/openlp/core/lib/toolbar.py b/openlp/core/lib/toolbar.py index 763e6bf67..f2c7f1b0d 100644 --- a/openlp/core/lib/toolbar.py +++ b/openlp/core/lib/toolbar.py @@ -51,7 +51,8 @@ class OpenLPToolbar(QtGui.QToolBar): log.debug(u'Init done') def addToolbarButton(self, title, icon, tooltip=None, slot=None, - checkable=False): + checkable=False, shortcut=0, alternate=0, + context=QtCore.Qt.WidgetShortcut): """ A method to help developers easily add a button to the toolbar. @@ -72,6 +73,15 @@ class OpenLPToolbar(QtGui.QToolBar): ``checkable`` If *True* the button has two, *off* and *on*, states. Default is *False*, which means the buttons has only one state. + + ``shortcut`` + The primary shortcut for this action + + ``alternate`` + The alternate shortcut for this action + + ``context`` + Specify the context in which this shortcut is valid """ newAction = None if icon: @@ -93,6 +103,8 @@ class OpenLPToolbar(QtGui.QToolBar): QtCore.QObject.connect(newAction, QtCore.SIGNAL(u'toggled(bool)'), slot) self.actions[title] = newAction + newAction.setShortcuts([shortcut, alternate]) + newAction.setShortcutContext(context) return newAction def addToolbarSeparator(self, handle): diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index ec5ab7b3f..b371d951e 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -54,45 +54,6 @@ class DisplayWidget(QtGui.QGraphicsView): QtGui.QGraphicsView.__init__(self) self.parent = parent self.live = live - self.hotkey_map = { - QtCore.Qt.Key_Return: 'servicemanager_next_item', - QtCore.Qt.Key_Space: 'slidecontroller_live_next_noloop', - QtCore.Qt.Key_Enter: 'slidecontroller_live_next_noloop', - QtCore.Qt.Key_0: 'servicemanager_next_item', - QtCore.Qt.Key_Backspace: 'slidecontroller_live_previous_noloop'} - self.setStyleSheet(u'border: none;') - - def keyPressEvent(self, event): - """ - Handle key events from display screen - """ - # Key events only needed for live - if not self.live: - return - if isinstance(event, QtGui.QKeyEvent): - # Here accept the event and do something - if event.key() == QtCore.Qt.Key_Up: - Receiver.send_message(u'slidecontroller_live_previous') - event.accept() - elif event.key() == QtCore.Qt.Key_Down: - Receiver.send_message(u'slidecontroller_live_next') - event.accept() - elif event.key() == QtCore.Qt.Key_PageUp: - Receiver.send_message(u'slidecontroller_live_first') - event.accept() - elif event.key() == QtCore.Qt.Key_PageDown: - Receiver.send_message(u'slidecontroller_live_last') - event.accept() - elif event.key() in self.hotkey_map: - Receiver.send_message(self.hotkey_map[event.key()]) - event.accept() - elif event.key() == QtCore.Qt.Key_Escape: - self.setVisible(False) - self.videoStop() - event.accept() - event.ignore() - else: - event.ignore() class MainDisplay(DisplayWidget): @@ -176,11 +137,10 @@ class MainDisplay(DisplayWidget): painter_image.begin(initialFrame) painter_image.fillRect(initialFrame.rect(), QtCore.Qt.white) painter_image.drawImage( - (self.screens.current[u'size'].width() \ - - splash_image.width()) / 2, - (self.screens.current[u'size'].height() \ - - splash_image.height()) / 2, - splash_image) + (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, @@ -280,7 +240,10 @@ class MainDisplay(DisplayWidget): Used after Image plugin has changed the background """ log.debug(u'resetImage') - self.displayImage(self.serviceItem.bg_image_bytes) + if hasattr(self, u'serviceItem'): + self.displayImage(self.serviceItem.bg_image_bytes) + else: + self.displayImage(None) # Update the preview frame. Receiver.send_message(u'maindisplay_active') @@ -382,13 +345,11 @@ class MainDisplay(DisplayWidget): Generates a preview of the image displayed. """ log.debug(u'preview for %s', self.isLive) - # We must have a service item to preview - if not hasattr(self, u'serviceItem'): - return Receiver.send_message(u'openlp_process_events') - if self.isLive: + # We must have a service item to preview + if self.isLive and hasattr(self, u'serviceItem'): # Wait for the fade to finish before geting the preview. - # Important otherwise preview will have incorrect text if at all ! + # Important otherwise preview will have incorrect text if at all! if self.serviceItem.themedata and \ self.serviceItem.themedata.display_slide_transition: while self.frame.evaluateJavaScript(u'show_text_complete()') \ @@ -401,9 +362,8 @@ class MainDisplay(DisplayWidget): # if was hidden keep it hidden if self.isLive: self.setVisible(True) - # if was hidden keep it hidden - if self.hideMode and self.isLive: - self.hideDisplay(self.hideMode) + if self.hideMode: + self.hideDisplay(self.hideMode) preview = QtGui.QImage(self.screen[u'size'].width(), self.screen[u'size'].height(), QtGui.QImage.Format_ARGB32_Premultiplied) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index f2545766e..db9d4f9d5 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -59,23 +59,23 @@ MEDIA_MANAGER_STYLE = """ """ class Ui_MainWindow(object): - def setupUi(self, MainWindow): + def setupUi(self, mainWindow): """ Set up the user interface """ - MainWindow.setObjectName(u'MainWindow') - MainWindow.resize(self.settingsmanager.width, + mainWindow.setObjectName(u'MainWindow') + mainWindow.resize(self.settingsmanager.width, self.settingsmanager.height) - MainWindow.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) - MainWindow.setDockNestingEnabled(True) + mainWindow.setWindowIcon(build_icon(u':/icon/openlp-logo-16x16.png')) + mainWindow.setDockNestingEnabled(True) # Set up the main container, which contains all the other form widgets. - self.MainContent = QtGui.QWidget(MainWindow) + self.MainContent = QtGui.QWidget(mainWindow) self.MainContent.setObjectName(u'MainContent') self.MainContentLayout = QtGui.QHBoxLayout(self.MainContent) self.MainContentLayout.setSpacing(0) self.MainContentLayout.setMargin(0) self.MainContentLayout.setObjectName(u'MainContentLayout') - MainWindow.setCentralWidget(self.MainContent) + mainWindow.setCentralWidget(self.MainContent) self.ControlSplitter = QtGui.QSplitter(self.MainContent) self.ControlSplitter.setOrientation(QtCore.Qt.Horizontal) self.ControlSplitter.setObjectName(u'ControlSplitter') @@ -92,7 +92,7 @@ class Ui_MainWindow(object): QtCore.QVariant(True)).toBool() self.liveController.Panel.setVisible(liveVisible) # Create menu - self.MenuBar = QtGui.QMenuBar(MainWindow) + self.MenuBar = QtGui.QMenuBar(mainWindow) self.MenuBar.setObjectName(u'MenuBar') self.FileMenu = QtGui.QMenu(self.MenuBar) self.FileMenu.setObjectName(u'FileMenu') @@ -116,16 +116,16 @@ class Ui_MainWindow(object): # Help Menu self.HelpMenu = QtGui.QMenu(self.MenuBar) self.HelpMenu.setObjectName(u'HelpMenu') - MainWindow.setMenuBar(self.MenuBar) - self.StatusBar = QtGui.QStatusBar(MainWindow) + mainWindow.setMenuBar(self.MenuBar) + self.StatusBar = QtGui.QStatusBar(mainWindow) self.StatusBar.setObjectName(u'StatusBar') - MainWindow.setStatusBar(self.StatusBar) + mainWindow.setStatusBar(self.StatusBar) self.DefaultThemeLabel = QtGui.QLabel(self.StatusBar) self.DefaultThemeLabel.setObjectName(u'DefaultThemeLabel') self.StatusBar.addPermanentWidget(self.DefaultThemeLabel) # Create the MediaManager self.MediaManagerDock = OpenLPDockWidget( - MainWindow, u'MediaManagerDock', + mainWindow, u'MediaManagerDock', build_icon(u':/system/system_mediamanager.png')) self.MediaManagerDock.setStyleSheet(MEDIA_MANAGER_STYLE) self.MediaManagerDock.setMinimumWidth( @@ -134,127 +134,127 @@ class Ui_MainWindow(object): self.MediaToolBox = QtGui.QToolBox(self.MediaManagerDock) self.MediaToolBox.setObjectName(u'MediaToolBox') self.MediaManagerDock.setWidget(self.MediaToolBox) - MainWindow.addDockWidget(QtCore.Qt.LeftDockWidgetArea, + mainWindow.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.MediaManagerDock) # Create the service manager self.ServiceManagerDock = OpenLPDockWidget( - MainWindow, u'ServiceManagerDock', + mainWindow, u'ServiceManagerDock', build_icon(u':/system/system_servicemanager.png')) self.ServiceManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ServiceManagerContents = ServiceManager(MainWindow, + self.ServiceManagerContents = ServiceManager(mainWindow, self.ServiceManagerDock) self.ServiceManagerDock.setWidget(self.ServiceManagerContents) - MainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, + mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.ServiceManagerDock) # Create the theme manager self.ThemeManagerDock = OpenLPDockWidget( - MainWindow, u'ThemeManagerDock', + mainWindow, u'ThemeManagerDock', build_icon(u':/system/system_thememanager.png')) self.ThemeManagerDock.setMinimumWidth( self.settingsmanager.mainwindow_right) - self.ThemeManagerContents = ThemeManager(MainWindow, + self.ThemeManagerContents = ThemeManager(mainWindow, self.ThemeManagerDock) self.ThemeManagerContents.setObjectName(u'ThemeManagerContents') self.ThemeManagerDock.setWidget(self.ThemeManagerContents) - MainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, + mainWindow.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.ThemeManagerDock) # Create the menu items - self.FileNewItem = QtGui.QAction(MainWindow) + self.FileNewItem = QtGui.QAction(mainWindow) self.FileNewItem.setIcon(build_icon(u':/general/general_new.png')) self.FileNewItem.setObjectName(u'FileNewItem') - MainWindow.actionList.add_action(self.FileNewItem, u'File') - self.FileOpenItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.FileNewItem, u'File') + self.FileOpenItem = QtGui.QAction(mainWindow) self.FileOpenItem.setIcon(build_icon(u':/general/general_open.png')) self.FileOpenItem.setObjectName(u'FileOpenItem') - MainWindow.actionList.add_action(self.FileOpenItem, u'File') - self.FileSaveItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.FileOpenItem, u'File') + self.FileSaveItem = QtGui.QAction(mainWindow) self.FileSaveItem.setIcon(build_icon(u':/general/general_save.png')) self.FileSaveItem.setObjectName(u'FileSaveItem') - MainWindow.actionList.add_action(self.FileSaveItem, u'File') - self.FileSaveAsItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.FileSaveItem, u'File') + self.FileSaveAsItem = QtGui.QAction(mainWindow) self.FileSaveAsItem.setObjectName(u'FileSaveAsItem') - MainWindow.actionList.add_action(self.FileSaveAsItem, u'File') - self.FileExitItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.FileSaveAsItem, u'File') + self.FileExitItem = QtGui.QAction(mainWindow) self.FileExitItem.setIcon(build_icon(u':/system/system_exit.png')) self.FileExitItem.setObjectName(u'FileExitItem') - MainWindow.actionList.add_action(self.FileExitItem, u'File') - self.ImportThemeItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.FileExitItem, u'File') + self.ImportThemeItem = QtGui.QAction(mainWindow) self.ImportThemeItem.setObjectName(u'ImportThemeItem') - MainWindow.actionList.add_action(self.ImportThemeItem, u'Import') - self.ImportLanguageItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ImportThemeItem, u'Import') + self.ImportLanguageItem = QtGui.QAction(mainWindow) self.ImportLanguageItem.setObjectName(u'ImportLanguageItem') - MainWindow.actionList.add_action(self.ImportLanguageItem, u'Import') - self.ExportThemeItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ImportLanguageItem, u'Import') + self.ExportThemeItem = QtGui.QAction(mainWindow) self.ExportThemeItem.setObjectName(u'ExportThemeItem') - MainWindow.actionList.add_action(self.ExportThemeItem, u'Export') - self.ExportLanguageItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ExportThemeItem, u'Export') + self.ExportLanguageItem = QtGui.QAction(mainWindow) self.ExportLanguageItem.setObjectName(u'ExportLanguageItem') - MainWindow.actionList.add_action(self.ExportLanguageItem, u'Export') - self.ViewMediaManagerItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ExportLanguageItem, u'Export') + self.ViewMediaManagerItem = QtGui.QAction(mainWindow) self.ViewMediaManagerItem.setCheckable(True) self.ViewMediaManagerItem.setChecked(self.MediaManagerDock.isVisible()) self.ViewMediaManagerItem.setIcon( build_icon(u':/system/system_mediamanager.png')) self.ViewMediaManagerItem.setObjectName(u'ViewMediaManagerItem') - self.ViewThemeManagerItem = QtGui.QAction(MainWindow) + self.ViewThemeManagerItem = QtGui.QAction(mainWindow) self.ViewThemeManagerItem.setCheckable(True) self.ViewThemeManagerItem.setChecked(self.ThemeManagerDock.isVisible()) self.ViewThemeManagerItem.setIcon( build_icon(u':/system/system_thememanager.png')) self.ViewThemeManagerItem.setObjectName(u'ViewThemeManagerItem') - MainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View') - self.ViewServiceManagerItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ViewMediaManagerItem, u'View') + self.ViewServiceManagerItem = QtGui.QAction(mainWindow) self.ViewServiceManagerItem.setCheckable(True) self.ViewServiceManagerItem.setChecked( self.ServiceManagerDock.isVisible()) self.ViewServiceManagerItem.setIcon( build_icon(u':/system/system_servicemanager.png')) self.ViewServiceManagerItem.setObjectName(u'ViewServiceManagerItem') - MainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View') - self.ViewPreviewPanel = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ViewServiceManagerItem, u'View') + self.ViewPreviewPanel = QtGui.QAction(mainWindow) self.ViewPreviewPanel.setCheckable(True) self.ViewPreviewPanel.setChecked(previewVisible) self.ViewPreviewPanel.setObjectName(u'ViewPreviewPanel') - MainWindow.actionList.add_action(self.ViewPreviewPanel, u'View') - self.ViewLivePanel = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ViewPreviewPanel, u'View') + self.ViewLivePanel = QtGui.QAction(mainWindow) self.ViewLivePanel.setCheckable(True) self.ViewLivePanel.setChecked(liveVisible) self.ViewLivePanel.setObjectName(u'ViewLivePanel') - MainWindow.actionList.add_action(self.ViewLivePanel, u'View') - self.ModeDefaultItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ViewLivePanel, u'View') + self.ModeDefaultItem = QtGui.QAction(mainWindow) self.ModeDefaultItem.setCheckable(True) self.ModeDefaultItem.setObjectName(u'ModeDefaultItem') - MainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode') - self.ModeSetupItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ModeDefaultItem, u'View Mode') + self.ModeSetupItem = QtGui.QAction(mainWindow) self.ModeSetupItem.setCheckable(True) self.ModeSetupItem.setObjectName(u'ModeLiveItem') - MainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode') - self.ModeLiveItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ModeSetupItem, u'View Mode') + self.ModeLiveItem = QtGui.QAction(mainWindow) self.ModeLiveItem.setCheckable(True) self.ModeLiveItem.setObjectName(u'ModeLiveItem') - MainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode') - self.ModeGroup = QtGui.QActionGroup(MainWindow) + mainWindow.actionList.add_action(self.ModeLiveItem, u'View Mode') + self.ModeGroup = QtGui.QActionGroup(mainWindow) self.ModeGroup.addAction(self.ModeDefaultItem) self.ModeGroup.addAction(self.ModeSetupItem) self.ModeGroup.addAction(self.ModeLiveItem) self.ModeDefaultItem.setChecked(True) - self.ToolsAddToolItem = QtGui.QAction(MainWindow) + self.ToolsAddToolItem = QtGui.QAction(mainWindow) self.ToolsAddToolItem.setIcon(build_icon(u':/tools/tools_add.png')) self.ToolsAddToolItem.setObjectName(u'ToolsAddToolItem') - MainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools') - self.SettingsPluginListItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.ToolsAddToolItem, u'Tools') + self.SettingsPluginListItem = QtGui.QAction(mainWindow) self.SettingsPluginListItem.setIcon( build_icon(u':/system/settings_plugin_list.png')) self.SettingsPluginListItem.setObjectName(u'SettingsPluginListItem') - MainWindow.actionList.add_action(self.SettingsPluginListItem, + mainWindow.actionList.add_action(self.SettingsPluginListItem, u'Settings') # i18n Language Items - self.AutoLanguageItem = QtGui.QAction(MainWindow) + self.AutoLanguageItem = QtGui.QAction(mainWindow) self.AutoLanguageItem.setObjectName(u'AutoLanguageItem') self.AutoLanguageItem.setCheckable(True) - MainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings') - self.LanguageGroup = QtGui.QActionGroup(MainWindow) + mainWindow.actionList.add_action(self.AutoLanguageItem, u'Settings') + self.LanguageGroup = QtGui.QActionGroup(mainWindow) self.LanguageGroup.setExclusive(True) self.LanguageGroup.setObjectName(u'LanguageGroup') self.AutoLanguageItem.setChecked(LanguageManager.auto_language) @@ -262,40 +262,40 @@ class Ui_MainWindow(object): qmList = LanguageManager.get_qm_list() savedLanguage = LanguageManager.get_language() for key in sorted(qmList.keys()): - languageItem = QtGui.QAction(MainWindow) + languageItem = QtGui.QAction(mainWindow) languageItem.setObjectName(key) languageItem.setCheckable(True) if qmList[key] == savedLanguage: languageItem.setChecked(True) add_actions(self.LanguageGroup, [languageItem]) - self.SettingsShortcutsItem = QtGui.QAction(MainWindow) + self.SettingsShortcutsItem = QtGui.QAction(mainWindow) self.SettingsShortcutsItem.setIcon( build_icon(u':/system/system_configure_shortcuts.png')) self.SettingsShortcutsItem.setObjectName(u'SettingsShortcutsItem') - self.SettingsConfigureItem = QtGui.QAction(MainWindow) + self.SettingsConfigureItem = QtGui.QAction(mainWindow) self.SettingsConfigureItem.setIcon( build_icon(u':/system/system_settings.png')) self.SettingsConfigureItem.setObjectName(u'SettingsConfigureItem') - MainWindow.actionList.add_action(self.SettingsShortcutsItem, + mainWindow.actionList.add_action(self.SettingsShortcutsItem, u'Settings') - self.HelpDocumentationItem = QtGui.QAction(MainWindow) + self.HelpDocumentationItem = QtGui.QAction(mainWindow) self.HelpDocumentationItem.setIcon( build_icon(u':/system/system_help_contents.png')) self.HelpDocumentationItem.setObjectName(u'HelpDocumentationItem') self.HelpDocumentationItem.setEnabled(False) - MainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help') - self.HelpAboutItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.HelpDocumentationItem, u'Help') + self.HelpAboutItem = QtGui.QAction(mainWindow) self.HelpAboutItem.setIcon( build_icon(u':/system/system_about.png')) self.HelpAboutItem.setObjectName(u'HelpAboutItem') - MainWindow.actionList.add_action(self.HelpAboutItem, u'Help') - self.HelpOnlineHelpItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.HelpAboutItem, u'Help') + self.HelpOnlineHelpItem = QtGui.QAction(mainWindow) self.HelpOnlineHelpItem.setObjectName(u'HelpOnlineHelpItem') self.HelpOnlineHelpItem.setEnabled(False) - MainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help') - self.HelpWebSiteItem = QtGui.QAction(MainWindow) + mainWindow.actionList.add_action(self.HelpOnlineHelpItem, u'Help') + self.HelpWebSiteItem = QtGui.QAction(mainWindow) self.HelpWebSiteItem.setObjectName(u'HelpWebSiteItem') - MainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help') + mainWindow.actionList.add_action(self.HelpWebSiteItem, u'Help') add_actions(self.FileImportMenu, (self.ImportThemeItem, self.ImportLanguageItem)) add_actions(self.FileExportMenu, @@ -324,21 +324,21 @@ class Ui_MainWindow(object): self.ViewMenu.menuAction(), self.ToolsMenu.menuAction(), self.SettingsMenu.menuAction(), self.HelpMenu.menuAction())) # Initialise the translation - self.retranslateUi(MainWindow) + self.retranslateUi(mainWindow) self.MediaToolBox.setCurrentIndex(0) # Connect up some signals and slots QtCore.QObject.connect(self.FileMenu, QtCore.SIGNAL(u'aboutToShow()'), self.updateFileMenu) QtCore.QObject.connect(self.FileExitItem, - QtCore.SIGNAL(u'triggered()'), MainWindow.close) - QtCore.QMetaObject.connectSlotsByName(MainWindow) + QtCore.SIGNAL(u'triggered()'), mainWindow.close) + QtCore.QMetaObject.connectSlotsByName(mainWindow) - def retranslateUi(self, MainWindow): + def retranslateUi(self, mainWindow): """ Set up the translation system """ - MainWindow.mainTitle = translate('OpenLP.MainWindow', 'OpenLP 2.0') - MainWindow.setWindowTitle(MainWindow.mainTitle) + mainWindow.mainTitle = translate('OpenLP.MainWindow', 'OpenLP 2.0') + mainWindow.setWindowTitle(mainWindow.mainTitle) self.FileMenu.setTitle(translate('OpenLP.MainWindow', '&File')) self.FileImportMenu.setTitle(translate('OpenLP.MainWindow', '&Import')) self.FileExportMenu.setTitle(translate('OpenLP.MainWindow', '&Export')) @@ -450,39 +450,34 @@ class Ui_MainWindow(object): self.HelpAboutItem.setText(translate('OpenLP.MainWindow', '&About')) self.HelpAboutItem.setStatusTip( translate('OpenLP.MainWindow', 'More information about OpenLP')) - self.HelpAboutItem.setShortcut(translate('OpenLP.MainWindow', - 'Ctrl+F1')) + self.HelpAboutItem.setShortcut( + translate('OpenLP.MainWindow', 'Ctrl+F1')) self.HelpOnlineHelpItem.setText( translate('OpenLP.MainWindow', '&Online Help')) self.HelpWebSiteItem.setText( translate('OpenLP.MainWindow', '&Web Site')) self.AutoLanguageItem.setText( translate('OpenLP.MainWindow', '&Auto Detect')) - self.AutoLanguageItem.setStatusTip( - translate('OpenLP.MainWindow', - 'Use the system language, if available.')) + self.AutoLanguageItem.setStatusTip(translate('OpenLP.MainWindow', + 'Use the system language, if available.')) for item in self.LanguageGroup.actions(): item.setText(item.objectName()) item.setStatusTip(unicode(translate('OpenLP.MainWindow', 'Set the interface language to %s')) % item.objectName()) self.ToolsAddToolItem.setText( translate('OpenLP.MainWindow', 'Add &Tool...')) - self.ToolsAddToolItem.setStatusTip( - translate('OpenLP.MainWindow', - 'Add an application to the list of tools.')) + self.ToolsAddToolItem.setStatusTip(translate('OpenLP.MainWindow', + 'Add an application to the list of tools.')) self.ModeDefaultItem.setText( translate('OpenLP.MainWindow', '&Default')) - self.ModeDefaultItem.setStatusTip( - translate('OpenLP.MainWindow', - 'Set the view mode back to the default.')) + self.ModeDefaultItem.setStatusTip(translate('OpenLP.MainWindow', + 'Set the view mode back to the default.')) self.ModeSetupItem.setText(translate('OpenLP.MainWindow', '&Setup')) self.ModeSetupItem.setStatusTip( - translate('OpenLP.MainWindow', - 'Set the view mode to Setup.')) + translate('OpenLP.MainWindow', 'Set the view mode to Setup.')) self.ModeLiveItem.setText(translate('OpenLP.MainWindow', '&Live')) self.ModeLiveItem.setStatusTip( - translate('OpenLP.MainWindow', - 'Set the view mode to Live.')) + translate('OpenLP.MainWindow', 'Set the view mode to Live.')) class MainWindow(QtGui.QMainWindow, Ui_MainWindow): diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 81f514959..b9f9fe53d 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -49,34 +49,6 @@ class ServiceManagerList(QtGui.QTreeWidget): QtGui.QTreeWidget.__init__(self, parent) self.mainwindow = mainwindow - def keyPressEvent(self, event): - if isinstance(event, QtGui.QKeyEvent): - #here accept the event and do something - if event.key() == QtCore.Qt.Key_Enter: - self.mainwindow.makeLive() - event.accept() - elif event.key() == QtCore.Qt.Key_Home: - self.mainwindow.onServiceTop() - event.accept() - elif event.key() == QtCore.Qt.Key_End: - self.mainwindow.onServiceEnd() - event.accept() - elif event.key() == QtCore.Qt.Key_PageUp: - self.mainwindow.onServiceUp() - event.accept() - elif event.key() == QtCore.Qt.Key_PageDown: - self.mainwindow.onServiceDown() - event.accept() - elif event.key() == QtCore.Qt.Key_Up: - self.mainwindow.onMoveSelectionUp() - event.accept() - elif event.key() == QtCore.Qt.Key_Down: - self.mainwindow.onMoveSelectionDown() - event.accept() - event.ignore() - else: - event.ignore() - def mouseMoveEvent(self, event): """ Drag and drop event does not care what data is selected @@ -178,50 +150,72 @@ class ServiceManager(QtGui.QWidget): self.layout.addWidget(self.serviceManagerList) # Add the bottom toolbar self.orderToolbar = OpenLPToolbar(self) - self.orderToolbar.addToolbarButton( + self.serviceManagerList.moveTop = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move to &top'), u':/services/service_top.png', translate('OpenLP.ServiceManager', 'Move item to the top of the service.'), - self.onServiceTop) - self.orderToolbar.addToolbarButton( + self.onServiceTop, shortcut=QtCore.Qt.Key_Home) + self.serviceManagerList.moveUp = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move &up'), u':/services/service_up.png', translate('OpenLP.ServiceManager', 'Move item up one position in the service.'), - self.onServiceUp) - self.orderToolbar.addToolbarButton( + self.onServiceUp, shortcut=QtCore.Qt.Key_PageUp) + self.serviceManagerList.moveDown = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move &down'), u':/services/service_down.png', translate('OpenLP.ServiceManager', 'Move item down one position in the service.'), - self.onServiceDown) - self.orderToolbar.addToolbarButton( + self.onServiceDown, shortcut=QtCore.Qt.Key_PageDown) + self.serviceManagerList.moveBottom = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', 'Move to &bottom'), u':/services/service_bottom.png', translate('OpenLP.ServiceManager', 'Move item to the end of the service.'), - self.onServiceEnd) + self.onServiceEnd, shortcut=QtCore.Qt.Key_End) + self.serviceManagerList.down = self.orderToolbar.addToolbarButton( + translate('OpenLP.ServiceManager', 'Move &down'), + None, + translate('OpenLP.ServiceManager', + 'Moves the selection up the window.'), + self.onMoveSelectionDown, shortcut=QtCore.Qt.Key_Up) + self.serviceManagerList.down.setVisible(False) + self.serviceManagerList.up = self.orderToolbar.addToolbarButton( + translate('OpenLP.ServiceManager', 'Move up'), + None, + translate('OpenLP.ServiceManager', + 'Moves the selection up the window.'), + self.onMoveSelectionUp, shortcut=QtCore.Qt.Key_Up) + self.serviceManagerList.up.setVisible(False) self.orderToolbar.addSeparator() - self.orderToolbar.addToolbarButton( + self.serviceManagerList.delete = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', '&Delete From Service'), u':/general/general_delete.png', translate('OpenLP.ServiceManager', 'Delete the selected item from the service.'), self.onDeleteFromService) self.orderToolbar.addSeparator() - self.orderToolbar.addToolbarButton( + self.serviceManagerList.expand = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', '&Expand all'), u':/services/service_expand_all.png', translate('OpenLP.ServiceManager', 'Expand all the service items.'), self.onExpandAll) - self.orderToolbar.addToolbarButton( + self.serviceManagerList.collapse = self.orderToolbar.addToolbarButton( translate('OpenLP.ServiceManager', '&Collapse all'), u':/services/service_collapse_all.png', translate('OpenLP.ServiceManager', 'Collapse all the service items.'), self.onCollapseAll) + self.orderToolbar.addSeparator() + self.serviceManagerList.makeLive = self.orderToolbar.addToolbarButton( + translate('OpenLP.ServiceManager', 'Go Live'), + u':/general/general_live.png', + translate('OpenLP.ServiceManager', + 'Send the selected item to Live.'), + self.makeLive, shortcut=QtCore.Qt.Key_Enter, + alternate=QtCore.Qt.Key_Return) self.orderToolbar.setObjectName(u'orderToolbar') self.layout.addWidget(self.orderToolbar) # Connect up our signals and slots @@ -245,6 +239,9 @@ class ServiceManager(QtGui.QWidget): QtCore.SIGNAL(u'servicemanager_list_request'), self.listRequest) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_updated'), self.configUpdated) + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'config_screen_changed'), + self.regenerateServiceItems) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_global'), self.themeChange) QtCore.QObject.connect(Receiver.get_receiver(), @@ -289,7 +286,27 @@ class ServiceManager(QtGui.QWidget): self.themeMenu = QtGui.QMenu( translate('OpenLP.ServiceManager', '&Change Item Theme')) self.menu.addMenu(self.themeMenu) - self.configUpdated(True) + self.setServiceHotkeys() + self.serviceManagerList.addActions( + [self.serviceManagerList.moveDown, + self.serviceManagerList.moveUp, + self.serviceManagerList.makeLive, + self.serviceManagerList.moveTop, + self.serviceManagerList.moveBottom, + self.serviceManagerList.up, + self.serviceManagerList.down + ]) + self.configUpdated() + + def setServiceHotkeys(self): + actionList = self.mainwindow.actionList + actionList.add_action(self.serviceManagerList.moveDown, u'Service') + actionList.add_action(self.serviceManagerList.moveUp, u'Service') + actionList.add_action(self.serviceManagerList.moveTop, u'Service') + actionList.add_action(self.serviceManagerList.moveBottom, u'Service') + actionList.add_action(self.serviceManagerList.makeLive, u'Service') + actionList.add_action(self.serviceManagerList.up, u'Service') + actionList.add_action(self.serviceManagerList.down, u'Service') def setModified(self, modified=True): """ @@ -328,15 +345,13 @@ class ServiceManager(QtGui.QWidget): """ return split_filename(self._fileName)[1] - def configUpdated(self, firstTime=False): + def configUpdated(self): """ Triggered when Config dialog is updated. """ self.expandTabs = QtCore.QSettings().value( u'advanced/expand service item', QtCore.QVariant(u'False')).toBool() - if not firstTime: - self.regenerateServiceItems() def supportedSuffixes(self, suffix): self.suffixes.append(suffix) @@ -793,17 +808,17 @@ class ServiceManager(QtGui.QWidget): self.repaintServiceList(0, 0) self.setModified(True) - def repaintServiceList(self, serviceItem, serviceItemCount): + def repaintServiceList(self, serviceItem, serviceItemChild): """ Clear the existing service list and prepaint all the items. This is used when moving items as the move takes place in a supporting list, and when regenerating all the items due to theme changes. ``serviceItem`` - The item which changed. + The item which changed. (int) - ``serviceItemCount`` - The number of items in the service. + ``serviceItemChild`` + The child of the ``serviceItem``, which will be selected. (int) """ # Correct order of items in array count = 1 @@ -836,17 +851,17 @@ class ServiceManager(QtGui.QWidget): treewidgetitem.setToolTip(0, serviceitem.notes) treewidgetitem.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(item[u'order'])) + # Add the children to their parent treewidgetitem. for count, frame in enumerate(serviceitem.get_frames()): - treewidgetitem1 = QtGui.QTreeWidgetItem(treewidgetitem) + child = QtGui.QTreeWidgetItem(treewidgetitem) text = frame[u'title'].replace(u'\n', u' ') - treewidgetitem1.setText(0, text[:40]) - treewidgetitem1.setData(0, QtCore.Qt.UserRole, - QtCore.QVariant(count)) - if serviceItem == itemcount and serviceItemCount == count: - #preserve expanding status as setCurrentItem sets it to True - temp = item[u'expanded'] - self.serviceManagerList.setCurrentItem(treewidgetitem1) - item[u'expanded'] = temp + child.setText(0, text[:40]) + child.setData(0, QtCore.Qt.UserRole, QtCore.QVariant(count)) + if serviceItem == itemcount: + if item[u'expanded'] and serviceItemChild == count: + self.serviceManagerList.setCurrentItem(child) + elif serviceItemChild == -1: + self.serviceManagerList.setCurrentItem(treewidgetitem) treewidgetitem.setExpanded(item[u'expanded']) def validateItem(self, serviceItem): @@ -957,7 +972,7 @@ class ServiceManager(QtGui.QWidget): if replace: item.merge(self.serviceItems[sitem][u'service_item']) self.serviceItems[sitem][u'service_item'] = item - self.repaintServiceList(sitem + 1, 0) + self.repaintServiceList(sitem, 0) self.mainwindow.liveController.replaceServiceManagerItem(item) else: # nothing selected for dnd @@ -1024,7 +1039,7 @@ class ServiceManager(QtGui.QWidget): ItemCapabilities.AllowsPreview): self.mainwindow.previewController.addServiceManagerItem( self.serviceItems[item][u'service_item'], 0) - self.mainwindow.liveController.PreviewListWidget.setFocus() + self.mainwindow.liveController.previewListWidget.setFocus() else: criticalErrorMessageBox( translate('OpenLP.ServiceManager', 'Missing Display Handler'), @@ -1045,11 +1060,16 @@ class ServiceManager(QtGui.QWidget): def findServiceItem(self): """ - Finds a ServiceItem in the list + 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:: + + (1, 2) """ items = self.serviceManagerList.selectedItems() pos = 0 - count = 0 + count = -1 for item in items: parentitem = item.parent() if parentitem is None: @@ -1081,7 +1101,7 @@ class ServiceManager(QtGui.QWidget): """ link = event.mimeData() if link.hasText(): - plugin = event.mimeData().text() + plugin = unicode(event.mimeData().text()) item = self.serviceManagerList.itemAt(event.pos()) # ServiceManager started the drag and drop if plugin == u'ServiceManager': diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 1563b7dbe..7266d197c 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -42,36 +42,8 @@ class SlideList(QtGui.QTableWidget): events. """ def __init__(self, parent=None, name=None): - QtGui.QTableWidget.__init__(self, parent.Controller) + QtGui.QTableWidget.__init__(self, parent.controller) self.parent = parent - self.hotkeyMap = { - QtCore.Qt.Key_Return: 'servicemanager_next_item', - QtCore.Qt.Key_Space: 'slidecontroller_live_next_noloop', - QtCore.Qt.Key_Enter: 'slidecontroller_live_next_noloop', - QtCore.Qt.Key_0: 'servicemanager_next_item', - QtCore.Qt.Key_Backspace: 'slidecontroller_live_previous_noloop'} - - def keyPressEvent(self, event): - if isinstance(event, QtGui.QKeyEvent): - #here accept the event and do something - if event.key() == QtCore.Qt.Key_Up: - self.parent.onSlideSelectedPrevious() - event.accept() - elif event.key() == QtCore.Qt.Key_Down: - self.parent.onSlideSelectedNext() - event.accept() - elif event.key() == QtCore.Qt.Key_PageUp: - self.parent.onSlideSelectedFirst() - event.accept() - elif event.key() == QtCore.Qt.Key_PageDown: - self.parent.onSlideSelectedLast() - event.accept() - elif event.key() in self.hotkeyMap and self.parent.isLive: - Receiver.send_message(self.hotkeyMap[event.key()]) - event.accept() - event.ignore() - else: - event.ignore() class SlideController(QtGui.QWidget): @@ -108,152 +80,154 @@ class SlideController(QtGui.QWidget): self.Panel = QtGui.QWidget(parent.ControlSplitter) self.slideList = {} # Layout for holding panel - self.PanelLayout = QtGui.QVBoxLayout(self.Panel) - self.PanelLayout.setSpacing(0) - self.PanelLayout.setMargin(0) + self.panelLayout = QtGui.QVBoxLayout(self.Panel) + self.panelLayout.setSpacing(0) + self.panelLayout.setMargin(0) # Type label for the top of the slide controller - self.TypeLabel = QtGui.QLabel(self.Panel) + self.typeLabel = QtGui.QLabel(self.Panel) if self.isLive: - self.TypeLabel.setText(translate('OpenLP.SlideController', 'Live')) + self.typeLabel.setText(translate('OpenLP.SlideController', 'Live')) self.split = 1 self.typePrefix = u'live' else: - self.TypeLabel.setText(translate('OpenLP.SlideController', + self.typeLabel.setText(translate('OpenLP.SlideController', 'Preview')) self.split = 0 self.typePrefix = u'preview' - self.TypeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;') - self.TypeLabel.setAlignment(QtCore.Qt.AlignCenter) - self.PanelLayout.addWidget(self.TypeLabel) + self.typeLabel.setStyleSheet(u'font-weight: bold; font-size: 12pt;') + self.typeLabel.setAlignment(QtCore.Qt.AlignCenter) + self.panelLayout.addWidget(self.typeLabel) # Splitter - self.Splitter = QtGui.QSplitter(self.Panel) - self.Splitter.setOrientation(QtCore.Qt.Vertical) - self.PanelLayout.addWidget(self.Splitter) + self.splitter = QtGui.QSplitter(self.Panel) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.panelLayout.addWidget(self.splitter) # Actual controller section - self.Controller = QtGui.QWidget(self.Splitter) - self.Controller.setGeometry(QtCore.QRect(0, 0, 100, 536)) - self.Controller.setSizePolicy( + self.controller = QtGui.QWidget(self.splitter) + self.controller.setGeometry(QtCore.QRect(0, 0, 100, 536)) + self.controller.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Maximum)) - self.ControllerLayout = QtGui.QVBoxLayout(self.Controller) - self.ControllerLayout.setSpacing(0) - self.ControllerLayout.setMargin(0) + self.controllerLayout = QtGui.QVBoxLayout(self.controller) + self.controllerLayout.setSpacing(0) + self.controllerLayout.setMargin(0) # Controller list view - self.PreviewListWidget = SlideList(self) - self.PreviewListWidget.setColumnCount(1) - self.PreviewListWidget.horizontalHeader().setVisible(False) - self.PreviewListWidget.setColumnWidth( - 0, self.Controller.width()) - self.PreviewListWidget.isLive = self.isLive - self.PreviewListWidget.setObjectName(u'PreviewListWidget') - self.PreviewListWidget.setSelectionBehavior(1) - self.PreviewListWidget.setEditTriggers( + self.previewListWidget = SlideList(self) + self.previewListWidget.setColumnCount(1) + self.previewListWidget.horizontalHeader().setVisible(False) + self.previewListWidget.setColumnWidth( + 0, self.controller.width()) + self.previewListWidget.isLive = self.isLive + self.previewListWidget.setObjectName(u'PreviewListWidget') + self.previewListWidget.setSelectionBehavior(1) + self.previewListWidget.setEditTriggers( QtGui.QAbstractItemView.NoEditTriggers) - self.PreviewListWidget.setHorizontalScrollBarPolicy( + self.previewListWidget.setHorizontalScrollBarPolicy( QtCore.Qt.ScrollBarAlwaysOff) - self.PreviewListWidget.setAlternatingRowColors(True) - self.ControllerLayout.addWidget(self.PreviewListWidget) + self.previewListWidget.setAlternatingRowColors(True) + self.controllerLayout.addWidget(self.previewListWidget) # Build the full toolbar - self.Toolbar = OpenLPToolbar(self) + self.toolbar = OpenLPToolbar(self) sizeToolbarPolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizeToolbarPolicy.setHorizontalStretch(0) sizeToolbarPolicy.setVerticalStretch(0) sizeToolbarPolicy.setHeightForWidth( - self.Toolbar.sizePolicy().hasHeightForWidth()) - self.Toolbar.setSizePolicy(sizeToolbarPolicy) - self.Toolbar.addToolbarButton( - u'Previous Slide', u':/slides/slide_previous.png', + self.toolbar.sizePolicy().hasHeightForWidth()) + self.toolbar.setSizePolicy(sizeToolbarPolicy) + self.previousItem = self.toolbar.addToolbarButton( + translate('OpenLP.SlideController', 'Previous Slide'), + u':/slides/slide_previous.png', translate('OpenLP.SlideController', 'Move to previous'), self.onSlideSelectedPrevious) - self.Toolbar.addToolbarButton( - u'Next Slide', u':/slides/slide_next.png', + self.nextItem = self.toolbar.addToolbarButton( + translate('OpenLP.SlideController', 'Next Slide'), + u':/slides/slide_next.png', translate('OpenLP.SlideController', 'Move to next'), self.onSlideSelectedNext) if self.isLive: - self.Toolbar.addToolbarSeparator(u'Close Separator') - self.HideMenu = QtGui.QToolButton(self.Toolbar) - self.HideMenu.setText(translate('OpenLP.SlideController', 'Hide')) - self.HideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) - self.Toolbar.addToolbarWidget(u'Hide Menu', self.HideMenu) - self.HideMenu.setMenu(QtGui.QMenu( - translate('OpenLP.SlideController', 'Hide'), self.Toolbar)) - self.BlankScreen = QtGui.QAction(QtGui.QIcon( + self.toolbar.addToolbarSeparator(u'Close Separator') + self.hideMenu = QtGui.QToolButton(self.toolbar) + self.hideMenu.setText(translate('OpenLP.SlideController', 'Hide')) + self.hideMenu.setPopupMode(QtGui.QToolButton.MenuButtonPopup) + self.toolbar.addToolbarWidget(u'Hide Menu', self.hideMenu) + self.hideMenu.setMenu(QtGui.QMenu( + translate('OpenLP.SlideController', 'Hide'), self.toolbar)) + self.blankScreen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_blank.png'), translate('OpenLP.SlideController', - 'Blank Screen'), self.HideMenu) - self.BlankScreen.setCheckable(True) - self.ThemeScreen = QtGui.QAction(QtGui.QIcon( + 'Blank Screen'), self.hideMenu) + self.blankScreen.setCheckable(True) + self.themeScreen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_theme.png'), translate('OpenLP.SlideController', - 'Blank to Theme'), self.HideMenu) - self.ThemeScreen.setCheckable(True) - self.HideMenu.setDefaultAction(self.BlankScreen) - self.HideMenu.menu().addAction(self.BlankScreen) - self.HideMenu.menu().addAction(self.ThemeScreen) + 'Blank to Theme'), self.hideMenu) + self.themeScreen.setCheckable(True) + self.hideMenu.setDefaultAction(self.blankScreen) + self.hideMenu.menu().addAction(self.blankScreen) + self.hideMenu.menu().addAction(self.themeScreen) if self.screens.display_count > 1: - self.DesktopScreen = QtGui.QAction(QtGui.QIcon( + self.desktopScreen = QtGui.QAction(QtGui.QIcon( u':/slides/slide_desktop.png'), translate('OpenLP.SlideController', - 'Show Desktop'), self.HideMenu) - self.HideMenu.menu().addAction(self.DesktopScreen) - self.DesktopScreen.setCheckable(True) - QtCore.QObject.connect(self.DesktopScreen, + 'Show Desktop'), self.hideMenu) + self.hideMenu.menu().addAction(self.desktopScreen) + self.desktopScreen.setCheckable(True) + QtCore.QObject.connect(self.desktopScreen, QtCore.SIGNAL(u'triggered(bool)'), self.onHideDisplay) - self.Toolbar.addToolbarSeparator(u'Loop Separator') - self.Toolbar.addToolbarButton( + self.toolbar.addToolbarSeparator(u'Loop Separator') + self.toolbar.addToolbarButton( u'Start Loop', u':/media/media_time.png', translate('OpenLP.SlideController', 'Start continuous loop'), self.onStartLoop) - self.Toolbar.addToolbarButton( + self.toolbar.addToolbarButton( u'Stop Loop', u':/media/media_stop.png', translate('OpenLP.SlideController', 'Stop continuous loop'), self.onStopLoop) self.DelaySpinBox = QtGui.QSpinBox() self.DelaySpinBox.setMinimum(1) self.DelaySpinBox.setMaximum(180) - self.Toolbar.addToolbarWidget(u'Image SpinBox', self.DelaySpinBox) + self.toolbar.addToolbarWidget(u'Image SpinBox', self.DelaySpinBox) self.DelaySpinBox.setSuffix(translate('OpenLP.SlideController', 's')) self.DelaySpinBox.setToolTip(translate('OpenLP.SlideController', 'Delay between slides in seconds')) else: - self.Toolbar.addToolbarSeparator(u'Close Separator') - self.Toolbar.addToolbarButton( + self.toolbar.addToolbarSeparator(u'Close Separator') + self.toolbar.addToolbarButton( u'Go Live', u':/general/general_live.png', translate('OpenLP.SlideController', 'Move to live'), self.onGoLive) - self.Toolbar.addToolbarSeparator(u'Close Separator') - self.Toolbar.addToolbarButton( + self.toolbar.addToolbarSeparator(u'Close Separator') + self.toolbar.addToolbarButton( u'Edit Song', u':/general/general_edit.png', translate('OpenLP.SlideController', 'Edit and reload song preview'), self.onEditSong) - self.ControllerLayout.addWidget(self.Toolbar) + self.controllerLayout.addWidget(self.toolbar) # Build a Media ToolBar - self.Mediabar = OpenLPToolbar(self) - self.Mediabar.addToolbarButton( + self.mediabar = OpenLPToolbar(self) + self.mediabar.addToolbarButton( u'Media Start', u':/slides/media_playback_start.png', translate('OpenLP.SlideController', 'Start playing media'), self.onMediaPlay) - self.Mediabar.addToolbarButton( + self.mediabar.addToolbarButton( u'Media Pause', u':/slides/media_playback_pause.png', translate('OpenLP.SlideController', 'Start playing media'), self.onMediaPause) - self.Mediabar.addToolbarButton( + self.mediabar.addToolbarButton( u'Media Stop', u':/slides/media_playback_stop.png', translate('OpenLP.SlideController', 'Start playing media'), self.onMediaStop) if self.isLive: # Build the Song Toolbar - self.SongMenu = QtGui.QToolButton(self.Toolbar) - self.SongMenu.setText(translate('OpenLP.SlideController', + self.songMenu = QtGui.QToolButton(self.toolbar) + self.songMenu.setText(translate('OpenLP.SlideController', 'Go To')) - self.SongMenu.setPopupMode(QtGui.QToolButton.InstantPopup) - self.Toolbar.addToolbarWidget(u'Song Menu', self.SongMenu) - self.SongMenu.setMenu(QtGui.QMenu( - translate('OpenLP.SlideController', 'Go To'), self.Toolbar)) - self.Toolbar.makeWidgetsInvisible([u'Song Menu']) + self.songMenu.setPopupMode(QtGui.QToolButton.InstantPopup) + self.toolbar.addToolbarWidget(u'Song Menu', self.songMenu) + self.songMenu.setMenu(QtGui.QMenu( + translate('OpenLP.SlideController', 'Go To'), self.toolbar)) + self.toolbar.makeWidgetsInvisible([u'Song Menu']) # Build the volumeSlider. self.volumeSlider = QtGui.QSlider(QtCore.Qt.Horizontal) self.volumeSlider.setTickInterval(1) @@ -265,29 +239,29 @@ class SlideController(QtGui.QWidget): self.seekSlider = Phonon.SeekSlider() self.seekSlider.setGeometry(QtCore.QRect(90, 260, 221, 24)) self.seekSlider.setObjectName(u'seekSlider') - self.Mediabar.addToolbarWidget(u'Seek Slider', self.seekSlider) + self.mediabar.addToolbarWidget(u'Seek Slider', self.seekSlider) self.volumeSlider = Phonon.VolumeSlider() self.volumeSlider.setGeometry(QtCore.QRect(90, 260, 221, 24)) self.volumeSlider.setObjectName(u'volumeSlider') - self.Mediabar.addToolbarWidget(u'Audio Volume', self.volumeSlider) - self.ControllerLayout.addWidget(self.Mediabar) + self.mediabar.addToolbarWidget(u'Audio Volume', self.volumeSlider) + self.controllerLayout.addWidget(self.mediabar) # Screen preview area - self.PreviewFrame = QtGui.QFrame(self.Splitter) - self.PreviewFrame.setGeometry(QtCore.QRect(0, 0, 300, 300 * self.ratio)) - self.PreviewFrame.setMinimumHeight(100) - self.PreviewFrame.setSizePolicy(QtGui.QSizePolicy( + self.previewFrame = QtGui.QFrame(self.splitter) + self.previewFrame.setGeometry(QtCore.QRect(0, 0, 300, 300 * self.ratio)) + self.previewFrame.setMinimumHeight(100) + self.previewFrame.setSizePolicy(QtGui.QSizePolicy( QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Ignored, QtGui.QSizePolicy.Label)) - self.PreviewFrame.setFrameShape(QtGui.QFrame.StyledPanel) - self.PreviewFrame.setFrameShadow(QtGui.QFrame.Sunken) - self.PreviewFrame.setObjectName(u'PreviewFrame') - self.grid = QtGui.QGridLayout(self.PreviewFrame) + self.previewFrame.setFrameShape(QtGui.QFrame.StyledPanel) + self.previewFrame.setFrameShadow(QtGui.QFrame.Sunken) + self.previewFrame.setObjectName(u'PreviewFrame') + self.grid = QtGui.QGridLayout(self.previewFrame) self.grid.setMargin(8) self.grid.setObjectName(u'grid') - self.SlideLayout = QtGui.QVBoxLayout() - self.SlideLayout.setSpacing(0) - self.SlideLayout.setMargin(0) - self.SlideLayout.setObjectName(u'SlideLayout') + self.slideLayout = QtGui.QVBoxLayout() + self.slideLayout.setSpacing(0) + self.slideLayout.setMargin(0) + self.slideLayout.setObjectName(u'SlideLayout') self.mediaObject = Phonon.MediaObject(self) self.video = Phonon.VideoWidget() self.video.setVisible(False) @@ -296,33 +270,33 @@ class SlideController(QtGui.QWidget): Phonon.createPath(self.mediaObject, self.audio) if not self.isLive: self.video.setGeometry(QtCore.QRect(0, 0, 300, 225)) - self.SlideLayout.insertWidget(0, self.video) + self.slideLayout.insertWidget(0, self.video) # Actual preview screen - self.SlidePreview = QtGui.QLabel(self) + self.slidePreview = QtGui.QLabel(self) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( - self.SlidePreview.sizePolicy().hasHeightForWidth()) - self.SlidePreview.setSizePolicy(sizePolicy) - self.SlidePreview.setFixedSize( + self.slidePreview.sizePolicy().hasHeightForWidth()) + self.slidePreview.setSizePolicy(sizePolicy) + self.slidePreview.setFixedSize( QtCore.QSize(self.settingsmanager.slidecontroller_image, self.settingsmanager.slidecontroller_image / self.ratio)) - self.SlidePreview.setFrameShape(QtGui.QFrame.Box) - self.SlidePreview.setFrameShadow(QtGui.QFrame.Plain) - self.SlidePreview.setLineWidth(1) - self.SlidePreview.setScaledContents(True) - self.SlidePreview.setObjectName(u'SlidePreview') - self.SlideLayout.insertWidget(0, self.SlidePreview) - self.grid.addLayout(self.SlideLayout, 0, 0, 1, 1) + self.slidePreview.setFrameShape(QtGui.QFrame.Box) + self.slidePreview.setFrameShadow(QtGui.QFrame.Plain) + self.slidePreview.setLineWidth(1) + self.slidePreview.setScaledContents(True) + self.slidePreview.setObjectName(u'SlidePreview') + self.slideLayout.insertWidget(0, self.slidePreview) + self.grid.addLayout(self.slideLayout, 0, 0, 1, 1) # Signals - QtCore.QObject.connect(self.PreviewListWidget, + QtCore.QObject.connect(self.previewListWidget, QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) if self.isLive: - QtCore.QObject.connect(self.BlankScreen, + QtCore.QObject.connect(self.blankScreen, QtCore.SIGNAL(u'triggered(bool)'), self.onBlankDisplay) - QtCore.QObject.connect(self.ThemeScreen, + QtCore.QObject.connect(self.themeScreen, QtCore.SIGNAL(u'triggered(bool)'), self.onThemeDisplay) QtCore.QObject.connect(self.volumeSlider, QtCore.SIGNAL(u'sliderReleased()'), self.mediaVolume) @@ -331,14 +305,33 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_live_spin_delay'), self.receiveSpinDelay) - self.Toolbar.makeWidgetsInvisible(self.loopList) - self.Toolbar.actions[u'Stop Loop'].setVisible(False) + self.toolbar.makeWidgetsInvisible(self.loopList) + self.toolbar.actions[u'Stop Loop'].setVisible(False) else: - QtCore.QObject.connect(self.PreviewListWidget, + QtCore.QObject.connect(self.previewListWidget, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onGoLiveClick) - self.Toolbar.makeWidgetsInvisible(self.songEditList) - self.Mediabar.setVisible(False) + self.toolbar.makeWidgetsInvisible(self.songEditList) + self.mediabar.setVisible(False) + if self.isLive: + self.setLiveHotkeys(self) + self.previewListWidget.addActions( + [self.previousItem, + self.nextItem, + self.previousService, + self.nextService, + self.escapeItem]) + self.display.addActions( + [self.previousItem, + self.nextItem, + self.previousService, + self.nextService, + self.escapeItem]) + else: + self.setPreviewHotkeys() + self.previewListWidget.addActions( + [self.nextItem, + self.previousItem]) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_%s_stop_loop' % self.typePrefix), self.onStopLoop) @@ -376,11 +369,59 @@ class SlideController(QtGui.QWidget): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'slidecontroller_%s_text_request' % self.typePrefix), self.onTextRequest) - QtCore.QObject.connect(Receiver.get_receiver(), - QtCore.SIGNAL(u'config_updated'), self.refreshServiceItem) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'config_screen_changed'), self.screenSizeChanged) + def setPreviewHotkeys(self, parent=None): + actionList = self.parent.actionList + self.previousItem.setShortcuts([QtCore.Qt.Key_Up, 0]) + actionList.add_action(self.previousItem, u'Preview') + self.nextItem.setShortcuts([QtCore.Qt.Key_Down, 0]) + actionList.add_action(self.nextItem, u'Preview') + + def setLiveHotkeys(self, parent=None): + actionList = self.parent.actionList + self.previousItem.setShortcuts([QtCore.Qt.Key_Up, QtCore.Qt.Key_PageUp]) + self.previousItem.setShortcutContext( + QtCore.Qt.WidgetWithChildrenShortcut) + actionList.add_action(self.nextItem, u'Live') + self.nextItem.setShortcuts([QtCore.Qt.Key_Down, QtCore.Qt.Key_PageDown]) + self.nextItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) + actionList.add_action(self.nextItem, u'Live') + self.previousService = QtGui.QAction(translate( + 'OpenLP.SlideController', 'Previous Service'), parent) + self.previousService.setShortcuts([QtCore.Qt.Key_Left, 0]) + self.previousService.setShortcutContext( + QtCore.Qt.WidgetWithChildrenShortcut) + QtCore.QObject.connect(self.previousService, + QtCore.SIGNAL(u'triggered()'), self.servicePrevious) + actionList.add_action(self.previousService, u'Live') + self.nextService = QtGui.QAction(translate( + 'OpenLP.SlideController', 'Next Service'), parent) + self.nextService.setShortcuts([QtCore.Qt.Key_Right, 0]) + self.nextService.setShortcutContext( + QtCore.Qt.WidgetWithChildrenShortcut) + QtCore.QObject.connect(self.nextService, + QtCore.SIGNAL(u'triggered()'), self.serviceNext) + actionList.add_action(self.nextService, u'Live') + self.escapeItem = QtGui.QAction(translate( + 'OpenLP.SlideController', 'Escape Item'), parent) + self.escapeItem.setShortcuts([QtCore.Qt.Key_Escape, 0]) + self.escapeItem.setShortcutContext(QtCore.Qt.WidgetWithChildrenShortcut) + QtCore.QObject.connect(self.escapeItem, + QtCore.SIGNAL(u'triggered()'), self.liveEscape) + actionList.add_action(self.escapeItem, u'Live') + + def liveEscape(self): + self.display.setVisible(False) + self.display.videoStop() + + def servicePrevious(self): + Receiver.send_message('servicemanager_previous_item') + + def serviceNext(self): + Receiver.send_message('servicemanager_next_item') + def screenSizeChanged(self): """ Settings dialog has changed the screen size of adjust output and @@ -391,10 +432,19 @@ class SlideController(QtGui.QWidget): self.display.imageManager = self.parent.renderManager.image_manager self.display.alertTab = self.alertTab self.display.setup() + if self.isLive: + self.display.addActions( + [self.previousItem, + self.nextItem, + self.previousService, + self.nextService, + self.escapeItem]) # The SlidePreview's ratio. self.ratio = float(self.screens.current[u'size'].width()) / \ float(self.screens.current[u'size'].height()) self.previewSizeChanged() + if self.serviceItem: + self.refreshServiceItem() def previewSizeChanged(self): """ @@ -402,42 +452,42 @@ class SlideController(QtGui.QWidget): splitters is moved or when the screen size is changed. Note, that this method is (also) called frequently from the mainwindow *paintEvent*. """ - if self.ratio < float(self.PreviewFrame.width()) / float( - self.PreviewFrame.height()): + if self.ratio < float(self.previewFrame.width()) / float( + self.previewFrame.height()): # We have to take the height as limit. - max_height = self.PreviewFrame.height() - self.grid.margin() * 2 - self.SlidePreview.setFixedSize(QtCore.QSize(max_height * self.ratio, + max_height = self.previewFrame.height() - self.grid.margin() * 2 + self.slidePreview.setFixedSize(QtCore.QSize(max_height * self.ratio, max_height)) else: # We have to take the width as limit. - max_width = self.PreviewFrame.width() - self.grid.margin() * 2 - self.SlidePreview.setFixedSize(QtCore.QSize(max_width, + max_width = self.previewFrame.width() - self.grid.margin() * 2 + self.slidePreview.setFixedSize(QtCore.QSize(max_width, max_width / self.ratio)) # Make sure that the frames have the correct size. - self.PreviewListWidget.setColumnWidth(0, - self.PreviewListWidget.viewport().size().width()) + self.previewListWidget.setColumnWidth(0, + self.previewListWidget.viewport().size().width()) if self.serviceItem: # Sort out songs, bibles, etc. if self.serviceItem.is_text(): - self.PreviewListWidget.resizeRowsToContents() + self.previewListWidget.resizeRowsToContents() else: # Sort out image heights. width = self.parent.ControlSplitter.sizes()[self.split] for framenumber in range(len(self.serviceItem.get_frames())): - self.PreviewListWidget.setRowHeight( + self.previewListWidget.setRowHeight( framenumber, width / self.ratio) def onSongBarHandler(self): request = unicode(self.sender().text()) slideno = self.slideList[request] - if slideno > self.PreviewListWidget.rowCount(): - self.PreviewListWidget.selectRow( - self.PreviewListWidget.rowCount() - 1) + if slideno > self.previewListWidget.rowCount(): + self.previewListWidget.selectRow( + self.previewListWidget.rowCount() - 1) else: - if slideno + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(slideno + 1, 0)) - self.PreviewListWidget.selectRow(slideno) + if slideno + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(slideno + 1, 0)) + self.previewListWidget.selectRow(slideno) self.onSlideSelected() def receiveSpinDelay(self, value): @@ -457,35 +507,35 @@ class SlideController(QtGui.QWidget): """ Allows the live toolbar to be customised """ - self.Toolbar.setVisible(True) - self.Mediabar.setVisible(False) - self.Toolbar.makeWidgetsInvisible([u'Song Menu']) - self.Toolbar.makeWidgetsInvisible(self.loopList) - self.Toolbar.actions[u'Stop Loop'].setVisible(False) + self.toolbar.setVisible(True) + self.mediabar.setVisible(False) + self.toolbar.makeWidgetsInvisible([u'Song Menu']) + self.toolbar.makeWidgetsInvisible(self.loopList) + self.toolbar.actions[u'Stop Loop'].setVisible(False) if item.is_text(): if QtCore.QSettings().value( self.parent.songsSettingsSection + u'/display songbar', QtCore.QVariant(True)).toBool() and len(self.slideList) > 0: - self.Toolbar.makeWidgetsVisible([u'Song Menu']) + self.toolbar.makeWidgetsVisible([u'Song Menu']) if item.is_capable(ItemCapabilities.AllowsLoop) and \ len(item.get_frames()) > 1: - self.Toolbar.makeWidgetsVisible(self.loopList) + self.toolbar.makeWidgetsVisible(self.loopList) if item.is_media(): - self.Toolbar.setVisible(False) - self.Mediabar.setVisible(True) + self.toolbar.setVisible(False) + self.mediabar.setVisible(True) def enablePreviewToolBar(self, item): """ Allows the Preview toolbar to be customised """ - self.Toolbar.setVisible(True) - self.Mediabar.setVisible(False) - self.Toolbar.makeWidgetsInvisible(self.songEditList) + self.toolbar.setVisible(True) + self.mediabar.setVisible(False) + self.toolbar.makeWidgetsInvisible(self.songEditList) if item.is_capable(ItemCapabilities.AllowsEdit) and item.from_plugin: - self.Toolbar.makeWidgetsVisible(self.songEditList) + self.toolbar.makeWidgetsVisible(self.songEditList) elif item.is_media(): - self.Toolbar.setVisible(False) - self.Mediabar.setVisible(True) + self.toolbar.setVisible(False) + self.mediabar.setVisible(True) self.volumeSlider.setAudioOutput(self.audio) def refreshServiceItem(self): @@ -493,11 +543,10 @@ class SlideController(QtGui.QWidget): Method to update the service item if the screen has changed """ log.debug(u'refreshServiceItem live = %s' % self.isLive) - if self.serviceItem: - if self.serviceItem.is_text() or self.serviceItem.is_image(): - item = self.serviceItem - item.render() - self._processItem(item, self.selectedRow) + if self.serviceItem.is_text() or self.serviceItem.is_image(): + item = self.serviceItem + item.render() + self._processItem(item, self.selectedRow) def addServiceItem(self, item): """ @@ -517,7 +566,7 @@ class SlideController(QtGui.QWidget): Replacement item following a remote edit """ if item.__eq__(self.serviceItem): - self._processItem(item, self.PreviewListWidget.currentRow()) + self._processItem(item, self.previewListWidget.currentRow()) def addServiceManagerItem(self, item, slideno): """ @@ -526,12 +575,15 @@ class SlideController(QtGui.QWidget): Called by ServiceManager """ log.debug(u'addServiceManagerItem live = %s' % self.isLive) + # If no valid slide number is specified we take the first one. + if slideno == -1: + slideno = 0 # If service item is the same as the current on only change slide if item.__eq__(self.serviceItem): - if slideno + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(slideno + 1, 0)) - self.PreviewListWidget.selectRow(slideno) + if slideno + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(slideno + 1, 0)) + self.previewListWidget.selectRow(slideno) self.onSlideSelected() return self._processItem(item, slideno) @@ -553,7 +605,7 @@ class SlideController(QtGui.QWidget): if self.isLive: if serviceItem.is_capable(ItemCapabilities.ProvidesOwnDisplay): self._forceUnblank() - blanked = self.BlankScreen.isChecked() + blanked = self.blankScreen.isChecked() else: blanked = False Receiver.send_message(u'%s_start' % serviceItem.name.lower(), @@ -561,16 +613,16 @@ class SlideController(QtGui.QWidget): self.slideList = {} width = self.parent.ControlSplitter.sizes()[self.split] self.serviceItem = serviceItem - self.PreviewListWidget.clear() - self.PreviewListWidget.setRowCount(0) - self.PreviewListWidget.setColumnWidth(0, width) + self.previewListWidget.clear() + self.previewListWidget.setRowCount(0) + self.previewListWidget.setColumnWidth(0, width) if self.isLive: - self.SongMenu.menu().clear() + self.songMenu.menu().clear() row = 0 text = [] for framenumber, frame in enumerate(self.serviceItem.get_frames()): - self.PreviewListWidget.setRowCount( - self.PreviewListWidget.rowCount() + 1) + self.previewListWidget.setRowCount( + self.previewListWidget.rowCount() + 1) item = QtGui.QTableWidgetItem() slideHeight = 0 if self.serviceItem.is_text(): @@ -582,7 +634,7 @@ class SlideController(QtGui.QWidget): if self.isLive: if tag1 not in self.slideList: self.slideList[tag1] = framenumber - self.SongMenu.menu().addAction(tag1, + self.songMenu.menu().addAction(tag1, self.onSongBarHandler) else: row += 1 @@ -599,33 +651,33 @@ class SlideController(QtGui.QWidget): image = self.parent.renderManager.image_manager. \ get_image(frame[u'title']) label.setPixmap(QtGui.QPixmap.fromImage(image)) - self.PreviewListWidget.setCellWidget(framenumber, 0, label) + self.previewListWidget.setCellWidget(framenumber, 0, label) slideHeight = width * self.parent.renderManager.screen_ratio row += 1 text.append(unicode(row)) - self.PreviewListWidget.setItem(framenumber, 0, item) + self.previewListWidget.setItem(framenumber, 0, item) if slideHeight != 0: - self.PreviewListWidget.setRowHeight(framenumber, slideHeight) - self.PreviewListWidget.setVerticalHeaderLabels(text) + self.previewListWidget.setRowHeight(framenumber, slideHeight) + self.previewListWidget.setVerticalHeaderLabels(text) if self.serviceItem.is_text(): - self.PreviewListWidget.resizeRowsToContents() - self.PreviewListWidget.setColumnWidth(0, - self.PreviewListWidget.viewport().size().width()) - if slideno > self.PreviewListWidget.rowCount(): - self.PreviewListWidget.selectRow( - self.PreviewListWidget.rowCount() - 1) + self.previewListWidget.resizeRowsToContents() + self.previewListWidget.setColumnWidth(0, + self.previewListWidget.viewport().size().width()) + if slideno > self.previewListWidget.rowCount(): + self.previewListWidget.selectRow( + self.previewListWidget.rowCount() - 1) else: - if slideno + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(slideno + 1, 0)) - self.PreviewListWidget.selectRow(slideno) + if slideno + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(slideno + 1, 0)) + self.previewListWidget.selectRow(slideno) self.enableToolBar(serviceItem) # Pass to display for viewing self.display.buildHtml(self.serviceItem) if serviceItem.is_media(): self.onMediaStart(serviceItem) self.onSlideSelected() - self.PreviewListWidget.setFocus() + self.previewListWidget.setFocus() Receiver.send_message(u'slidecontroller_%s_started' % self.typePrefix, [serviceItem]) @@ -644,7 +696,7 @@ class SlideController(QtGui.QWidget): dataItem[u'tag'] = unicode(framenumber) dataItem[u'text'] = u'' dataItem[u'selected'] = \ - (self.PreviewListWidget.currentRow() == framenumber) + (self.previewListWidget.currentRow() == framenumber) data.append(dataItem) Receiver.send_message(u'slidecontroller_%s_text_response' % self.typePrefix, data) @@ -661,7 +713,7 @@ class SlideController(QtGui.QWidget): [self.serviceItem, self.isLive]) self.updatePreview() else: - self.PreviewListWidget.selectRow(0) + self.previewListWidget.selectRow(0) self.onSlideSelected() def onSlideSelectedIndex(self, message): @@ -676,10 +728,10 @@ class SlideController(QtGui.QWidget): [self.serviceItem, self.isLive, index]) self.updatePreview() else: - if index + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(index + 1, 0)) - self.PreviewListWidget.selectRow(index) + if index + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(index + 1, 0)) + self.previewListWidget.selectRow(index) self.onSlideSelected() def mainDisplaySetBackground(self): @@ -716,11 +768,11 @@ class SlideController(QtGui.QWidget): Handle the blank screen button actions """ log.debug(u'onBlankDisplay %s' % checked) - self.HideMenu.setDefaultAction(self.BlankScreen) - self.BlankScreen.setChecked(checked) - self.ThemeScreen.setChecked(False) + self.hideMenu.setDefaultAction(self.blankScreen) + self.blankScreen.setChecked(checked) + self.themeScreen.setChecked(False) if self.screens.display_count > 1: - self.DesktopScreen.setChecked(False) + self.desktopScreen.setChecked(False) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Blank) QtCore.QSettings().setValue( @@ -731,17 +783,18 @@ class SlideController(QtGui.QWidget): QtCore.QSettings().remove( self.parent.generalSettingsSection + u'/screen blank') self.blankPlugin(checked) + self.updatePreview() def onThemeDisplay(self, checked): """ Handle the Theme screen button """ log.debug(u'onThemeDisplay %s' % checked) - self.HideMenu.setDefaultAction(self.ThemeScreen) - self.BlankScreen.setChecked(False) - self.ThemeScreen.setChecked(checked) + self.hideMenu.setDefaultAction(self.themeScreen) + self.blankScreen.setChecked(False) + self.themeScreen.setChecked(checked) if self.screens.display_count > 1: - self.DesktopScreen.setChecked(False) + self.desktopScreen.setChecked(False) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Theme) QtCore.QSettings().setValue( @@ -752,19 +805,20 @@ class SlideController(QtGui.QWidget): QtCore.QSettings().remove( self.parent.generalSettingsSection + u'/screen blank') self.blankPlugin(checked) + self.updatePreview() def onHideDisplay(self, checked): """ Handle the Hide screen button """ log.debug(u'onHideDisplay %s' % checked) - self.HideMenu.setDefaultAction(self.DesktopScreen) - self.BlankScreen.setChecked(False) - self.ThemeScreen.setChecked(False) + self.hideMenu.setDefaultAction(self.desktopScreen) + self.blankScreen.setChecked(False) + self.themeScreen.setChecked(False) # On valid if more than 1 display if self.screens.display_count <= 1: return - self.DesktopScreen.setChecked(checked) + self.desktopScreen.setChecked(checked) if checked: Receiver.send_message(u'maindisplay_hide', HideMode.Screen) QtCore.QSettings().setValue( @@ -775,6 +829,7 @@ class SlideController(QtGui.QWidget): QtCore.QSettings().remove( self.parent.generalSettingsSection + u'/screen blank') self.hidePlugin(checked) + self.updatePreview() def blankPlugin(self, blank): """ @@ -811,9 +866,9 @@ class SlideController(QtGui.QWidget): Generate the preview when you click on a slide. if this is the Live Controller also display on the screen """ - row = self.PreviewListWidget.currentRow() + row = self.previewListWidget.currentRow() self.selectedRow = 0 - if row > -1 and row < self.PreviewListWidget.rowCount(): + if row > -1 and row < self.previewListWidget.rowCount(): if self.serviceItem.is_command(): if self.isLive: Receiver.send_message( @@ -826,7 +881,7 @@ class SlideController(QtGui.QWidget): frame = self.display.text(toDisplay) else: frame = self.display.image(toDisplay) - self.SlidePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) + self.slidePreview.setPixmap(QtGui.QPixmap.fromImage(frame)) self.selectedRow = row Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row) @@ -835,31 +890,38 @@ class SlideController(QtGui.QWidget): """ The slide has been changed. Update the slidecontroller accordingly """ - if row + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(row + 1, 0)) - self.PreviewListWidget.selectRow(row) + if row + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(row + 1, 0)) + self.previewListWidget.selectRow(row) self.updatePreview() Receiver.send_message(u'slidecontroller_%s_changed' % self.typePrefix, row) def updatePreview(self): - log.debug(u'updatePreview %s ' %self.screens.current[u'primary']) + """ + This updates the preview frame, for example after changing a slide or + using *Blank to Theme*. + """ + log.debug(u'updatePreview %s ' % self.screens.current[u'primary']) if not self.screens.current[u'primary']: # Grab now, but try again in a couple of seconds if slide change # is slow QtCore.QTimer.singleShot(0.5, self.grabMainDisplay) QtCore.QTimer.singleShot(2.5, self.grabMainDisplay) else: - self.SlidePreview.setPixmap( + self.slidePreview.setPixmap( QtGui.QPixmap.fromImage(self.display.preview())) def grabMainDisplay(self): + """ + Creates an image of the current screen and updates the preview frame. + """ winid = QtGui.QApplication.desktop().winId() rect = self.screens.current[u'size'] winimg = QtGui.QPixmap.grabWindow(winid, rect.x(), rect.y(), rect.width(), rect.height()) - self.SlidePreview.setPixmap(winimg) + self.slidePreview.setPixmap(winimg) def onSlideSelectedNextNoloop(self): self.onSlideSelectedNext(False) @@ -875,17 +937,17 @@ class SlideController(QtGui.QWidget): if self.serviceItem.is_command() and self.isLive: self.updatePreview() else: - row = self.PreviewListWidget.currentRow() + 1 - if row == self.PreviewListWidget.rowCount(): + row = self.previewListWidget.currentRow() + 1 + if row == self.previewListWidget.rowCount(): if loop: row = 0 else: Receiver.send_message('servicemanager_next_item') return - if row + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(row + 1, 0)) - self.PreviewListWidget.selectRow(row) + if row + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(row + 1, 0)) + self.previewListWidget.selectRow(row) self.onSlideSelected() def onSlideSelectedPreviousNoloop(self): @@ -902,16 +964,16 @@ class SlideController(QtGui.QWidget): if self.serviceItem.is_command() and self.isLive: self.updatePreview() else: - row = self.PreviewListWidget.currentRow() - 1 + row = self.previewListWidget.currentRow() - 1 if row == -1: if loop: - row = self.PreviewListWidget.rowCount() - 1 + row = self.previewListWidget.rowCount() - 1 else: row = 0 - if row + 1 < self.PreviewListWidget.rowCount(): - self.PreviewListWidget.scrollToItem( - self.PreviewListWidget.item(row + 1, 0)) - self.PreviewListWidget.selectRow(row) + if row + 1 < self.previewListWidget.rowCount(): + self.previewListWidget.scrollToItem( + self.previewListWidget.item(row + 1, 0)) + self.previewListWidget.selectRow(row) self.onSlideSelected() def onSlideSelectedLast(self): @@ -925,19 +987,19 @@ class SlideController(QtGui.QWidget): if self.serviceItem.is_command(): self.updatePreview() else: - self.PreviewListWidget.selectRow( - self.PreviewListWidget.rowCount() - 1) + self.previewListWidget.selectRow( + self.previewListWidget.rowCount() - 1) self.onSlideSelected() def onStartLoop(self): """ Start the timer loop running and store the timer id """ - if self.PreviewListWidget.rowCount() > 1: + 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) + self.toolbar.actions[u'Stop Loop'].setVisible(True) + self.toolbar.actions[u'Start Loop'].setVisible(False) def onStopLoop(self): """ @@ -946,8 +1008,8 @@ 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) + self.toolbar.actions[u'Start Loop'].setVisible(True) + self.toolbar.actions[u'Stop Loop'].setVisible(False) def timerEvent(self, event): """ @@ -976,8 +1038,8 @@ class SlideController(QtGui.QWidget): """ If preview copy slide item to live """ - row = self.PreviewListWidget.currentRow() - if row > -1 and row < self.PreviewListWidget.rowCount(): + row = self.previewListWidget.currentRow() + if row > -1 and row < self.previewListWidget.rowCount(): self.parent.liveController.addServiceManagerItem( self.serviceItem, row) @@ -1024,7 +1086,7 @@ class SlideController(QtGui.QWidget): if self.isLive: self.display.videoPlay() else: - self.SlidePreview.hide() + self.slidePreview.hide() self.video.show() self.mediaObject.play() @@ -1038,8 +1100,8 @@ class SlideController(QtGui.QWidget): else: self.mediaObject.stop() self.video.hide() - self.SlidePreview.clear() - self.SlidePreview.show() + self.slidePreview.clear() + self.slidePreview.show() def onMediaClose(self): """ @@ -1052,24 +1114,23 @@ class SlideController(QtGui.QWidget): self.mediaObject.stop() self.mediaObject.clearQueue() self.video.hide() - self.SlidePreview.clear() - self.SlidePreview.show() + self.slidePreview.clear() + self.slidePreview.show() def _forceUnblank(self): """ Used by command items which provide their own displays to reset the screen hide attributes """ - if self.BlankScreen.isChecked: - self.BlankScreen.setChecked(False) - self.HideMenu.setDefaultAction(self.BlankScreen) + if self.blankScreen.isChecked: + self.blankScreen.setChecked(False) + self.hideMenu.setDefaultAction(self.blankScreen) QtCore.QSettings().remove( self.parent.generalSettingsSection + u'/screen blank') - if self.ThemeScreen.isChecked: - self.ThemeScreen.setChecked(False) - self.HideMenu.setDefaultAction(self.ThemeScreen) + if self.themeScreen.isChecked: + self.themeScreen.setChecked(False) + self.hideMenu.setDefaultAction(self.themeScreen) if self.screens.display_count > 1: - if self.DesktopScreen.isChecked: - self.DesktopScreen.setChecked(False) - self.HideMenu.setDefaultAction(self.DesktopScreen) - + if self.desktopScreen.isChecked: + self.desktopScreen.setChecked(False) + self.hideMenu.setDefaultAction(self.desktopScreen) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 9117a8e19..9dd133852 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -47,6 +47,8 @@ from openlp.core.lib import Receiver, translate log = logging.getLogger(__name__) IMAGES_FILTER = None +UNO_CONNECTION_TYPE = u'pipe' +#UNO_CONNECTION_TYPE = u'socket' class VersionThread(QtCore.QThread): """ @@ -121,18 +123,6 @@ class AppLocation(object): return _get_frozen_path( os.path.abspath(os.path.split(sys.argv[0])[0]), os.path.split(openlp.__file__)[0]) - elif dir_type == AppLocation.ConfigDir: - return _get_os_dir_path(u'openlp', - os.path.join(os.getenv(u'HOME'), u'Library', - u'Application Support', u'openlp'), - os.path.join(BaseDirectory.xdg_config_home, u'openlp'), - os.path.join(os.getenv(u'HOME'), u'.openlp')) - elif dir_type == AppLocation.DataDir: - return _get_os_dir_path(os.path.join(u'openlp', u'data'), - os.path.join(os.getenv(u'HOME'), u'Library', - u'Application Support', u'openlp', u'Data'), - os.path.join(BaseDirectory.xdg_data_home, u'openlp'), - os.path.join(os.getenv(u'HOME'), u'.openlp', u'data')) elif dir_type == AppLocation.PluginsDir: app_path = os.path.abspath(os.path.split(sys.argv[0])[0]) return _get_frozen_path(os.path.join(app_path, u'plugins'), @@ -141,17 +131,16 @@ class AppLocation(object): return _get_frozen_path( os.path.abspath(os.path.split(sys.argv[0])[0]), os.path.split(openlp.__file__)[0]) - elif dir_type == AppLocation.CacheDir: - return _get_os_dir_path(u'openlp', - os.path.join(os.getenv(u'HOME'), u'Library', - u'Application Support', u'openlp'), - os.path.join(BaseDirectory.xdg_cache_home, u'openlp'), - os.path.join(os.getenv(u'HOME'), u'.openlp')) - if dir_type == AppLocation.LanguageDir: + elif dir_type == AppLocation.LanguageDir: app_path = _get_frozen_path( os.path.abspath(os.path.split(sys.argv[0])[0]), 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) @staticmethod def get_data_path(): @@ -175,17 +164,24 @@ class AppLocation(object): return path def _get_os_dir_path(win_option, darwin_option, base_dir_option, - non_base_dir_option): + non_base_dir_option, dir_type=1): """ 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) elif sys.platform == u'darwin': + if dir_type == AppLocation.DataDir: + return os.path.join(darwin_option, u'Data') return darwin_option else: if XDG_BASE_AVAILABLE: - return base_dir_option + if dir_type == AppLocation.ConfigDir: + return os.path.join(BaseDirectory.xdg_config_home, u'openlp') + elif dir_type == AppLocation.DataDir: + return os.path.join(BaseDirectory.xdg_data_home, u'openlp') + elif dir_type == AppLocation.CacheDir: + return os.path.join(BaseDirectory.xdg_cache_home, u'openlp') else: return non_base_dir_option @@ -375,9 +371,37 @@ def string_is_unicode(test_string): log.exception("Error encoding string to unicode") return return_string +def get_uno_command(): + """ + Returns the UNO command to launch an openoffice.org instance. + """ + if UNO_CONNECTION_TYPE == u'pipe': + return u'openoffice.org -nologo -norestore -minimized -invisible ' \ + + u'-nofirststartwizard -accept=pipe,name=openlp_pipe;urp;' + else: + return u'openoffice.org -nologo -norestore -minimized ' \ + + u'-invisible -nofirststartwizard ' \ + + u'-accept=socket,host=localhost,port=2002;urp;' + +def get_uno_instance(resolver): + """ + Returns a running openoffice.org instance. + + ``resolver`` + The UNO resolver to use to find a running instance. + """ + log.debug(u'get UNO Desktop Openoffice - resolve') + if UNO_CONNECTION_TYPE == u'pipe': + return resolver.resolve(u'uno:pipe,name=openlp_pipe;' \ + + u'urp;StarOffice.ComponentContext') + else: + return resolver.resolve(u'uno:socket,host=localhost,port=2002;' \ + + u'urp;StarOffice.ComponentContext') + from languagemanager import LanguageManager from actions import ActionList __all__ = [u'AppLocation', u'check_latest_version', u'add_actions', u'get_filesystem_encoding', u'LanguageManager', u'ActionList', - u'get_web_page', u'file_is_unicode', u'string_is_unicode'] + u'get_web_page', u'file_is_unicode', u'string_is_unicode', + u'get_uno_command', u'get_uno_instance', u'delete_file'] diff --git a/openlp/core/utils/actions.py b/openlp/core/utils/actions.py index 4434c416e..e181dd2e1 100644 --- a/openlp/core/utils/actions.py +++ b/openlp/core/utils/actions.py @@ -27,7 +27,6 @@ The :mod:`~openlp.core.utils.actions` module provides action list classes used by the shortcuts system. """ - class ActionCategory(object): """ The :class:`~openlp.core.utils.ActionCategory` class encapsulates a @@ -181,4 +180,4 @@ class ActionList(object): if weight is None: self.categories[category].actions.append(action) else: - self.categories[category].actions.add(action, weight) \ No newline at end of file + self.categories[category].actions.add(action, weight) diff --git a/openlp/plugins/bibles/lib/__init__.py b/openlp/plugins/bibles/lib/__init__.py index f2797e16d..34e1bf5a5 100644 --- a/openlp/plugins/bibles/lib/__init__.py +++ b/openlp/plugins/bibles/lib/__init__.py @@ -109,7 +109,7 @@ def parse_reference(reference): regular expression looks like this: 1. ``^\s*(?!\s)(?P[\d]*[^\d]+)(?(?:`` + range_string + ``(?:%(sep_l)s|(?=\s*$)))+)\s*$`` @@ -177,7 +177,7 @@ def parse_reference(reference): to_verse = -1 if to_chapter > from_chapter: ref_list.append((book, from_chapter, from_verse, -1)) - for i in range(from_chapter + 1, to_chapter - 1): + for i in range(from_chapter + 1, to_chapter): ref_list.append((book, i, 1, -1)) ref_list.append((book, to_chapter, 1, to_verse)) elif to_verse >= from_verse or to_verse == -1: diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 4ecd4b49e..f5e7b3966 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -507,6 +507,7 @@ class BibleMediaItem(MediaManagerItem): """ log.debug(u'Advanced Search Button pressed') self.advancedSearchButton.setEnabled(False) + Receiver.send_message(u'openlp_process_events') bible = unicode(self.advancedVersionComboBox.currentText()) second_bible = unicode(self.advancedSecondComboBox.currentText()) book = unicode(self.advancedBookComboBox.currentText()) @@ -519,6 +520,7 @@ class BibleMediaItem(MediaManagerItem): verse_range = chapter_from + verse_separator + verse_from + \ 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) if second_bible: self.second_search_results = self.parent.manager.get_verses( @@ -541,7 +543,9 @@ class BibleMediaItem(MediaManagerItem): self.displayResults(bible, second_bible) else: self.displayResults(bible, second_bible) + Receiver.send_message(u'cursor_normal') self.advancedSearchButton.setEnabled(True) + Receiver.send_message(u'openlp_process_events') def onQuickSearchButton(self): """ @@ -550,6 +554,7 @@ class BibleMediaItem(MediaManagerItem): """ log.debug(u'Quick Search Button pressed') self.quickSearchButton.setEnabled(False) + Receiver.send_message(u'openlp_process_events') bible = unicode(self.quickVersionComboBox.currentText()) second_bible = unicode(self.quickSecondComboBox.currentText()) text = unicode(self.quickSearchEdit.text()) @@ -591,6 +596,7 @@ class BibleMediaItem(MediaManagerItem): self.displayResults(bible, second_bible) self.quickSearchButton.setEnabled(True) Receiver.send_message(u'cursor_normal') + Receiver.send_message(u'openlp_process_events') def displayResults(self, bible, second_bible=u''): """ diff --git a/openlp/plugins/bibles/resources/httpbooks.sqlite b/openlp/plugins/bibles/resources/httpbooks.sqlite index 4d89d0243..406914b63 100644 Binary files a/openlp/plugins/bibles/resources/httpbooks.sqlite and b/openlp/plugins/bibles/resources/httpbooks.sqlite differ diff --git a/openlp/plugins/presentations/lib/impresscontroller.py b/openlp/plugins/presentations/lib/impresscontroller.py index 516c595c7..6ca67c2ae 100644 --- a/openlp/plugins/presentations/lib/impresscontroller.py +++ b/openlp/plugins/presentations/lib/impresscontroller.py @@ -51,7 +51,7 @@ else: from PyQt4 import QtCore -from openlp.core.utils import delete_file +from openlp.core.utils import delete_file, get_uno_command, get_uno_instance from presentationcontroller import PresentationController, PresentationDocument log = logging.getLogger(__name__) @@ -75,7 +75,6 @@ class ImpressController(PresentationController): self.process = None self.desktop = None self.manager = None - self.uno_connection_type = u'pipe' #u'socket' def check_available(self): """ @@ -100,14 +99,7 @@ class ImpressController(PresentationController): self.manager._FlagAsMethod(u'Bridge_GetValueObject') else: # -headless - if self.uno_connection_type == u'pipe': - cmd = u'openoffice.org -nologo -norestore -minimized ' \ - + u'-invisible -nofirststartwizard ' \ - + u'-accept=pipe,name=openlp_pipe;urp;' - else: - cmd = u'openoffice.org -nologo -norestore -minimized ' \ - + u'-invisible -nofirststartwizard ' \ - + u'-accept=socket,host=localhost,port=2002;urp;' + cmd = get_uno_command() self.process = QtCore.QProcess() self.process.startDetached(cmd) self.process.waitForStarted() @@ -118,7 +110,7 @@ class ImpressController(PresentationController): which will be used to manage impress """ log.debug(u'get UNO Desktop Openoffice') - ctx = None + uno_instance = None loop = 0 log.debug(u'get UNO Desktop Openoffice - getComponentContext') context = uno.getComponentContext() @@ -126,27 +118,19 @@ class ImpressController(PresentationController): u'UnoUrlResolver') resolver = context.ServiceManager.createInstanceWithContext( u'com.sun.star.bridge.UnoUrlResolver', context) - while ctx is None and loop < 3: + while uno_instance is None and loop < 3: try: - log.debug(u'get UNO Desktop Openoffice - resolve') - if self.uno_connection_type == u'pipe': - ctx = resolver.resolve(u'uno:' \ - + u'pipe,name=openlp_pipe;' \ - + u'urp;StarOffice.ComponentContext') - else: - ctx = resolver.resolve(u'uno:' \ - + u'socket,host=localhost,port=2002;' \ - + u'urp;StarOffice.ComponentContext') + uno_instance = get_uno_instance(resolver) except: log.exception(u'Unable to find running instance ') self.start_process() loop += 1 try: - self.manager = ctx.ServiceManager + self.manager = uno_instance.ServiceManager log.debug(u'get UNO Desktop Openoffice - createInstanceWithContext' u' - Desktop') desktop = self.manager.createInstanceWithContext( - "com.sun.star.frame.Desktop", ctx ) + "com.sun.star.frame.Desktop", uno_instance) return desktop except: log.exception(u'Failed to get UNO desktop') diff --git a/openlp/plugins/presentations/lib/mediaitem.py b/openlp/plugins/presentations/lib/mediaitem.py index 2c9381a70..e72d97be1 100644 --- a/openlp/plugins/presentations/lib/mediaitem.py +++ b/openlp/plugins/presentations/lib/mediaitem.py @@ -268,12 +268,22 @@ class PresentationMediaItem(MediaManagerItem): doc.load_presentation() i = 1 img = doc.get_thumbnail_path(i, True) - while img: - service_item.add_from_command(path, name, img) - i = i + 1 - img = doc.get_thumbnail_path(i, True) - doc.close_presentation() - return True + if img: + while img: + service_item.add_from_command(path, name, img) + i = i + 1 + img = doc.get_thumbnail_path(i, True) + doc.close_presentation() + return True + else: + # File is no longer present + criticalErrorMessageBox( + translate('PresentationPlugin.MediaItem', + 'Missing Presentation'), + unicode(translate('PresentationPlugin.MediaItem', + 'The Presentation %s is incomplete,' + ' please reload.')) % filename) + return False else: # File is no longer present criticalErrorMessageBox( diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index d14ab9c36..3de251462 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -654,7 +654,7 @@ class SongImportForm(OpenLPWizard): 'Select EasiSlides songfile'), self.easiSlidesFilenameEdit ) - + def onEWBrowseButtonClicked(self): """ Get EasyWorship song database files @@ -784,7 +784,6 @@ class SongImportForm(OpenLPWizard): filenames=self.getListOfFiles(self.songBeamerFileListWidget) ) if importer.do_import(): - # reload songs self.progressLabel.setText( translate('SongsPlugin.SongImportForm', 'Finished import.')) else: diff --git a/openlp/plugins/songs/forms/songmaintenanceform.py b/openlp/plugins/songs/forms/songmaintenanceform.py index cd10dca9b..93a01623e 100644 --- a/openlp/plugins/songs/forms/songmaintenanceform.py +++ b/openlp/plugins/songs/forms/songmaintenanceform.py @@ -50,6 +50,14 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): self.authorform = AuthorsForm(self) self.topicform = TopicsForm(self) self.bookform = SongBookForm(self) + # Disable all edit and delete buttons, as there is no row selected. + self.authorsDeleteButton.setEnabled(False) + self.authorsEditButton.setEnabled(False) + self.topicsDeleteButton.setEnabled(False) + self.topicsEditButton.setEnabled(False) + self.booksDeleteButton.setEnabled(False) + self.booksEditButton.setEnabled(False) + # Signals QtCore.QObject.connect(self.authorsAddButton, QtCore.SIGNAL(u'pressed()'), self.onAuthorAddButtonClick) QtCore.QObject.connect(self.topicsAddButton, @@ -68,6 +76,15 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): QtCore.SIGNAL(u'pressed()'), self.onTopicDeleteButtonClick) QtCore.QObject.connect(self.booksDeleteButton, QtCore.SIGNAL(u'pressed()'), self.onBookDeleteButtonClick) + QtCore.QObject.connect(self.authorsListWidget, + QtCore.SIGNAL(u'currentRowChanged(int)'), + self.onAuthorsListRowChanged) + QtCore.QObject.connect(self.topicsListWidget, + QtCore.SIGNAL(u'currentRowChanged(int)'), + self.onTopicsListRowChanged) + QtCore.QObject.connect(self.booksListWidget, + QtCore.SIGNAL(u'currentRowChanged(int)'), + self.onBooksListRowChanged) def exec_(self): self.typeListWidget.setCurrentRow(0) @@ -115,12 +132,6 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): u' '.join([author.first_name, author.last_name])) author_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id)) self.authorsListWidget.addItem(author_name) - if self.authorsListWidget.count() == 0: - self.authorsDeleteButton.setEnabled(False) - self.authorsEditButton.setEnabled(False) - else: - self.authorsDeleteButton.setEnabled(True) - self.authorsEditButton.setEnabled(True) def resetTopics(self): """ @@ -132,12 +143,6 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): topic_name = QtGui.QListWidgetItem(topic.name) topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id)) self.topicsListWidget.addItem(topic_name) - if self.topicsListWidget.count() == 0: - self.topicsDeleteButton.setEnabled(False) - self.topicsEditButton.setEnabled(False) - else: - self.topicsDeleteButton.setEnabled(True) - self.topicsEditButton.setEnabled(True) def resetBooks(self): """ @@ -150,31 +155,27 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): book.publisher)) book_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(book.id)) self.booksListWidget.addItem(book_name) - if self.booksListWidget.count() == 0: - self.booksDeleteButton.setEnabled(False) - self.booksEditButton.setEnabled(False) - else: - self.booksDeleteButton.setEnabled(True) - self.booksEditButton.setEnabled(True) def checkAuthor(self, new_author, edit=False): """ - Returns False if the given Author is already in the list otherwise - True. + Returns *False* if the given Author already exists, otherwise *True*. + + ``edit`` + If we edit an item, this should be *True*. """ authors = self.manager.get_all_objects(Author, and_(Author.first_name == new_author.first_name, Author.last_name == new_author.last_name, Author.display_name == new_author.display_name)) + # Check if this author already exists. if len(authors) > 0: # If we edit an existing Author, we need to make sure that we do - # not return False when nothing has changed (because this would - # cause an error message later on). + # not return False when nothing has changed. if edit: - if authors[0].id == new_author.id: - return True - else: - return False + for author in authors: + if author.id != new_author.id: + return False + return True else: return False else: @@ -182,19 +183,21 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def checkTopic(self, new_topic, edit=False): """ - Returns False if the given Topic is already in the list otherwise True. + Returns *False* if the given Topic already exists, otherwise *True*. + + ``edit`` + If we edit an item, this should be *True*. """ topics = self.manager.get_all_objects(Topic, Topic.name == new_topic.name) if len(topics) > 0: # If we edit an existing Topic, we need to make sure that we do - # not return False when nothing has changed (because this would - # cause an error message later on). + # not return False when nothing has changed. if edit: - if topics[0].id == new_topic.id: - return True - else: - return False + for topic in topics: + if topic.id != new_topic.id: + return False + return True else: return False else: @@ -202,20 +205,22 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): def checkBook(self, new_book, edit=False): """ - Returns False if the given Book is already in the list otherwise True. + Returns *False* if the given Topic already exists, otherwise *True*. + + ``edit`` + If we edit an item, this should be *True*. """ books = self.manager.get_all_objects(Book, and_(Book.name == new_book.name, Book.publisher == new_book.publisher)) if len(books) > 0: # If we edit an existing Book, we need to make sure that we do - # not return False when nothing has changed (because this would - # cause an error message later on). + # not return False when nothing has changed. if edit: - if books[0].id == new_book.id: - return True - else: - return False + for book in books: + if book.id != new_book.id: + return False + return True else: return False else: @@ -390,12 +395,14 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): Merges two authors into one author. ``old_author`` - The author which will be deleted afterwards. + The object, which was edited, that will be deleted """ + # Find the duplicate. existing_author = self.manager.get_object_filtered(Author, and_(Author.first_name == old_author.first_name, Author.last_name == old_author.last_name, Author.display_name == old_author.display_name)) + # Find the songs, which have the old_author as author. songs = self.manager.get_all_objects(Song, Song.authors.contains(old_author)) for song in songs: @@ -412,10 +419,12 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): Merges two topics into one topic. ``old_topic`` - The topic which will be deleted afterwards. + The object, which was edited, that will be deleted """ + # Find the duplicate. existing_topic = self.manager.get_object_filtered(Topic, Topic.name == old_topic.name) + # Find the songs, which have the old_topic as topic. songs = self.manager.get_all_objects(Song, Song.topics.contains(old_topic)) for song in songs: @@ -432,11 +441,13 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): Merges two books into one book. ``old_book`` - The book which will be deleted afterwards. + The object, which was edited, that will be deleted """ + # Find the duplicate. existing_book = self.manager.get_object_filtered(Book, and_(Book.name == old_book.name, Book.publisher == old_book.publisher)) + # Find the songs, which have the old_book as book. songs = self.manager.get_all_objects(Song, Song.song_book_id == old_book.id) for song in songs: @@ -482,3 +493,45 @@ class SongMaintenanceForm(QtGui.QDialog, Ui_SongMaintenanceDialog): 'This book cannot be deleted, it is currently ' 'assigned to at least one song.'), translate('SongsPlugin.SongMaintenanceForm', 'No book selected!')) + + def onAuthorsListRowChanged(self, row): + """ + Called when the *authorsListWidget* current's row has changed. + + ``row`` + The current row. If there is no current row, the value is -1 + """ + if row == -1: + self.authorsDeleteButton.setEnabled(False) + self.authorsEditButton.setEnabled(False) + else: + self.authorsDeleteButton.setEnabled(True) + self.authorsEditButton.setEnabled(True) + + def onTopicsListRowChanged(self, row): + """ + Called when the *booksListWidget* current's row has changed. + + ``row`` + The current row. If there is no current row, the value is -1. + """ + if row == -1: + self.topicsDeleteButton.setEnabled(False) + self.topicsEditButton.setEnabled(False) + else: + self.topicsDeleteButton.setEnabled(True) + self.topicsEditButton.setEnabled(True) + + def onBooksListRowChanged(self, row): + """ + Called when the *booksListWidget* current's row has changed. + + ``row`` + The current row. If there is no current row, the value is -1. + """ + if row == -1: + self.booksDeleteButton.setEnabled(False) + self.booksEditButton.setEnabled(False) + else: + self.booksDeleteButton.setEnabled(True) + self.booksEditButton.setEnabled(True) diff --git a/openlp/plugins/songs/lib/easislidesimport.py b/openlp/plugins/songs/lib/easislidesimport.py index 8685b6934..64523fd3a 100644 --- a/openlp/plugins/songs/lib/easislidesimport.py +++ b/openlp/plugins/songs/lib/easislidesimport.py @@ -27,7 +27,6 @@ import logging import os from lxml import etree, objectify -from lxml.etree import Error, LxmlError import re from openlp.core.lib import translate @@ -82,44 +81,43 @@ class EasiSlidesImport(SongImport): def _parse_song(self, song): self._success = True - self._add_title(song) - self._add_alttitle(song) - self._add_number(song) + self._add_title(self.title, song.Title1, True) + self._add_alttitle(self.alternate_title, song.Title2) + self._add_number(self.song_number, song.SongNumber) + if self.song_number == u'0': + self.song_number = u'' self._add_authors(song) self._add_copyright(song) - self._add_book(song) + self._add_book(self.song_book_name, song.BookReference) self._parse_and_add_lyrics(song) return self._success - def _add_title(self, song): - try: - self.title = unicode(song.Title1).strip() - except UnicodeDecodeError: - log.exception(u'Unicode decode error while decoding Title1') - self._success = False - except AttributeError: - log.exception(u'no Title1') - self._success = False + def _add_unicode_attribute(self, self_attribute, import_attribute, + mandatory=False): + """ + Add imported values to the song model converting them to unicode at the + same time. If the unicode decode fails or a mandatory attribute is not + present _success is set to False so the importer can react + appropriately. - def _add_alttitle(self, song): - try: - self.alternate_title = unicode(song.Title2).strip() - except UnicodeDecodeError: - log.exception(u'Unicode decode error while decoding Title2') - self._success = False - except AttributeError: - pass + ``self_attribute`` + The attribute in the song model to populate. - def _add_number(self, song): + ``import_attribute`` + The imported value to convert to unicode and save to the song. + + ``mandatory`` + Signals that this attribute must exist in a valid song. + """ try: - number = unicode(song.SongNumber) - if number != u'0': - self.song_number = number + self_attribute = unicode(import_attribute).strip() except UnicodeDecodeError: - log.exception(u'Unicode decode error while decoding SongNumber') + log.exception(u'UnicodeDecodeError decoding %s' % import_attribute) self._success = False except AttributeError: - pass + log.exception(u'No attribute %s' % import_attribute) + if mandatory: + self._success = False def _add_authors(self, song): try: @@ -159,15 +157,6 @@ class EasiSlidesImport(SongImport): pass self.add_copyright(u' '.join(copyright)) - def _add_book(self, song): - try: - self.song_book_name = unicode(song.BookReference).strip() - except UnicodeDecodeError: - log.exception(u'Unicode decode error while decoding BookReference') - self._success = False - except AttributeError: - pass - def _parse_and_add_lyrics(self, song): try: lyrics = unicode(song.Contents).strip() @@ -313,7 +302,6 @@ class EasiSlidesImport(SongImport): tag = SeqTypes[tag.lower()] else: continue - if tag in versetags: self.verse_order_list.append(tag) else: diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 67021616b..625f99f18 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -157,7 +157,6 @@ class SongMediaItem(MediaManagerItem): (5, u':/slides/slide_theme.png', translate('SongsPlugin.MediaItem', 'Themes')) ]) - self.configUpdated() def onSearchTextButtonClick(self): @@ -269,8 +268,8 @@ class SongMediaItem(MediaManagerItem): def onImportClick(self): if not hasattr(self, u'import_wizard'): self.import_wizard = SongImportForm(self, self.parent) - self.import_wizard.exec_() - Receiver.send_message(u'songs_load_list') + if self.import_wizard.exec_() == QtGui.QDialog.Accepted: + Receiver.send_message(u'songs_load_list') def onNewClick(self): log.debug(u'onNewClick') diff --git a/openlp/plugins/songs/lib/oooimport.py b/openlp/plugins/songs/lib/oooimport.py index be33cb8fb..45d1ce5b9 100644 --- a/openlp/plugins/songs/lib/oooimport.py +++ b/openlp/plugins/songs/lib/oooimport.py @@ -29,6 +29,7 @@ import os from PyQt4 import QtCore from openlp.core.lib import Receiver +from openlp.core.utils import get_uno_command, get_uno_instance from songimport import SongImport log = logging.getLogger(__name__) @@ -61,7 +62,6 @@ class OooImport(SongImport): self.document = None self.process_started = False self.filenames = kwargs[u'filenames'] - self.uno_connection_type = u'pipe' #u'socket' QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stop_import) @@ -105,25 +105,18 @@ class OooImport(SongImport): context = uno.getComponentContext() resolver = context.ServiceManager.createInstanceWithContext( u'com.sun.star.bridge.UnoUrlResolver', context) - ctx = None + uno_instance = None loop = 0 - while ctx is None and loop < 5: + while uno_instance is None and loop < 5: try: - if self.uno_connection_type == u'pipe': - ctx = resolver.resolve(u'uno:' \ - + u'pipe,name=openlp_pipe;' \ - + u'urp;StarOffice.ComponentContext') - else: - ctx = resolver.resolve(u'uno:' \ - + u'socket,host=localhost,port=2002;' \ - + u'urp;StarOffice.ComponentContext') + uno_instance = get_uno_instance(resolver) except: log.exception("Failed to resolve uno connection") - self.start_ooo_process() - loop += 1 - manager = ctx.ServiceManager + self.start_ooo_process() + loop += 1 + manager = uno_instance.ServiceManager self.desktop = manager.createInstanceWithContext( - "com.sun.star.frame.Desktop", ctx) + "com.sun.star.frame.Desktop", uno_instance) def start_ooo_process(self): try: @@ -132,14 +125,7 @@ class OooImport(SongImport): self.manager._FlagAsMethod(u'Bridge_GetStruct') self.manager._FlagAsMethod(u'Bridge_GetValueObject') else: - if self.uno_connection_type == u'pipe': - cmd = u'openoffice.org -nologo -norestore -minimized ' \ - + u'-invisible -nofirststartwizard ' \ - + u'-accept=pipe,name=openlp_pipe;urp;' - else: - cmd = u'openoffice.org -nologo -norestore -minimized ' \ - + u'-invisible -nofirststartwizard ' \ - + u'-accept=socket,host=localhost,port=2002;urp;' + cmd = get_uno_command() process = QtCore.QProcess() process.startDetached(cmd) process.waitForStarted() diff --git a/openlp/plugins/songs/lib/openlyricsimport.py b/openlp/plugins/songs/lib/openlyricsimport.py index 220160b1d..37407c75c 100644 --- a/openlp/plugins/songs/lib/openlyricsimport.py +++ b/openlp/plugins/songs/lib/openlyricsimport.py @@ -61,17 +61,18 @@ class OpenLyricsImport(SongImport): Imports the songs. """ self.import_wizard.progressBar.setMaximum(len(self.import_source)) + parser = etree.XMLParser(remove_blank_text=True) for file_path in self.import_source: if self.stop_import_flag: return False self.import_wizard.incrementProgressBar(unicode(translate( 'SongsPlugin.OpenLyricsImport', 'Importing %s...')) % os.path.basename(file_path)) - parser = etree.XMLParser(remove_blank_text=True) - parsed_file = etree.parse(file_path, parser) - xml = unicode(etree.tostring(parsed_file)) - if self.openLyrics.xml_to_song(xml) is None: - log.debug(u'File could not be imported: %s' % file_path) - # Importing this song failed! For now we stop import. - return False + try: + parsed_file = etree.parse(file_path, parser) + xml = unicode(etree.tostring(parsed_file)) + if self.openLyrics.xml_to_song(xml) is None: + log.debug(u'File could not be imported: %s' % file_path) + except etree.XMLSyntaxError: + log.exception(u'XML syntax error in file %s' % file_path) return True diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 3ce271466..cab0aacf6 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -197,16 +197,24 @@ class SongImport(QtCore.QObject): return self.media_files.append(filename) - def add_verse(self, verse, versetag=u'V'): + def add_verse(self, versetext, versetag=u'V', lang=None): """ - Add a verse. This is the whole verse, lines split by \n - Verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the verses/ - choruses itself) or None, where it will assume verse - It will also attempt to detect duplicates. In this case it will just - add to the verse order + Add a verse. This is the whole verse, lines split by \n. It will also + attempt to detect duplicates. In this case it will just add to the verse + order. + + ``versetext`` + The text of the verse. + + ``versetag`` + The verse tag can be V1/C1/B etc, or 'V' and 'C' (will count the + verses/choruses itself) or None, where it will assume verse. + + ``lang`` + The language code (ISO-639) of the verse, for example *en* or *de*. """ - for (oldversetag, oldverse) in self.verses: - if oldverse.strip() == verse.strip(): + for (oldversetag, oldverse, oldlang) in self.verses: + if oldverse.strip() == versetext.strip(): self.verse_order_list.append(oldversetag) return if versetag[0] in self.versecounts: @@ -217,7 +225,7 @@ class SongImport(QtCore.QObject): versetag += unicode(self.versecounts[versetag[0]]) elif int(versetag[1:]) > self.versecounts[versetag[0]]: self.versecounts[versetag[0]] = int(versetag[1:]) - self.verses.append([versetag, verse.rstrip()]) + self.verses.append([versetag, versetext.rstrip(), lang]) self.verse_order_list.append(versetag) if versetag.startswith(u'V') and self.contains_verse(u'C1'): self.verse_order_list.append(u'C1') @@ -266,7 +274,7 @@ class SongImport(QtCore.QObject): verses_changed_to_other = {} sxml = SongXML() other_count = 1 - for (versetag, versetext) in self.verses: + for (versetag, versetext, lang) in self.verses: if versetag[0] == u'C': versetype = VerseType.to_string(VerseType.Chorus) elif versetag[0] == u'V': @@ -286,7 +294,7 @@ class SongImport(QtCore.QObject): versetype = VerseType.to_string(VerseType.Other) log.info(u'Versetype %s changing to %s' , versetag, newversetag) versetag = newversetag - sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext) + sxml.add_verse_to_lyrics(versetype, versetag[1:], versetext, lang) song.search_lyrics += u' ' + self.remove_punctuation(versetext) song.search_lyrics = song.search_lyrics.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') @@ -338,7 +346,7 @@ class SongImport(QtCore.QObject): + u'========================================' print u'TITLE: ' + self.title print u'ALT TITLE: ' + self.alternate_title - for (versetag, versetext) in self.verses: + for (versetag, versetext, lang) in self.verses: print u'VERSE ' + versetag + u': ' + versetext print u'ORDER: ' + u' '.join(self.verse_order_list) for author in self.authors: diff --git a/openlp/plugins/songs/lib/xml.py b/openlp/plugins/songs/lib/xml.py index 88459b797..91bfdb025 100644 --- a/openlp/plugins/songs/lib/xml.py +++ b/openlp/plugins/songs/lib/xml.py @@ -31,7 +31,7 @@ The basic XML for storing the lyrics in the song database is of the format:: - + @@ -84,7 +84,7 @@ class SongXML(object): self.song_xml = objectify.fromstring(u'') self.lyrics = etree.SubElement(self.song_xml, u'lyrics') - def add_verse_to_lyrics(self, type, number, content): + def add_verse_to_lyrics(self, type, number, content, lang=None): """ Add a verse to the ** tag. @@ -97,9 +97,15 @@ class SongXML(object): ``content`` The actual text of the verse to be stored. + + ``lang`` + The verse's language code (ISO-639). This is not required, but + should be added if available. """ verse = etree.Element(u'verse', type=unicode(type), label=unicode(number)) + if lang: + verse.set(u'lang', lang) verse.text = etree.CDATA(content) self.lyrics.append(verse) @@ -117,6 +123,11 @@ class SongXML(object): ``xml`` The XML of the song to be parsed. + + The returned list has the following format:: + + [[{'lang': 'en', 'type': 'V', 'label': '1'}, u"The English verse."], + [{'lang': 'en', 'type': 'C', 'label': '1'}, u"The English chorus."]] """ self.song_xml = None if xml[:5] == u'* - The attribute *translit* and *lang* are not supported. + The attribute *translit* is not supported. ** OpenLP supports this property. @@ -268,13 +279,16 @@ class OpenLyrics(object): # No xml get out of here. if not xml: return None - song = Song() if xml[:5] == u'').sub(u'', xml) song_xml = objectify.fromstring(xml) - properties = song_xml.properties + try: + properties = song_xml.properties + except AttributeError: + return None + song = Song() self._process_copyright(properties, song) self._process_cclinumber(properties, song) self._process_titles(properties, song) @@ -442,7 +456,10 @@ class OpenLyrics(object): if not verse_number: verse_number = u'1' temp_verse_order.append((verse_type, verse_number, verse_part)) - sxml.add_verse_to_lyrics(verse_type, verse_number, text) + lang = None + if self._get(verse, u'lang'): + lang = self._get(verse, u'lang') + sxml.add_verse_to_lyrics(verse_type, verse_number, text, lang) search_text = search_text + text song.search_lyrics = search_text.lower() song.lyrics = unicode(sxml.extract_xml(), u'utf-8') diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index 17e609fd4..7efe73db2 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -134,7 +134,7 @@ class SongsPlugin(Plugin): def onToolsReindexItemTriggered(self): """ - Rebuild the search title of each song. + Rebuild each song. """ maxSongs = self.manager.get_object_count(Song) progressDialog = QtGui.QProgressDialog( @@ -150,8 +150,13 @@ class SongsPlugin(Plugin): song.title = u'' if song.alternate_title is None: song.alternate_title = u'' - song.search_title = self.whitespace.sub(u' ', song.title.lower() + \ + song.search_title = self.whitespace.sub(u' ', song.title.lower() + u' ' + song.alternate_title.lower()) + # Remove the "language" attribute from lyrics tag. This is not very + # important, but this keeps the database clean. This can be removed + # when everybody has run the reindex tool once. + song.lyrics = song.lyrics.replace( + u'', u'') lyrics = u'' verses = SongXML().get_verses(song.lyrics) for verse in verses: @@ -159,8 +164,7 @@ class SongsPlugin(Plugin): song.search_lyrics = lyrics.lower() progressDialog.setValue(counter) self.manager.save_objects(songs) - counter += 1 - progressDialog.setValue(counter) + progressDialog.setValue(counter + 1) self.mediaItem.displayResultsSong( self.manager.get_all_objects(Song, order_by_ref=Song.search_title))