diff --git a/openlp/plugins/__init__.py b/openlp/plugins/__init__.py index 41a166708..9f3f83203 100644 --- a/openlp/plugins/__init__.py +++ b/openlp/plugins/__init__.py @@ -1,2 +1,3 @@ from plugin import Plugin from plugin_manager import PluginManager +from mediamanageritem import MediaManagerItem diff --git a/openlp/plugins/mediamanageritem.py b/openlp/plugins/mediamanageritem.py new file mode 100644 index 000000000..cc75fe7fa --- /dev/null +++ b/openlp/plugins/mediamanageritem.py @@ -0,0 +1,111 @@ +from PyQt4 import QtCore, QtGui +from openlp.resources import * +# from openlp.plugins import Plugin +import logging + +class ToolbarButton(QtGui.QToolButton): + log=logging.getLogger("ToolbarBtn") + log.info("loaded") + def __init__(self, parent, name, pixmap, tooltiptext, statustip=None): + self.log.info("create '%s', '%s'"%(name, pixmap)) + QtGui.QToolButton.__init__(self, parent.Toolbar) + self.icon = QtGui.QIcon() + self.icon.addPixmap(QtGui.QPixmap(pixmap), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.setIcon(self.icon) + self.setIconSize(QtCore.QSize(20, 20)) + self.setAutoRaise(True) +# self.setObjectName("%sItem"%name) + parent.ToolbarLayout.addWidget(self) + if statustip is None: + statustip=tooltiptext + self.setToolTip(QtGui.QApplication.translate("main_window", tooltiptext, None, QtGui.QApplication.UnicodeUTF8)) + self.setText(QtGui.QApplication.translate("main_window", tooltiptext, None, QtGui.QApplication.UnicodeUTF8)) + self.setStatusTip(QtGui.QApplication.translate("main_window", statustip, None, QtGui.QApplication.UnicodeUTF8)) + +class MediaManagerItem(QtGui.QWidget): + log=logging.getLogger("MediaMgrItem") + log.info("loaded") + name="Default_Item" + iconname=":/media/media_video.png" # xxx change this to some default bare icon + def __init__(self): + QtGui.QWidget.__init__(self) + self.log.info("init") + self.setGeometry(QtCore.QRect(0, 0, 267, 609)) +# self.setObjectName("%sPage"%self.name) + self.icon = QtGui.QIcon() + self.icon.addPixmap(QtGui.QPixmap(self.iconname), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.setGeometry(QtCore.QRect(0,0,267,609)) + + self.Layout = QtGui.QVBoxLayout(self) + self.Layout.setSpacing(0) + self.Layout.setMargin(0) +# self.Layout.setObjectName("Layout") + + # setup toolbar + self.Toolbar = QtGui.QWidget(self) +# self.Toolbar.setObjectName("%sToolbar"%self.name) + self.ToolbarLayout = QtGui.QHBoxLayout(self.Toolbar) + self.ToolbarLayout.setSpacing(0) + self.ToolbarLayout.setMargin(0) +# self.ToolbarLayout.setObjectName("%sToolbarLayout"%self.name) + + self.log.info("Adding toolbar item") + self.ToolbarButtons=[] + self.ToolbarButtons.append(ToolbarButton(self, "LoadItem", ":/images/image_load.png", "Load something", "Load something in")) + self.ToolbarButtons.append(ToolbarButton(self, "DeleteItem", ":/images/image_delete.png", "Delete something", "Delete something from")) + + # add items +# self.LoadItem = QtGui.QToolButton(self.Toolbar) +# icon17 = QtGui.QIcon() +# icon17.addPixmap(QtGui.QPixmap(":/images/image_load.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + +# self.LoadItem.setIcon(icon17) +# self.LoadItem.setIconSize(QtCore.QSize(20, 20)) +# self.LoadItem.setAutoRaise(True) +# self.LoadItem.setObjectName("LoadItem") +# self.ToolbarLayout.addWidget(self.LoadItem) + + +# self.ImageDeleteItem = QtGui.QToolButton(self.ImageToolbar) +# icon18 = QtGui.QIcon() +# icon18.addPixmap(QtGui.QPixmap(":/images/image_delete.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) +# self.ImageDeleteItem.setIcon(icon18) +# self.ImageDeleteItem.setIconSize(QtCore.QSize(20, 20)) +# self.ImageDeleteItem.setAutoRaise(True) +# self.ImageDeleteItem.setObjectName("ImageDeleteItem") +# self.ImageToolbarLayout.addWidget(self.ImageDeleteItem) +# self.ImageLine = QtGui.QFrame(self.ImageToolbar) +# self.ImageLine.setFrameShape(QtGui.QFrame.VLine) +# self.ImageLine.setFrameShadow(QtGui.QFrame.Sunken) +# self.ImageLine.setObjectName("ImageLine") +# self.ImageToolbarLayout.addWidget(self.ImageLine) +# self.ImageLiveItem = QtGui.QToolButton(self.ImageToolbar) +# self.ImageLiveItem.setIcon(icon5) +# self.ImageLiveItem.setIconSize(QtCore.QSize(20, 20)) +# self.ImageLiveItem.setAutoRaise(True) +# self.ImageLiveItem.setObjectName("ImageLiveItem") +# self.ImageToolbarLayout.addWidget(self.ImageLiveItem) +# self.ImageAddItem = QtGui.QToolButton(self.ImageToolbar) +# self.ImageAddItem.setIcon(icon6) +# self.ImageAddItem.setIconSize(QtCore.QSize(20, 20)) +# self.ImageAddItem.setAutoRaise(True) +# self.ImageAddItem.setObjectName("ImageAddItem") +# self.ImageToolbarLayout.addWidget(self.ImageAddItem) +# spacerItem6 = QtGui.QSpacerItem(105, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) +# self.ImageToolbarLayout.addItem(spacerItem6) +# self.Layout.addWidget(self.ImageToolbar) +# self.ImageListView = QtGui.QListWidget(self.ImagePage) +# self.ImageListView.setObjectName("ImageListView") +# self.Layout.addWidget(self.ImageListView) +# icon19 = QtGui.QIcon() +# icon19.addPixmap(QtGui.QPixmap(":/media/media_image.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) +# self.MediaToolBox.addItem(self.ImagePage, icon19, "") + +# self.ImageDeleteItem.setToolTip(QtGui.QApplication.translate("main_window", "Remove Video", None, QtGui.QApplication.UnicodeUTF8)) +# self.ImageDeleteItem.setText(QtGui.QApplication.translate("main_window", "Delete Image", None, QtGui.QApplication.UnicodeUTF8)) +# self.ImageLiveItem.setToolTip(QtGui.QApplication.translate("main_window", "Go Live!", None, QtGui.QApplication.UnicodeUTF8)) +# self.ImageAddItem.setToolTip(QtGui.QApplication.translate("main_window", "Add to Order of Service", None, QtGui.QApplication.UnicodeUTF8)) +# self.MediaToolBox.setItemText(self.MediaToolBox.indexOf(self.ImagePage), QtGui.QApplication.translate("main_window", "Images", None, QtGui.QApplication.UnicodeUTF8)) + + self.log.info("done init") + diff --git a/openlp/plugins/plugin.txt b/openlp/plugins/plugin.txt new file mode 100644 index 000000000..591024e20 --- /dev/null +++ b/openlp/plugins/plugin.txt @@ -0,0 +1,95 @@ +A plugin architecture for openlp 2.0 +------------------------------------ + +Why? +---- +To allow easy development of new "things to display". Examples: +* Bible passages +* Video +* Powerpoint/Openoffice Impress +* Lyrics :) (with chords, rich text, etc...) +* Musical score +* Midi files (hmmm, that's not a thing to display, but feels like it should be there...) +* Audio files, CDs (hmmm again) +* Collections of pictures +* Alerts to members of the congregation +... etc. + +The scope of these plugins is "things for display purposes", so +each needs to be able to: +* Render their display (on the projection screen and in a "shrunken form" + for preview purposes) + +These plugins need to be part of an OOS. This means they need to +* Be able to tell the OOS manager code what to put in the OOS for their "bit" +* Have a "tab" in the media manager, which they can render on request + to allow bits to be added to the OOS (or indeed shown live) + +In addition, some plugins need to be able to show +* How their multiple screens of data are split (eg verses) +* be told which screen to display + +Some plugins will also have things to configure, so will need +* to tell the core app that they need a preferences page +* and be able to render it and handle those prefs + +Some plugins may need to define +* Hot keys for their display actions. The core will have to pass these on... + +Other basic things all plugins will need: +* A name +* A version number +* Helpfile? + +Funnily enough, the core lyrics engine fits those requirements, so +could actually form a plugin... + +Each OOS entry may be made up of multiple plugins (to do text on +video), so each plugin that contributes to an OOS item will need a +"layering" priority. + +Plugin management +----------------- + +Plugins will be packages within the plugins/ directory. The plugin +manager will scan this directory when openlp loads for any class which +is based on the base Plugin class (or should we call it the +DisplayPlugin class to allow for other sorts??) + +These plugins are then queried for their capabilities/requirements and +spaces made in the prefs UI as required, and in the media manager. + +The OOS manager can find out what plugins it has available (we need to +report missing plugins when an OOS is loaded). + +The display manager will get a ref to a/some plugin(s) from the OOS +manager when each OOS item is made live, and can then call on each to +render their display. + +Each plugin will have basic attributes for +* name +* version number +* capabilities/requirements + (eg: + needs a prefs page, + needs key presses forwarding + has multiple screensful? + ) + +and a set of API functions for +* media manager rendering and handling +* creating OOS data +* being told OOS data +* set paint context +* render +* selecting a screen to display +* handling preferences +* shortcut key handling... + + +Other things to add: +Multiple monitors +Openoffice like plugins - external rendering. +update hook for rendering? +Event hook from app +Event hook to app (MIDI events....) diff --git a/openlp/plugins/test/test_mediamanageritem.py b/openlp/plugins/test/test_mediamanageritem.py new file mode 100644 index 000000000..d71a70271 --- /dev/null +++ b/openlp/plugins/test/test_mediamanageritem.py @@ -0,0 +1,80 @@ +from PyQt4 import QtCore, QtGui +import logging +logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', + datefmt='%m-%d %H:%M', + filename='plugins.log', + filemode='w') + +console=logging.StreamHandler() +# set a format which is simpler for console use +formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') +# tell the handler to use this format +console.setFormatter(formatter) +logging.getLogger('').addHandler(console) +log=logging.getLogger('') + +logging.info("Logging started") +import os, sys +mypath=os.path.split(os.path.abspath(__file__))[0] + +sys.path.insert(0,(os.path.join(mypath, '..' ,'..', '..'))) +from openlp.plugins import MediaManagerItem +class TestMediaManager: + def setup_class(self): + self.app = QtGui.QApplication([]) + logging.info ("App is " + str(self.app)) + self.main_window = QtGui.QMainWindow() + self.main_window.resize(800, 600) +# self.StatusBar = QtGui.QStatusBar(self.main_window) +# self.StatusBar.setObjectName("StatusBar") +# self.main_window.setStatusBar(self.StatusBar) + self.MediaManagerDock = QtGui.QDockWidget(self.main_window) + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.MediaManagerDock.sizePolicy().hasHeightForWidth()) + self.MediaManagerDock.setSizePolicy(sizePolicy) + icon = QtGui.QIcon() + icon.addPixmap(QtGui.QPixmap(":/system/system_mediamanager.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.MediaManagerDock.setWindowIcon(icon) + self.MediaManagerDock.setFloating(False) +# self.MediaManagerDock.setObjectName("MediaManagerDock") + self.MediaManagerContents = QtGui.QWidget() + sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.MediaManagerContents.sizePolicy().hasHeightForWidth()) + self.MediaManagerContents.setSizePolicy(sizePolicy) +# self.MediaManagerContents.setObjectName("MediaManagerContents") + self.MediaManagerLayout = QtGui.QHBoxLayout(self.MediaManagerContents) + self.MediaManagerLayout.setContentsMargins(0, 2, 0, 0) +# self.MediaManagerLayout.setObjectName("MediaManagerLayout") + self.MediaToolBox = QtGui.QToolBox(self.MediaManagerContents) +# self.MediaToolBox.setObjectName("MediaToolBox") + self.MediaManagerDock.setWidget(self.MediaManagerContents) + self.main_window.addDockWidget(QtCore.Qt.DockWidgetArea(1), self.MediaManagerDock) + self.MediaManagerLayout.addWidget(self.MediaToolBox) + def test1(self): + log=logging.getLogger("test1") + log.info("Start") + i1=MediaManagerItem() + i2=MediaManagerItem() + log.info("i1"+str(i1)) + log.info("i2"+str(i2)) + self.MediaToolBox.addItem(i1, i1.icon, "Test1") + self.MediaToolBox.addItem(i2, i2.icon, "Test2") + self.MediaToolBox.setItemText(self.MediaToolBox.indexOf(i1), QtGui.QApplication.translate("main_window", "Item1", None, QtGui.QApplication.UnicodeUTF8)) + self.MediaToolBox.setItemText(self.MediaToolBox.indexOf(i2), QtGui.QApplication.translate("main_window", "Item2", None, QtGui.QApplication.UnicodeUTF8)) + log.info("Show window") + self.main_window.show() +# self.app.exec_() + log.info("End") + return 1 + +if __name__=="__main__": + t=TestMediaManager() + t.setup_class() + t.test1() + log.info("exec") + t.app.exec_()