From 10ba1db5f30b3f91d558dbc49ece9e082a1aa584 Mon Sep 17 00:00:00 2001 From: Tim Bentley Date: Thu, 13 Aug 2009 21:02:38 +0100 Subject: [PATCH] Fix bug on song saving Add new screen for Plugin status Add new presentation plugin code --- openlp/core/lib/pluginmanager.py | 8 +- openlp/core/ui/__init__.py | 1 + openlp/core/ui/mainwindow.py | 28 +- openlp/core/ui/plugindialoglistform.py | 76 ++++ .../lib/impressslidecontroller.py | 329 ++++++++++++++++++ openlp/plugins/songs/forms/editsongform.py | 2 +- resources/forms/plugindialoglistform.ui | 108 ++++++ 7 files changed, 548 insertions(+), 4 deletions(-) create mode 100644 openlp/core/ui/plugindialoglistform.py create mode 100644 openlp/plugins/presentations/lib/impressslidecontroller.py create mode 100644 resources/forms/plugindialoglistform.ui diff --git a/openlp/core/lib/pluginmanager.py b/openlp/core/lib/pluginmanager.py index fa4e36c32..26442cd82 100644 --- a/openlp/core/lib/pluginmanager.py +++ b/openlp/core/lib/pluginmanager.py @@ -86,18 +86,22 @@ class PluginManager(object): __import__(modulename, globals(), locals(), []) except ImportError, e: log.error(u'Failed to import module %s on path %s for reason %s', modulename, path, e.args[0]) - self.plugin_classes = Plugin.__subclasses__() + plugin_classes = Plugin.__subclasses__() self.plugins = [] + self.plugin_list=[] plugin_objects = [] - for p in self.plugin_classes: + for p in plugin_classes: try: plugin = p(self.plugin_helpers) log.debug(u'loaded plugin %s with helpers', unicode(p)) log.debug(u'Plugin: %s', unicode(p)) + pList = {u'name': plugin.name, u'version':plugin.version, u'status': u'Inactive'} if plugin.check_pre_conditions(): log.debug(u'Appending %s ', unicode(p)) plugin_objects.append(plugin) eventmanager.register(plugin) + pList[u'status'] = u'Active' + self.plugin_list.append(pList) except TypeError: log.error(u'loaded plugin %s has no helpers', unicode(p)) self.plugins = sorted(plugin_objects, self.order_by_weight) diff --git a/openlp/core/ui/__init__.py b/openlp/core/ui/__init__.py index 10b046748..7f8cc54eb 100644 --- a/openlp/core/ui/__init__.py +++ b/openlp/core/ui/__init__.py @@ -27,6 +27,7 @@ from generaltab import GeneralTab from themestab import ThemesTab from about import AboutForm from alertform import AlertForm +from plugindialoglistform import PluginForm from settingsform import SettingsForm from servicemanager import ServiceManager from thememanager import ThemeManager diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index fe5fc14ab..2a5e7764a 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -23,7 +23,8 @@ import logging from PyQt4 import QtCore, QtGui from openlp.core.ui import AboutForm, SettingsForm, AlertForm, \ - ServiceManager, ThemeManager, MainDisplay, SlideController + ServiceManager, ThemeManager, MainDisplay, SlideController, \ + PluginForm from openlp.core.lib import translate, Plugin, MediaManagerItem, \ SettingsTab, EventManager, RenderManager, PluginConfig, \ SettingsManager, PluginManager, EventType @@ -203,6 +204,14 @@ class Ui_MainWindow(object): QtGui.QIcon.Normal, QtGui.QIcon.Off) self.ToolsAlertItem.setIcon(AlertIcon) self.ToolsAlertItem.setObjectName(u'ToolsAlertItem') + + self.PluginItem = QtGui.QAction(MainWindow) + PluginIcon = QtGui.QIcon() + PluginIcon.addPixmap(QtGui.QPixmap(u':/tools/tools_alert.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.PluginItem.setIcon(AlertIcon) + self.PluginItem.setObjectName(u'PluginItem') + self.HelpDocumentationItem = QtGui.QAction(MainWindow) ContentsIcon = QtGui.QIcon() ContentsIcon.addPixmap(QtGui.QPixmap(u':/system/system_help_contents.png'), @@ -264,6 +273,7 @@ class Ui_MainWindow(object): self.OptionsMenu.addSeparator() self.OptionsMenu.addAction(self.OptionsSettingsItem) self.ToolsMenu.addAction(self.ToolsAlertItem) + self.ToolsMenu.addAction(self.PluginItem) self.ToolsMenu.addSeparator() self.ToolsMenu.addAction(self.ToolsAddToolItem) self.HelpMenu.addAction(self.HelpDocumentationItem) @@ -362,6 +372,12 @@ class Ui_MainWindow(object): self.ToolsAlertItem.setStatusTip( translate(u'mainWindow', u'Show an alert message')) self.ToolsAlertItem.setShortcut(translate(u'mainWindow', u'F7')) + + self.PluginItem.setText(translate(u'mainWindow', u'&Plugin')) + self.PluginItem.setStatusTip( + translate(u'mainWindow', u'List the Plugins')) + self.PluginItem.setShortcut(translate(u'mainWindow', u'F8')) + self.HelpDocumentationItem.setText( translate(u'mainWindow', u'&User Guide')) self.HelpAboutItem.setText(translate(u'mainWindow', u'&About')) @@ -408,6 +424,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): self.mainDisplay = MainDisplay(self, screens) self.generalConfig = PluginConfig(u'General') self.alertForm = AlertForm(self) + self.pluginForm = PluginForm(self) self.aboutForm = AboutForm() self.settingsForm = SettingsForm(self.screenList, self) # Set up the path with plugins @@ -441,6 +458,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked) QtCore.QObject.connect(self.ToolsAlertItem, QtCore.SIGNAL(u'triggered()'), self.onToolsAlertItemClicked) + QtCore.QObject.connect(self.PluginItem, + QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked) QtCore.QObject.connect(self.OptionsSettingsItem, QtCore.SIGNAL(u'triggered()'), self.onOptionsSettingsItemClicked) #warning cyclic dependency @@ -514,6 +533,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ self.alertForm.exec_() + def onPluginItemClicked(self): + """ + Show the Plugin form + """ + self.pluginForm.load() + self.pluginForm.exec_() + def onOptionsSettingsItemClicked(self): """ Show the Settings dialog diff --git a/openlp/core/ui/plugindialoglistform.py b/openlp/core/ui/plugindialoglistform.py new file mode 100644 index 000000000..f63115189 --- /dev/null +++ b/openlp/core/ui/plugindialoglistform.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'plugindialoglistform.ui' +# +# Created: Thu Aug 13 05:52:06 2009 +# by: PyQt4 UI code generator 4.5.4 +# +# WARNING! All changes made in this file will be lost! + +import logging +from PyQt4 import QtCore, QtGui +from openlp.core.lib import translate + +class PluginForm(QtGui.QDialog): + global log + log = logging.getLogger(u'PluginForm') + + def __init__(self, parent=None): + QtGui.QDialog.__init__(self, None) + self.parent = parent + self.setupUi(self) + log.debug(u'Defined') + + def setupUi(self, PluginViewDialog): + PluginViewDialog.setObjectName("PluginViewDialog") + PluginViewDialog.resize(400, 393) + self.PluginViewList = QtGui.QTableWidget(PluginViewDialog) + self.PluginViewList.setGeometry(QtCore.QRect(20, 10, 371, 331)) + self.PluginViewList.setObjectName("PluginViewList") + self.PluginViewList.setShowGrid(False) + self.PluginViewList.setGridStyle(QtCore.Qt.SolidLine) + self.PluginViewList.setSortingEnabled(False) + self.PluginViewList.setColumnCount(3) + item = QtGui.QTableWidgetItem() + self.PluginViewList.setHorizontalHeaderItem(0, item) + item = QtGui.QTableWidgetItem() + self.PluginViewList.setHorizontalHeaderItem(1, item) + item = QtGui.QTableWidgetItem() + self.PluginViewList.setHorizontalHeaderItem(2, item) + self.PluginViewList.horizontalHeader().setVisible(True) + self.PluginViewList.verticalHeader().setVisible(False) + self.ButtonBox = QtGui.QDialogButtonBox(PluginViewDialog) + self.ButtonBox.setGeometry(QtCore.QRect(220, 350, 170, 25)) + self.ButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok) + self.ButtonBox.setObjectName("ButtonBox") + + self.retranslateUi(PluginViewDialog) + QtCore.QObject.connect(self.ButtonBox, QtCore.SIGNAL("accepted()"), PluginViewDialog.close) + QtCore.QMetaObject.connectSlotsByName(PluginViewDialog) + + def retranslateUi(self, PluginViewDialog): + PluginViewDialog.setWindowTitle(QtGui.QApplication.translate("PluginViewDialog", "Plugin list", None, QtGui.QApplication.UnicodeUTF8)) + self.PluginViewList.horizontalHeaderItem(0).setText(QtGui.QApplication.translate("PluginViewDialog", "Name", None, QtGui.QApplication.UnicodeUTF8)) + self.PluginViewList.horizontalHeaderItem(1).setText(QtGui.QApplication.translate("PluginViewDialog", "Version", None, QtGui.QApplication.UnicodeUTF8)) + self.PluginViewList.horizontalHeaderItem(2).setText(QtGui.QApplication.translate("PluginViewDialog", "Status", None, QtGui.QApplication.UnicodeUTF8)) + + def load(self): + """ + Load the plugin details into the screen + """ + for plugin in self.parent.plugin_manager.plugin_list: + row = self.PluginViewList.rowCount() + self.PluginViewList.setRowCount(row + 1) + item1 = QtGui.QTableWidgetItem(plugin[u'name']) + item1.setTextAlignment(QtCore.Qt.AlignVCenter) + item2 = QtGui.QTableWidgetItem(plugin[u'version']) + item2.setTextAlignment(QtCore.Qt.AlignVCenter) + item3 = QtGui.QTableWidgetItem(plugin[u'status']) + item3.setTextAlignment(QtCore.Qt.AlignVCenter) + self.PluginViewList.setItem(row, 0, item1) + self.PluginViewList.setItem(row, 1, item2) + self.PluginViewList.setItem(row, 2, item3) + self.PluginViewList.setRowHeight(row, 15) + + + diff --git a/openlp/plugins/presentations/lib/impressslidecontroller.py b/openlp/plugins/presentations/lib/impressslidecontroller.py new file mode 100644 index 000000000..b8ba26e86 --- /dev/null +++ b/openlp/plugins/presentations/lib/impressslidecontroller.py @@ -0,0 +1,329 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 +""" +OpenLP - Open Source Lyrics Projection +Copyright (c) 2008 Raoul Snyman +Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley + +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 +""" +# OOo API documentation: +# http://api.openoffice.org/docs/common/ref/com/sun/star/presentation/XSlideShowController.html +# http://docs.go-oo.org/sd/html/classsd_1_1SlideShow.html +# http://www.oooforum.org/forum/viewtopic.phtml?t=5252 +# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Working_with_Presentations +# http://mail.python.org/pipermail/python-win32/2008-January/006676.html + +import os , subprocess +import time +import uno + +from PyQt4 import QtCore, QtGui +from openlp.core.lib import OpenLPToolbar, translate +from openlp.core.ui.slidecontroller import MasterToolbar + +class impressToolbar(MasterToolbar): + def __init__(self): + self.startOpenoffice() + self.isLive = True + + def createResolver(self): + self.localContext = uno.getComponentContext() + self.resolver = self.localContext.ServiceManager.createInstanceWithContext(u'com.sun.star.bridge.UnoUrlResolver', self.localContext) + try: + self.ctx = self.resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') + except: + return False + return True + + def buildEnvironment(self): + self.smgr = self.ctx.ServiceManager + self.desktop = self.smgr.createInstanceWithContext( "com.sun.star.frame.Desktop", self.ctx ) + self.model = self.desktop.getCurrentComponent() + text = self.model.Text + cursor = text.createTextCursor() + text.insertString(cursor, "Hello world", 0) + self.ctx.ServiceManager + self.createApp() + if self._sm == None: + # start OO here + # Create output log file + time.sleep(10) + self.createApp() + + def startOpenoffice(self): + cmd = u'openoffice.org -nologo -norestore -invisible -minimized -impress' + u'"' + u'-accept=socket,host=localhost,port=2002;urp;'+ u'"' + retval = subprocess.Popen(cmd, shell=True) + self.oopid = retval.pid + + def checkOoPid(self): + if os.name == u'nt': + import win32api + handle = win32api.OpenProcess(PROCESS_TERMINATE, False, self.oopid) + #todo need some code here + return True + elif os.name == u'mac': + pass + else: + procfile = open("/proc/%d/stat" %(self.oopid)) + file = procfile.readline().split()[1] + print file + if file == u'(soffice)' or file == u'(openoffice.org)': + return True + return False + + def createApp(self): + try: + self._app = self._sm.createInstance( "com.sun.star.frame.Desktop" ) + print "started" + except: + print "oops" + self._sm = None + self._app = None + return + + def getApp(self): + if self._app == None: + self.createApp() + if self._app == None: + return None + return self._app + + app = property(getApp) + + def quit(self): + self._app.Terminate() + self._app = None + self._sm = None + def defineToolbar(self): + # Controller toolbar + 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) + + if self.isLive: + self.Toolbar.addToolbarButton(u'First Slide', + u':/slides/slide_first.png', + translate(u'SlideController', u'Move to first'), + self.onSlideSelectedFirst) + self.Toolbar.addToolbarButton(u'Previous Slide', + u':/slides/slide_previous.png', + translate(u'SlideController', u'Move to previous'), + self.onSlideSelectedPrevious) + self.Toolbar.addToolbarButton(u'Next Slide', + u':/slides/slide_next.png', + translate(u'SlideController', u'Move to next'), + self.onSlideSelectedNext) + if self.isLive: + self.Toolbar.addToolbarButton(u'Last Slide', + u':/slides/slide_last.png', + translate(u'SlideController', u'Move to last'), + self.onSlideSelectedLast) + self.Toolbar.addSeparator() + self.Toolbar.addToolbarButton(u'Close Screen', + u':/slides/slide_close.png', + translate(u'SlideController', u'Close Screen'), + self.onBlankScreen) + + def serviceLoaded(self): + """ + method to allow toolbars to know when the service item + is fully in place + """ + pass + + def onSlideSelectedFirst(self): + """ + Go to the first slide. + """ + self.PreviewListWidget.selectRow(0) + self.onSlideSelected() + + def onSlideSelectedNext(self): + """ + Go to the next slide. + """ + row = self.PreviewListWidget.currentRow() + 1 + if row == self.PreviewListWidget.rowCount(): + row = 0 + self.PreviewListWidget.selectRow(row) + self.onSlideSelected() + + def onSlideSelectedPrevious(self): + """ + Go to the previous slide. + """ + row = self.PreviewListWidget.currentRow() - 1 + if row == -1: + row = self.PreviewListWidget.rowCount() - 1 + self.PreviewListWidget.selectRow(row) + self.onSlideSelected() + + def onSlideSelectedLast(self): + """ + Go to the last slide. + """ + self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount() - 1) + self.onSlideSelected() + + def onBlankScreen(self): + """ + Blank the screen. + """ + self.mainDisplay.blankDisplay() + + def onSlideSelected(self): + """ + Generate the preview when you click on a slide. + if this is the Live Controller also display on the screen + """ + row = self.PreviewListWidget.currentRow() + if row > -1 and row < self.PreviewListWidget.rowCount(): + label = self.PreviewListWidget.cellWidget(row, 0) + smallframe = label.pixmap() + frame = self.serviceitem.frames[row][u'image'] + self.SlidePreview.setPixmap(smallframe) + if self.isLive: + self.mainDisplay.frameView(frame) + + def addServiceItem(self, serviceitem, slideno = 1): + """ + Loads a ServiceItem into the system from plugins + Display the first slide + """ + log.debug(u'add Service Item') +# serviceitem.render() +# self.addServiceManagerItem(serviceitem, 0) + + def addServiceManagerItem(self, serviceitem, slideno): + """ + Loads a ServiceItem into the system from ServiceManager + Display the slide number passed + """ + log.debug(u'add Service Manager Item') +# self.PreviewListWidget.clear() +# self.PreviewListWidget.setRowCount(0) +# self.serviceitem = serviceitem +# framenumber = 0 +# for frame in self.serviceitem.frames: +# self.PreviewListWidget.setRowCount(self.PreviewListWidget.rowCount() + 1) +# pixmap = QtGui.QPixmap.fromImage(frame[u'image']) +# item = QtGui.QTableWidgetItem() +# label = QtGui.QLabel() +# label.setMargin(15) +# label.setScaledContents(True) +# width = 300 +# height = width * pixmap.height() / pixmap.width() +# label.setPixmap(pixmap) +# self.PreviewListWidget.setCellWidget(framenumber, 0,label) +# self.PreviewListWidget.setItem( framenumber, 0, item) +# self.PreviewListWidget.setRowHeight(framenumber, height) +# self.PreviewListWidget.setColumnWidth(0, width) +# framenumber += 1 +# if slideno > self.PreviewListWidget.rowCount(): +# self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount()) +# else: +# self.PreviewListWidget.selectRow(slideno) +# self.onSlideSelected() +# self.serviceLoaded() + + +class ImpressCOMPres(object): + + def __init__(self, oooApp, filename): + self.oooApp = oooApp + self.filename = filename + self.open() + + def getPres(self): + if self._pres == None: + self.open() + return self._pres + + pres = property(getPres) + + def open(self): + self.comp = self.oooApp.app.loadComponentFromURL(u'file:///' + self.filename, '_blank', 0, []) + self.presdoc = self.comp.getPresentation() + self.presdoc.start() + self._pres = self.presdoc.getController() + + def close(self): + self.pres.deactivate() + self.presdoc.end() + self.comp.dispose() + self._pres = None + self.presdoc = None + self.comp = None + + def isActive(self): + return self.pres.isRunning() and self.pres.isActive() + + def resume(self): + return self.pres.resume() + + def pause(self): + return self.pres.pause() + + def blankScreen(self): + self.pres.blankScreen(0) + + def stop(self): + self.pres.deactivate() + # self.presdoc.end() + + def go(self): + self.pres.activate() + # self.presdoc.start() + + def getSlideNumber(self): + return self.pres.getCurrentSlideIndex + + def setSlideNumber(self, slideno): + self.pres.gotoSlideIndex(slideno) + + slideNumber = property(getSlideNumber, setSlideNumber) + + def nextStep(self): + self.pres.gotoNextEffect() + + def prevStep(self): + self.pres.gotoPreviousSlide() + + def moveWindow(self, top, height, left, width): + # position the window somehow + pass + +class ImpressCOMSlide(object): + def __init__(self, pres, index): + self.pres = pres + self.slide = pres.getSlideByIndex(index) + + def preview(self): + if self.preview == None: + # get a slide somehow + pass + return self.preview + +if __name__ == '__main__': + ooo = Openoffice() + ooo.createResolver() + #show = ImpressCOMPres(ooo, u'/home/timali/test1.odp') + #show.go() + #show.resume() + #show.nextStep() diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 8d5176f9e..4dad397bb 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -356,7 +356,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.processTitle() self.songmanager.save_song(self.song) if self.title_change: - self.eventmanager.post_event(Event(EventType.LoadSongList), u'EditSongForm') + self.eventmanager.post_event(Event(EventType.LoadSongList, u'EditSongForm')) self.close() def processLyrics(self): diff --git a/resources/forms/plugindialoglistform.ui b/resources/forms/plugindialoglistform.ui new file mode 100644 index 000000000..3e76962bd --- /dev/null +++ b/resources/forms/plugindialoglistform.ui @@ -0,0 +1,108 @@ + + + PluginViewDialog + + + + 0 + 0 + 400 + 393 + + + + Plugin list + + + + + 20 + 10 + 371 + 331 + + + + false + + + Qt::SolidLine + + + 1 + + + true + + + true + + + false + + + + + Name + + + + + Version + + + + + Status + + + + + qqq + + + + + aaa + + + + + ccc + + + + + + + 220 + 350 + 170 + 25 + + + + QDialogButtonBox::Ok + + + + + + + ButtonBox + accepted() + PluginViewDialog + close() + + + 370 + 364 + + + 460 + 367 + + + + +