diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index b4edc06fd..272ee47f3 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -93,6 +93,7 @@ class Plugin(object): self.theme_manager=plugin_helpers[u'theme'] self.event_manager=plugin_helpers[u'event'] self.render_manager=plugin_helpers[u'render'] + self.service_manager=plugin_helpers[u'service'] def check_pre_conditions(self): """ diff --git a/openlp/core/lib/rendermanager.py b/openlp/core/lib/rendermanager.py index bded79ca7..b891ce0a0 100644 --- a/openlp/core/lib/rendermanager.py +++ b/openlp/core/lib/rendermanager.py @@ -76,7 +76,6 @@ class RenderManager: def generate_preview(self, themedata): self.calculate_default(QtCore.QSize(800,600)) self.renderer.set_theme(themedata) - self.build_text_rectangle(themedata) frame = QtGui.QPixmap(self.width, self.height) @@ -96,14 +95,19 @@ class RenderManager: def format_slide(self, words, footer): self.calculate_default(QtCore.QSize(800,600)) + frame = QtGui.QPixmap(self.width, self.height) + self.renderer.set_paint_dest(frame) return self.renderer.format_slide(words, footer) def generate_slide(self,main_text, footer_text, preview=True): if preview == True: self.calculate_default(QtCore.QSize(800,600)) + frame = QtGui.QPixmap(self.width, self.height) + self.renderer.set_paint_dest(frame) + answer=self.renderer.render_lines(main_text, footer_text) - return self.frame + return frame def calculate_default(self, screen): self.width = screen.width() diff --git a/openlp/core/lib/serviceitem.py b/openlp/core/lib/serviceitem.py index 7d2224169..1e438ff1c 100644 --- a/openlp/core/lib/serviceitem.py +++ b/openlp/core/lib/serviceitem.py @@ -3,7 +3,7 @@ """ OpenLP - Open Source Lyrics Projection Copyright (c) 2008 Raoul Snyman -Portions copyright (c) 2008 Martin Thompson, Tim Bentley +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 @@ -17,31 +17,68 @@ 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 types +from PyQt4 import QtCore, QtGui from PyQt4.QtCore import * from PyQt4.QtGui import * -class ServiceItem(QAbstractItemModel): +class ServiceItem(): """ The service item is a base class for the plugins to use to interact with the service manager, the slide controller, and the projection screen compositor. """ + global log + log=logging.getLogger(u'ServiceItem') + log.info(u'Service Item created') def __init__(self, hostplugin): """ Init Method """ - self.plugin=hostplugin - self.shortname=hostplugin.name - self.items=[] - self.iconic_representation=None - + self.plugin = hostplugin + self.shortname = hostplugin.name + self.title = u'' + self.items = [] + self.iconic_representation = None + self.raw_slides = None + self.format_slides = [] + self.frames = [] + self.raw_footer = None + self.theme = None + log.debug(u'Service item created for %s', self.shortname) + + def addIcon(self, icon): + ButtonIcon = None + if type(icon) is QtGui.QIcon: + ButtonIcon = icon + elif type(icon) is types.StringType or type(icon) is types.UnicodeType: + ButtonIcon = QtGui.QIcon() + if icon.startswith(u':/'): + ButtonIcon.addPixmap(QtGui.QPixmap(icon), QtGui.QIcon.Normal, + QtGui.QIcon.Off) + else: + ButtonIcon.addPixmap(QtGui.QPixmap.fromImage(QtGui.QImage(icon)), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.iconic_representation = ButtonIcon + def render(self): """ The render method is what the plugin uses to render it's meda to the screen. """ - pass + log.debug(u'Render called') + if self.theme == None: + self.render_manager.set_override_theme(None) + else: + self.render_manager.set_override_theme(self.theme) + + for slide in self.raw_slides: + self.format_slides.append(self.render_manager.format_slide(slide, False)) + for slide in self.format_slides: + + self.frames.append(self.render_manager.generate_slide(slide, self.raw_footer, False)) def get_parent_node(self): """ @@ -64,7 +101,7 @@ class ServiceItem(QAbstractItemModel): """ pass - def set_from_plugin(self, data): + def set_from_plugin(self): """ Takes data from the plugin media chooser """ diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index d322e90af..628dcff1e 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -45,14 +45,14 @@ class MainDisplay(QtGui.QWidget): screen = scrn break self.setGeometry(screen['size']) + self.display.setGeometry(screen['size']) if not screen['primary']: self.showFullScreen() else: - self.hide() + self.showMinimized() def frameView(self, frame): - self.display.setGeometry(0, 0, imagesize.width(), imagesize.height()) - self.display.setPixmap(QtGui.QPixmap(frame)) + self.display.setPixmap(frame) def kill(self): pass diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index f0650dda2..386976772 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -60,8 +60,9 @@ class MainWindow(object): self.plugin_helpers[u'preview'] = self.PreviewController self.plugin_helpers[u'live'] = self.LiveController self.plugin_helpers[u'event'] = self.EventManager - self.plugin_helpers[u'theme'] = self.ThemeManagerContents # Theme manger + self.plugin_helpers[u'theme'] = self.ThemeManagerContents self.plugin_helpers[u'render'] = self.RenderManager + self.plugin_helpers[u'service'] = self.ServiceManagerContents self.plugin_manager.find_plugins(pluginpath, self.plugin_helpers, self.EventManager) # hook methods have to happen after find_plugins. Find plugins needs the controllers @@ -94,6 +95,12 @@ class MainWindow(object): self.ThemeManagerContents.serviceManager = self.ServiceManagerContents self.ThemeManagerContents.loadThemes() + # Initialise SlideControllers + log.info(u'Set Up SlideControllers') + self.PreviewController.isLive = False + self.LiveController.isLive = True + self.LiveController.mainDisplay = self.main_display + def setupUi(self): self.main_window.setObjectName(u'main_window') self.main_window.resize(1087, 847) diff --git a/openlp/core/ui/servicemanager.py b/openlp/core/ui/servicemanager.py index 15ea0c2a5..9905a91ed 100644 --- a/openlp/core/ui/servicemanager.py +++ b/openlp/core/ui/servicemanager.py @@ -46,20 +46,25 @@ class ServiceData(QAbstractItemModel): QAbstractItemModel.__init__(self) self.items=[] log.info("Starting") + def columnCount(self, parent): return 1; # always only a single column (for now) + def rowCount(self, parent): return len(self.items) + def insertRow(self, row, service_item): -# self.beginInsertRows(QModelIndex(),row,row) - log.info("insert row %d:%s"%(row,service_item)) + self.beginInsertRows(QModelIndex(),row,row) + log.info("insert row %s:%s" % (row,service_item)) self.items.insert(row, service_item) log.info("Items: %s" % self.items) -# self.endInsertRows() + self.endInsertRows() + def removeRow(self, row): self.beginRemoveRows(QModelIndex(), row,row) self.items.pop(row) self.endRemoveRows() + def addRow(self, item): self.insertRow(len(self.items), item) @@ -68,16 +73,18 @@ class ServiceData(QAbstractItemModel): def parent(self, index=QModelIndex()): return QModelIndex() # no children as yet + def data(self, index, role): """ Called by the service manager to draw us in the service window """ + log.debug(u'data %s %d', index, role) row=index.row() if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row! return QVariant() item=self.items[row] if role==Qt.DisplayRole: - retval= item.pluginname + ":" + item.shortname + retval= item.title + u':' + item.shortname elif role == Qt.DecorationRole: retval = item.iconic_representation elif role == Qt.ToolTipRole: @@ -139,6 +146,7 @@ class ServiceManager(QWidget): self.service_data=ServiceData() self.TreeView.setModel(self.service_data) self.Layout.addWidget(self.TreeView) + QtCore.QObject.connect(self.ThemeComboBox, QtCore.SIGNAL("activated(int)"), self.onThemeComboBoxSelected) @@ -159,6 +167,7 @@ class ServiceManager(QWidget): # if currently selected is of correct type, add it to it log.info("row:%d"%row) selected_item=self.service_data.item(row) + if type(selected_item) == type(item): log.info("Add to existing item") selected_item.add(item) diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 597c0a3b1..2ffbf9c01 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -17,11 +17,92 @@ 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 time import sleep + from PyQt4 import QtCore, QtGui +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +class SlideData(QAbstractListModel): + """ + Tree of items for an order of Theme. + Includes methods for reading and writing the contents to an OOS file + Root contains a list of ThemeItems + """ + global log + log=logging.getLogger(u'SlideData') + + def __init__(self): + QAbstractListModel.__init__(self) + self.items=[] + self.rowheight=50 + self.maximagewidth=self.rowheight*16/9.0; + log.info(u'Starting') + + def clearItems(self): + self.items=[] + + def columnCount(self, parent): + return 1 + + def rowCount(self, parent): + return len(self.items) + + def insertRow(self, row, frame): + self.beginInsertRows(QModelIndex(),row,row) + log.info(u'insert row %d' % row) + # create a preview image + frame1 = frame.scaled(QtCore.QSize(350,260)) + self.items.insert(row,(frame1)) + log.info(u'Items: %s' % self.items) + self.endInsertRows() + + def removeRow(self, row): + self.beginRemoveRows(QModelIndex(), row,row) + self.items.pop(row) + self.endRemoveRows() + + def addRow(self, frame): + self.insertRow(len(self.items), frame) + + def data(self, index, role): + row=index.row() + if row > len(self.items): # if the last row is selected and deleted, we then get called with an empty row! + return QVariant() +# if role==Qt.DisplayRole: +# retval= self.items[row][1] + if role == Qt.DecorationRole: + retval= self.items[row]#[0] + else: + retval= QVariant() +# log.info("Returning"+ str(retval)) + if type(retval) is not type(QVariant): + return QVariant(retval) + else: + return retval + + def __iter__(self): + for i in self.items: + yield i + + def getValue(self, index): + row = index.row() + return self.items[row] + + def getItem(self, row): + log.info(u'Get Item:%d -> %s' %(row, str(self.items))) + return self.items[row] + + def getList(self): + filelist = [item[3] for item in self.items]; + return filelist + class SlideController(QtGui.QWidget): + global log + log=logging.getLogger(u'SlideController') + def __init__(self, control_splitter): QtGui.QWidget.__init__(self) self.Pane = QtGui.QWidget(control_splitter) @@ -33,18 +114,16 @@ class SlideController(QtGui.QWidget): self.PaneLayout.setSpacing(50) self.PaneLayout.setMargin(0) - #self.VerseListView = QtGui.QListWidget(customEditDialog) - #self.VerseListView.setObjectName("VerseListView") - #self.horizontalLayout_4.addWidget(self.VerseListView) - self.Controller = QtGui.QScrollArea(self.Splitter) self.Controller.setWidgetResizable(True) - self.ControllerContents = QtGui.QWidget(self.Controller) - self.ControllerContents.setGeometry(QtCore.QRect(0, 0, 228, 536)) + self.PreviewListView = QtGui.QListView(self.Splitter) + self.PreviewListView.setAlternatingRowColors(True) + self.PreviewListData = SlideData() + self.PreviewListView.setModel(self.PreviewListData) self.Controller.setGeometry(QtCore.QRect(0, 0, 828, 536)) - self.Controller.setWidget(self.ControllerContents) + self.Controller.setWidget(self.PreviewListView) self.SlidePreview = QtGui.QLabel(self.Splitter) sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) @@ -59,9 +138,25 @@ class SlideController(QtGui.QWidget): self.SlidePreview.setScaledContents(True) self.SlidePreview.setObjectName("SlidePreview") + QtCore.QObject.connect(self.PreviewListView, + QtCore.SIGNAL("clicked(QModelIndex)"), self.onSlideSelected) + + + def onSlideSelected(self, index): + frame = self.PreviewListData.getValue(index) + self.previewFrame(frame) + def previewFrame(self, frame): self.SlidePreview.setPixmap(frame) + if self.isLive: + self.mainDisplay.frameView(frame) - imageLabel = QtGui.QLabel() - imageLabel.setPixmap(frame) - self.Controller.setWidget(imageLabel) + def addServiceItem(self, serviceitem): + self.serviceitem = serviceitem + self.serviceitem.render() + self.PreviewListData.clearItems() + for frame in self.serviceitem.frames: + self.PreviewListData.addRow(frame) + + def render(self): + pass diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 090fd50ea..7de4d32bf 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -230,7 +230,17 @@ class ThemeManager(QWidget): def getThemeData(self, themename): log.debug(u'getthemedata for theme %s', themename) xml_file = os.path.join(self.path, str(themename), str(themename) + u'.xml') - xml = fileToXML(xml_file) + try: + xml = fileToXML(xml_file) + except: + newtheme = ThemeXML() + newtheme.new_document(u'New Theme') + newtheme.add_background_solid(str(u'#000000')) + newtheme.add_font(str(QFont().family()), str(u'#FFFFFF'), str(30), u'False') + newtheme.add_font(str(QFont().family()), str(u'#FFFFFF'), str(12), u'False', u'footer') + newtheme.add_display(u'False', str(u'#FFFFFF'), u'False', str(u'#FFFFFF'), + str(0), str(0), str(0)) + xml = newtheme.extract_xml() theme = ThemeXML() theme.parse(xml) return theme diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 42a99beee..b4c24459a 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -23,7 +23,7 @@ from PyQt4 import QtCore, QtGui from openlp.core import translate from openlp.core.lib import MediaManagerItem, Receiver -from openlp.core.resources import * +from openlp.core.lib import ServiceItem from openlp.plugins.bibles.forms import BibleImportForm from openlp.plugins.bibles.lib import TextListData @@ -270,12 +270,6 @@ class BibleMediaItem(MediaManagerItem): self.bibleimportform.exec_() pass - def onBibleLiveClick(self): - pass - - def onBibleAddClick(self): - pass - def onAdvancedFromVerse(self): frm = self.AdvancedFromVerse.currentText() self.adjustComboBox(frm, self.verses, self.AdvancedToVerse) @@ -325,12 +319,33 @@ class BibleMediaItem(MediaManagerItem): if not self.search_results == None: self.displayResults(bible) + def onBibleLiveClick(self): + service_item = ServiceItem(self.parent) + service_item.addIcon( ":/media/media_verse.png") + service_item.render_manager = self.parent.render_manager + self.generateSlideData(service_item) + self.parent.live_controller.addServiceItem(service_item) + + def onBibleAddClick(self): + service_item = ServiceItem(self.parent) + service_item.addIcon( ":/media/media_verse.png") + service_item.render_manager = self.parent.render_manager + self.generateSlideData(service_item) + self.parent.service_manager.addServiceItem(service_item) + def onBiblePreviewClick(self): + service_item = ServiceItem(self.parent) + service_item.addIcon( ":/media/media_verse.png") + service_item.render_manager = self.parent.render_manager + self.generateSlideData(service_item) + self.parent.preview_controller.addServiceItem(service_item) + + def generateSlideData(self, service_item): log.debug(u'Bible Preview Button pressed') items = self.BibleListView.selectedIndexes() old_chapter = '' - main_lines=[] - footer_lines = [] + raw_slides=[] + raw_footer = [] for item in items: text = self.BibleListData.getValue(item) verse = text[:text.find("(")] @@ -351,13 +366,15 @@ class BibleMediaItem(MediaManagerItem): else: loc = self.formatVerse(old_chapter, chapter, verse, u'', u'') old_chapter = chapter - main_lines.append(loc + u' '+text) - if len(footer_lines) <= 1: - footer_lines.append(book) + raw_slides.append(loc + u' '+text) + service_item.title = book + u' ' + loc + if len(raw_footer) <= 1: + raw_footer.append(book) - self.parent.render_manager.set_override_theme(None) - frame=self.parent.render_manager.generate_slide(main_lines, footer_lines) - self.parent.preview_controller.previewFrame(frame) + service_item.theme = None + + service_item.raw_slides = raw_slides + service_item.raw_footer = raw_footer def formatVerse(self, old_chapter, chapter, verse, opening, closing): loc = opening diff --git a/openlp/plugins/custom/lib/mediaitem.py b/openlp/plugins/custom/lib/mediaitem.py index dbfe43578..3f24ac285 100644 --- a/openlp/plugins/custom/lib/mediaitem.py +++ b/openlp/plugins/custom/lib/mediaitem.py @@ -24,6 +24,7 @@ from PyQt4 import QtCore, QtGui from openlp.core import translate from openlp.core.lib import MediaManagerItem from openlp.core.lib import SongXMLParser +from openlp.core.lib import ServiceItem from openlp.plugins.custom.lib import TextListData @@ -37,6 +38,7 @@ class CustomMediaItem(MediaManagerItem): def __init__(self, parent, icon, title): MediaManagerItem.__init__(self, parent, icon, title) + self.parent = parent def setupUi(self): # Add a toolbar @@ -134,7 +136,7 @@ class CustomMediaItem(MediaManagerItem): translate('CustomMediaItem',u'&Show Live'), self.onCustomLiveClick)) self.CustomListView.addAction(self.contextMenuAction( self.CustomListView, ':/system/system_add.png', - translate('CustomMediaItem',u'&Add to Service'), self.onCustomEditClick)) + translate('CustomMediaItem',u'&Add to Service'), self.onCustomAddClick)) # def retranslateUi(self): # self.ClearTextButton.setText(translate('CustomMediaItem', u'Clear')) @@ -185,9 +187,30 @@ class CustomMediaItem(MediaManagerItem): self.CustomListData.deleteRow(index) def onCustomPreviewClick(self): + service_item = ServiceItem(self.parent) + service_item.addIcon( ":/media/media_song.png") + service_item.render_manager = self.parent.render_manager + self.generateSlideData(service_item) + self.parent.preview_controller.addServiceItem(service_item) + + def onCustomLiveClick(self): + service_item = ServiceItem(self.parent) + service_item.addIcon( ":/media/media_song.png") + service_item.render_manager = self.parent.render_manager + self.generateSlideData(service_item) + self.parent.live_controller.addServiceItem(service_item) + + def onCustomAddClick(self): + service_item = ServiceItem(self.parent) + service_item.addIcon( ":/media/media_song.png") + service_item.render_manager = self.parent.render_manager + self.generateSlideData(service_item) + self.parent.service_manager.addServiceItem(service_item) + + def generateSlideData(self, service_item): indexes = self.CustomListView.selectedIndexes() - main_lines=[] - footer_lines = [] + raw_slides =[] + raw_footer = [] slide = None theme = None for index in indexes: @@ -196,25 +219,13 @@ class CustomMediaItem(MediaManagerItem): title = customSlide.title credit = customSlide.credits theme = customSlide.theme_name - if len(theme) == 0 or theme == None: - self.parent.render_manager.set_override_theme(None) - else: - self.parent.render_manager.set_override_theme(theme) - + if len(theme) is not 0 : + service_item.theme = theme songXML=SongXMLParser(customSlide.text) verseList = songXML.get_verses() for verse in verseList: - slide = self.parent.render_manager.format_slide(verse[1], False) - print verse - print slide - - footer_lines.append(title + u' '+ credit) - if slide is not None: - frame=self.parent.render_manager.generate_slide(slide, footer_lines, False) - self.parent.preview_controller.previewFrame(frame) - - def onCustomLiveClick(self): - pass - - def onCustomAddClick(self): - pass + raw_slides.append(verse[1]) + raw_footer.append(title + u' '+ credit) + service_item.title = title + service_item.raw_slides = raw_slides + service_item.raw_footer = raw_footer