diff --git a/openlp/core/lib/eventreceiver.py b/openlp/core/lib/eventreceiver.py index 7f6caacc1..ff8e8f925 100644 --- a/openlp/core/lib/eventreceiver.py +++ b/openlp/core/lib/eventreceiver.py @@ -78,6 +78,8 @@ class EventReceiver(QtCore.QObject): ``{plugin}_stop`` Requests a plugin to handle a stop event + ``audit_live`` + Sends live song audit requests to the audit component """ global log log = logging.getLogger(u'EventReceiver') diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 7557348ca..b8e299211 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -178,8 +178,16 @@ class MediaManagerItem(QtGui.QWidget): """ # Add a toolbar self.addToolbar() - #Allow the plugin to define it's own header + #Allow the plugin to define buttons at start of bar self.addStartHeaderBar() + #Add the middle of the tool bar (pre defined) + self.addMiddleHeaderBar() + #Allow the plugin to define buttons at end of bar + self.addEndHeaderBar() + #Add the list view + self.addListViewToToolBar() + + def addMiddleHeaderBar(self): # Create buttons for the toolbar ## File Button ## if self.hasFileIcon: @@ -221,8 +229,8 @@ class MediaManagerItem(QtGui.QWidget): translate(self.TranslationContext, u'Add '+self.PluginTextShort+u' To Service'), translate(self.TranslationContext, u'Add the selected item(s) to the service'), u':/system/system_add.png', self.onAddClick, self.PluginTextShort+u'AddItem') - #Allow the plugin to define it's own header - self.addEndHeaderBar() + + def addListViewToToolBar(self): #Add the List widget self.ListView = self.ListViewWithDnD_class() self.ListView.uniformItemSizes = True diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index 87c999b97..a64b4938d 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -166,6 +166,15 @@ class Plugin(object): """ pass + def add_tools_menu_item(self, tools_menu): + """ + Create a menu item and add it to the "Tools" menu. + + ``tools_menu`` + The Tools menu + """ + pass + def get_settings_tab(self): """ Create a tab for the settings window. diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index ecce6747b..4f0ae3742 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -178,6 +178,18 @@ class PluginManager(object): if plugin[u'status'] == u'Active': plugin[u'plugin'].add_export_menu_item(export_menu) + def hook_tools_menu(self, tools_menu): + """ + Loop through all the plugins and give them an opportunity to add an + item to the tools menu. + + ``tools_menu`` + The Tools menu. + """ + for plugin in self.plugins: + if plugin[u'status'] == u'Active': + plugin[u'plugin'].add_tools_menu_item(tools_menu) + def initialise_plugins(self): """ Loop through all the plugins and give them an opportunity to diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 9585d11e1..40ddbd9da 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -58,6 +58,7 @@ class ServiceItem(object): self.shortname = hostplugin.name self.name = self.plugin.name self.title = u'' + self.audit = u'' self.items = [] self.iconic_representation = None self.raw_slides = None @@ -185,7 +186,8 @@ class ServiceItem(object): u'title':self.title, u'icon':self.icon, u'footer':self.raw_footer, - u'type':self.service_item_type + u'type':self.service_item_type, + u'audit':self.audit } oos_data = [] if self.service_item_type == ServiceType.Text: @@ -218,6 +220,7 @@ class ServiceItem(object): self.theme = header[u'theme'] self.addIcon(header[u'icon']) self.raw_footer = header[u'footer'] + self.audit = header[u'audit'] if self.service_item_type == ServiceType.Text: for slide in serviceitem[u'serviceitem'][u'data']: self.service_frames.append(slide) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 67644643b..f2a90f8fd 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -545,6 +545,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.plugin_manager.hook_import_menu(self.FileImportMenu) # Call the hook method to pull in export menus. self.plugin_manager.hook_export_menu(self.FileExportMenu) + # Call the hook method to pull in tools menus. + self.plugin_manager.hook_tools_menu(self.ToolsMenu) # Call the initialise method to setup plugins. log.info(u'initialise plugins') self.plugin_manager.initialise_plugins() diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 33c652389..45068a42d 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -314,6 +314,7 @@ class SlideController(QtGui.QWidget): self.onSlideSelected() self.PreviewListWidget.setFocus() log.info(u'Display Rendering took %4s' % (time.time() - before)) + Receiver().send_message(u'audit_live', self.serviceitem.audit) log.debug(u'displayServiceManagerItems End') #Screen event methods @@ -382,22 +383,28 @@ class SlideController(QtGui.QWidget): def onStartLoop(self): """ - Go to the last slide. + Start the timer loop running and store the timer id """ if self.PreviewListWidget.rowCount() > 1: self.timer_id = self.startTimer(int(self.DelaySpinBox.value()) * 1000) def onStopLoop(self): """ - Go to the last slide. + Stop the timer loop running """ self.killTimer(self.timer_id) def timerEvent(self, event): + """ + If the timer event is for this window select next slide + """ if event.timerId() == self.timer_id: self.onSlideSelectedNext() def onGoLive(self): + """ + If preview copy slide item to live + """ row = self.PreviewListWidget.currentRow() if row > -1 and row < self.PreviewListWidget.rowCount(): self.parent.LiveController.addServiceManagerItem(self.commandItem, row) diff --git a/openlp/plugins/audit/__init__.py b/openlp/plugins/audit/__init__.py new file mode 100644 index 000000000..df3741192 --- /dev/null +++ b/openlp/plugins/audit/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2009 Raoul Snyman # +# Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten # +# Tinggaard, Jon Tibble, Jonathan Corwin, Maikel Stuivenberg, Scott Guerrieri # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### diff --git a/openlp/plugins/audit/auditplugin.py b/openlp/plugins/audit/auditplugin.py new file mode 100644 index 000000000..b0ad33a70 --- /dev/null +++ b/openlp/plugins/audit/auditplugin.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2009 Raoul Snyman # +# Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten # +# Tinggaard, Jon Tibble, Jonathan Corwin, Maikel Stuivenberg, Scott Guerrieri # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +import logging + +from PyQt4 import QtCore, QtGui +from datetime import date + +from openlp.core.lib import Plugin, Receiver, translate +from openlp.plugins.audit.lib import AuditTab + +class AuditPlugin(Plugin): + global log + log = logging.getLogger(u'AuditPlugin') + log.info(u'Audit Plugin loaded') + + def __init__(self, plugin_helpers): + # Call the parent constructor + Plugin.__init__(self, u'Audit', u'1.9.0', plugin_helpers) + self.weight = -4 + # Create the plugin icon + self.icon = QtGui.QIcon() + self.icon.addPixmap(QtGui.QPixmap(u':/media/media_image.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.auditfile = None + + def check_pre_conditions(self): + """ + Check to see if auditing is required + """ + log.debug('check_pre_conditions') + #Lets see if audit is required + if int(self.config.get_config(u'startup', 0)) == QtCore.Qt.Checked: + return True + else: + return False + + def add_tools_menu_item(self, tools_menu): + """ + Give the Audit plugin the opportunity to add items to the + **Tools** menu. + + ``tools_menu`` + The actual **Tools** menu item, so that your actions can + use it as their parent. + """ + AuditIcon = QtGui.QIcon() + AuditIcon.addPixmap(QtGui.QPixmap(u':/tools/tools_alert.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.ToolsAuditItem = QtGui.QAction(tools_menu) + self.ToolsAuditItem.setIcon(AuditIcon) + self.ToolsAuditItem.setCheckable(True) + self.ToolsAuditItem.setChecked(False) + self.ToolsAuditItem.setText(translate(u'AuditPlugin', u'A&udit')) + self.ToolsAuditItem.setStatusTip( + translate(u'AuditPlugin', u'Start/Stop live song auditing')) + self.ToolsAuditItem.setShortcut(translate(u'AuditPlugin', u'F4')) + self.ToolsAuditItem.setObjectName(u'ToolsAuditItem') + tools_menu.addSeparator() + tools_menu.addAction(self.ToolsAuditItem) + # Signals and slots + QtCore.QObject.connect(self.ToolsAuditItem, + QtCore.SIGNAL(u'visibilityChanged(bool)'), + self.ToolsAuditItem.setChecked) + QtCore.QObject.connect(self.ToolsAuditItem, + QtCore.SIGNAL(u'triggered(bool)'), + self.toggleAuditState) + + def get_settings_tab(self): + self.AuditTab = AuditTab() + return self.AuditTab + + def initialise(self): + log.info(u'Plugin Initialising') + QtCore.QObject.connect(Receiver.get_receiver(), + QtCore.SIGNAL(u'audit_live'), self.onReceiveAudit) + self.auditFile = open(u'openlp.aud', 'a') + self.auditActive = False + + def toggleAuditState(self): + self.auditActive = not self.auditActive + + def onReceiveAudit(self, auditData): + if self.auditActive: + self.auditFile.write(u'%s,%s\n' % (date.today(), auditData)) + self.auditFile.flush() + + def finalise(self): + log.debug(u'Finalise') + if self.auditFile is not None: + self.auditFile.close() diff --git a/openlp/plugins/audit/lib/__init__.py b/openlp/plugins/audit/lib/__init__.py new file mode 100644 index 000000000..9db18d784 --- /dev/null +++ b/openlp/plugins/audit/lib/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2009 Raoul Snyman # +# Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten # +# Tinggaard, Jon Tibble, Jonathan Corwin, Maikel Stuivenberg, Scott Guerrieri # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +from audittab import AuditTab diff --git a/openlp/plugins/audit/lib/audittab.py b/openlp/plugins/audit/lib/audittab.py new file mode 100644 index 000000000..ac3d545ef --- /dev/null +++ b/openlp/plugins/audit/lib/audittab.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2009 Raoul Snyman # +# Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley, Carsten # +# Tinggaard, Jon Tibble, Jonathan Corwin, Maikel Stuivenberg, Scott Guerrieri # +# --------------------------------------------------------------------------- # +# This program is free software; you can redistribute it and/or modify it # +# under the terms of the GNU General Public License as published by the Free # +# Software Foundation; version 2 of the License. # +# # +# This program is distributed in the hope that it will be useful, but WITHOUT # +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # +# more details. # +# # +# You should have received a copy of the GNU General Public License along # +# with this program; if not, write to the Free Software Foundation, Inc., 59 # +# Temple Place, Suite 330, Boston, MA 02111-1307 USA # +############################################################################### + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import SettingsTab, str_to_bool, translate, Receiver + +class AuditTab(SettingsTab): + """ + AuditTab is the Audit settings tab in the settings dialog. + """ + def __init__(self): + SettingsTab.__init__(self, translate(u'AuditTab', u'Audit'), u'Audit') + + def setupUi(self): + self.setObjectName(u'AuditTab') + self.AuditLayout = QtGui.QFormLayout(self) + self.AuditLayout.setObjectName(u'AuditLayout') + self.AuditModeGroupBox = QtGui.QGroupBox(self) + self.AuditModeGroupBox.setObjectName(u'AuditModeGroupBox') + self.AuditModeLayout = QtGui.QVBoxLayout(self.AuditModeGroupBox) + self.AuditModeLayout.setSpacing(8) + self.AuditModeLayout.setMargin(8) + self.AuditModeLayout.setObjectName(u'AuditModeLayout') + self.AuditPortSpinBox = QtGui.QSpinBox(self.AuditModeGroupBox) + self.AuditPortSpinBox.setObjectName(u'AuditPortSpinBox') + self.AuditPortSpinBox.setMaximum(32767) + self.AuditModeLayout.addWidget(self.AuditPortSpinBox) + self.AuditActive = QtGui.QCheckBox(self.AuditModeGroupBox) + self.AuditActive.setObjectName(u'AuditPortSpinBox') + self.AuditModeLayout.addWidget(self.AuditActive) + self.WarningLabel = QtGui.QLabel(self.AuditModeGroupBox) + self.WarningLabel.setObjectName(u'WarningLabel') + self.AuditModeLayout.addWidget(self.WarningLabel) + self.AuditLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.AuditModeGroupBox) + + def retranslateUi(self): + self.AuditModeGroupBox.setTitle(translate(u'AuditTab', u'Audit File')) + self.AuditActive.setText(translate(u'AuditTab', 'Audit available:')) + self.WarningLabel.setText(translate(u'AuditTab', u'A restart is needed for this change to become effective')) + + def load(self): + self.AuditPortSpinBox.setValue(int(self.config.get_config(u'Audit port', 4316))) + self.AuditActive.setChecked(int(self.config.get_config(u'startup', 0))) + + def save(self): + self.config.set_config(u'Audit port', unicode(self.AuditPortSpinBox.value())) + self.config.set_config(u'startup', unicode(self.AuditActive.checkState())) + diff --git a/openlp/plugins/songs/lib/mediaitem.py b/openlp/plugins/songs/lib/mediaitem.py index 9e65616e7..cce5cf8a8 100644 --- a/openlp/plugins/songs/lib/mediaitem.py +++ b/openlp/plugins/songs/lib/mediaitem.py @@ -269,17 +269,12 @@ class SongMediaItem(MediaManagerItem): self.parent.songmanager.delete_song(item_id) row = self.ListView.row(item) self.ListView.takeItem(row) -# -# def onSongPreviewClick(self): -# service_item = ServiceItem(self.parent) -# service_item.addIcon(u':/media/media_song.png') -# self.generateSlideData(service_item) -# self.parent.preview_controller.addServiceItem(service_item) def generateSlideData(self, service_item): raw_slides =[] raw_footer = [] author_list = u'' + author_audit = [] ccl = u'' item = self.ListView.currentItem() if item is None: @@ -302,6 +297,7 @@ class SongMediaItem(MediaManagerItem): if len(author_list) > 1: author_list = author_list + u', ' author_list = author_list + unicode(author.display_name) + author_audit.append(unicode(author.display_name)) if song.ccli_number == None or len(song.ccli_number) == 0: ccl = self.parent.settings.GeneralTab.CCLNumber else: @@ -312,16 +308,5 @@ class SongMediaItem(MediaManagerItem): raw_footer.append(unicode( translate(u'SongMediaItem', u'CCL Licence: ') + ccl )) service_item.raw_footer = raw_footer + service_item.audit = [service_item.title, author_audit, ccl] return True - -# def onSongLiveClick(self): -# service_item = ServiceItem(self.parent) -# service_item.addIcon(u':/media/media_song.png') -# self.generateSlideData(service_item) -# self.parent.live_controller.addServiceItem(service_item) -# -# def onSongAddClick(self): -# service_item = ServiceItem(self.parent) -# service_item.addIcon( u':/media/media_song.png') -# self.generateSlideData(service_item) -# self.parent.service_manager.addServiceItem(service_item) diff --git a/resources/images/openlp-2.qrc b/resources/images/openlp-2.qrc index 83c88c3e5..096c27dfe 100644 --- a/resources/images/openlp-2.qrc +++ b/resources/images/openlp-2.qrc @@ -49,6 +49,10 @@ import_remove.png import_load.png + + audit_start.png + audit_stop.png + export_selectall.png export_remove.png