From 1cc973b334adbf18d1ec5d479898b40ddf8413b4 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Wed, 16 Sep 2009 06:01:11 +0100 Subject: [PATCH] Audit UI 2 --- openlp/plugins/audit/__init__.py | 23 +++++++ openlp/plugins/audit/auditplugin.py | 56 +++++++++++++++++ openlp/plugins/audit/lib/__init__.py | 26 ++++++++ openlp/plugins/audit/lib/audittab.py | 77 ++++++++++++++++++++++++ openlp/plugins/audit/lib/mediaitem.py | 83 ++++++++++++++++++++++++++ resources/images/audit_start.png | Bin 0 -> 3046 bytes resources/images/audit_stop.png | Bin 0 -> 3253 bytes 7 files changed, 265 insertions(+) create mode 100644 openlp/plugins/audit/__init__.py create mode 100644 openlp/plugins/audit/auditplugin.py create mode 100644 openlp/plugins/audit/lib/__init__.py create mode 100644 openlp/plugins/audit/lib/audittab.py create mode 100644 openlp/plugins/audit/lib/mediaitem.py create mode 100644 resources/images/audit_start.png create mode 100644 resources/images/audit_stop.png 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..130954003 --- /dev/null +++ b/openlp/plugins/audit/auditplugin.py @@ -0,0 +1,56 @@ +# -*- 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 openlp.core.lib import Plugin +from openlp.plugins.audit.lib import AuditMediaItem, 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) + + def get_settings_tab(self): + self.AuditTab = AuditTab() + return self.AuditTab + + def get_media_manager_item(self): + # Create the MediaManagerItem object + self.media_item = AuditMediaItem(self, self.icon, u'Audit') + return self.media_item + + def initialise(self): + log.info(u'Plugin Initialising') diff --git a/openlp/plugins/audit/lib/__init__.py b/openlp/plugins/audit/lib/__init__.py new file mode 100644 index 000000000..544b1dec2 --- /dev/null +++ b/openlp/plugins/audit/lib/__init__.py @@ -0,0 +1,26 @@ +# -*- 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 mediaitem import AuditMediaItem +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..91e6a88b3 --- /dev/null +++ b/openlp/plugins/audit/lib/audittab.py @@ -0,0 +1,77 @@ +# -*- 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.TimeoutLayout = QtGui.QHBoxLayout(self.AuditModeGroupBox) + self.TimeoutLayout.setSpacing(8) + self.TimeoutLayout.setMargin(0) + self.TimeoutLayout.setObjectName(u'TimeoutLayout') + self.TimeoutLabel = QtGui.QLabel(self.AuditModeGroupBox) + self.TimeoutLabel.setObjectName(u'TimeoutLabel') + self.TimeoutLayout.addWidget(self.TimeoutLabel) + self.TimeoutSpinBox = QtGui.QSpinBox(self.AuditModeGroupBox) + self.TimeoutSpinBox.setMaximum(180) + self.TimeoutSpinBox.setObjectName(u'TimeoutSpinBox') + self.TimeoutLayout.addWidget(self.TimeoutSpinBox) + self.TimeoutSpacer = QtGui.QSpacerItem(147, 20, + QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + self.TimeoutLayout.addItem(self.TimeoutSpacer) + self.AuditLayout.setWidget(0, QtGui.QFormLayout.LabelRole, self.AuditModeGroupBox) + # Signals and slots + QtCore.QObject.connect(self.TimeoutSpinBox, + QtCore.SIGNAL(u'valueChanged(int)'), self.onTimeoutSpinBoxChanged) + + def retranslateUi(self): + self.TimeoutLabel.setText(translate(u'AuditTab', u'Slide Loop Delay:')) + self.TimeoutSpinBox.setSuffix(translate(u'AuditTab', u's')) + + def onTimeoutSpinBoxChanged(self): + self.loop_delay = self.TimeoutSpinBox.value() + + def load(self): + self.loop_delay = int(self.config.get_config(u'loop delay', 5)) + self.TimeoutSpinBox.setValue(self.loop_delay) + + def save(self): + self.config.set_config(u'loop delay', self.loop_delay) + Receiver().send_message(u'update_spin_delay', self.loop_delay ) + + def postSetUp(self): + Receiver().send_message(u'update_spin_delay', self.loop_delay ) diff --git a/openlp/plugins/audit/lib/mediaitem.py b/openlp/plugins/audit/lib/mediaitem.py new file mode 100644 index 000000000..9b7a5aa7f --- /dev/null +++ b/openlp/plugins/audit/lib/mediaitem.py @@ -0,0 +1,83 @@ +# -*- 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 +import os + +from PyQt4 import QtCore, QtGui +from openlp.core.lib import MediaManagerItem, translate, buildIcon + +class AuditMediaItem(MediaManagerItem): + """ + This is the custom media manager item for Audits. + """ + global log + log = logging.getLogger(u'AuditMediaItem') + log.info(u'Audit Media Item loaded') + + def __init__(self, parent, icon, title): + self.TranslationContext = u'AuditPlugin' + self.PluginTextShort = u'Audit' + self.ConfigSection = u'Audits' + self.IconPath = u'Audit/Audit' + self.hasFileIcon = False + self.hasNewIcon = False + self.hasEditIcon = False + MediaManagerItem.__init__(self, parent, icon, title) + + def initialise(self): + pass + + def addStartHeaderBar(self): + self.startMessage = translate(self.TranslationContext, u'Start Collecting') + self.addToolbarButton(self.startMessage, + translate(self.TranslationContext, u'Start collecting alert messages '), + u':audit/audit_start.png', self.onStartClick, u'AuditStartItem') + self.stopMessage = translate(self.TranslationContext, u'Stop Collecting') + self.addToolbarButton(self.stopMessage, + translate(self.TranslationContext, u'Stop collecting alert messages '), + u':audit/audit_stop.png', self.onStopClick, u'AuditStopItem') + + def addMiddleHeaderBar(self): + pass + + def addListViewToToolBar(self): + self.ListView = QtGui.QListWidget() + self.ListView.uniformItemSizes = True + self.ListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) + self.ListView.setSpacing(1) + self.ListView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) + self.ListView.setAlternatingRowColors(True) + self.ListView.setDragEnabled(True) + self.ListView.setObjectName(u'AlertListView') + #Add tp PageLayout + self.PageLayout.addWidget(self.ListView) + + def onStartClick(self): + self.Toolbar.actions[self.startMessage].setVisible(False) + self.Toolbar.actions[self.stopMessage].setVisible(True) + + def onStopClick(self): + self.Toolbar.actions[self.startMessage].setVisible(True) + self.Toolbar.actions[self.stopMessage].setVisible(False) diff --git a/resources/images/audit_start.png b/resources/images/audit_start.png new file mode 100644 index 0000000000000000000000000000000000000000..1a741be174be6c42ccb2d1efd81c9ad13fb56a06 GIT binary patch literal 3046 zcmV zUQ9Hj*WFUf%mgitWTcsuMCxG?MFD}CXZB~dXZgMN&U-w~Ih-%g<=*e-b7tlb1a>=n z7Nh~NyzBr-0t4GPQ-zfP!lsvj;0H`Pb$r%AO|7S0wl6GB)Six!HhJ7D_Ac(%x~N9ilZ2@%cbZS(8X*!}wz_9yDIVSjU!y}jXYh-!|ucTnCh zw?)t#_ZHF~-VLO?#JB-D)bnXf?o{eU&U3`^%;sB(iylYG1HGOhFZA3?o`_Ku;r#+0k*8pFO3}v60F6Hxr__t9S9ME|Y6=M+aWN$& zv1nqGa<|RrI@vT?ciNt&ju(r-?cA^3uuOtrTa0>6{0hLDuB3^>FgL0FO??1t3%Jb` zhq;hDFlnAZb8Ci@MSHebwVdvp2edz_$DX0SLA`B?>mqSdQWHyviyj^1(Rjs}NnTc$ z6i=Q)@TK4^!ES_@A@u;!eRKy5(Vi%+)>fw` zcjm!w_Q}e4u?j&~mF=c+m|v>(rVIoXvC*bvfR6o^Lh-)<4X@tH75iget9?Qoj9Fb9 zhDq}rns*$aJ-jPs$#_RS52(j>T`8en>gi!U~Mj*t*t-E_QbYfU{kF!#WDUTCG%@J_c}9LW8&qpuNJBD&7L9 zkFOacPQqu!m?~BRh$p0-Vv#?0P`1m)6q?sRRr9oe@1p3xb5yZM)MNccxkYowsqSzJZKGWMcH+s99a`3s#U1VB<`Gvcf(jt0e z{PQYjDeX0lsf(dIOSb$v_1Mp9$EnwxEgvS%?awVoiOVMG$B{>%FZd6?*BZe}o&xg; z^T5#coG?j$olgbOC+e$VJ``KW$={i80NmMOopWOq7M@me+eace-Z9@i8=&K|u}XX% z=Z8Fj;s-eQNgi<_K3iN~F$>e?@=%IQl5tLZ2HNYmXuL>wVn0VN_E7IK>byGOm< z;ndT7P#T53$WfLchqwvE!*H*z= zT+pD6zC-H!N`n>+;JqC%*j@u*U&D5E;NROfS{8TUo$+hwd}lXItD~s%Fs9j2?9UU@ zcQkJ=wB*yCy^tNGJ5OU^BK4@Nl{?fcsBoV+Jd>{>E^pQjkcaxD;_-V$YG0A3piR|e zP;dPyS9o{BC@k3Fn+d=j@SZjfbokpwZ8;R<=^14)SOD}RVKgiN=s9=DYhVZ9hqpHRscu|)M9+cM0axH5=Cyz-N^P#Y&cC<8afJ3D&v(f$%6%*SJ$9dgdX*pC-w;QN zw`LI6QEF)<4<$n>A}{oGlc&IgJmLIHES{kj@~UnB_O5cJu+W>YT35Dz4QKTIr60_% zKu zJ@BljJM6hkJ@PEqD(aOknuig`y1acialHkum&pUYHjo#3hLNWr=t8bS5<3Y1TcEFW zQZ=h0zdQZ5)MQ`82DONyt2Gv`<3B&ios}?Lk-d%fE(nNIJ6)+HqGfs3p@7Wm-IqX5 zUmZ^{3GvaMAb&Qv&(mDX^t?}ds?jx(?z~NQMm_eV&Xd$DI$Ak#q(*x-anZv_9_Y25 zywLL|c?xg^;#n7-B}^9zAVv`QVQn%qcTs#!v9sjt7|rULW+?-W_w|K3azTYWIoi1v(>@yXZxp1O1+CCtL#qgt7`SGlQlHtAyvEA8X|Y zy-VTUhT+N#?uGnG=l&xSi|N*5Exhjo5dn{tS%z>TXveA)inrH*ksosO|J!j@MGIYBu z-xB@(;nV+p*!p;p&slF zqF&@oCk}G25*IzP$pgJ|$O}Ci$@72Pbl{Ls_b1l?001I-R9JLVZ)S9NVRB^v0C?If oFE7{2%*!rLPAo{(%P&d?05;eLSP)anTmS$707*qoM6N<$f_Agk>;M1& literal 0 HcmV?d00001 diff --git a/resources/images/audit_stop.png b/resources/images/audit_stop.png new file mode 100644 index 0000000000000000000000000000000000000000..0dfaa6af3480a572db50909deb7afefadc875a8c GIT binary patch literal 3253 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 literal 0 HcmV?d00001