diff --git a/cnvdb.py b/cnvdb.py new file mode 100644 index 000000000..4bf4af2f8 --- /dev/null +++ b/cnvdb.py @@ -0,0 +1,23 @@ +import codecs + + +class Convert(): + def __init__(self): + pass + + def process(self, inname, outname): + infile = codecs.open(inname, 'r', encoding='iso-8859-1') + writefile = codecs.open(outname, 'w', encoding='utf-8') + count = 0 + for line in infile: + writefile.write(line) + if count < 150: + print line + count += 1 + infile.close() + writefile.close() + + +if __name__ == '__main__': + mig = Convert() + mig.process(u'/home/timali/.local/share/openlp/songs/songs.dmp',u'/home/timali/.local/share/openlp/songs/songs.dmp2') diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 96991a40e..0cbd3219b 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -75,7 +75,7 @@ from themexmlhandler import ThemeXML from renderer import Renderer from rendermanager import RenderManager from mediamanageritem import MediaManagerItem -from imagelist import ImageList +from baselistwithdnd import BaseListWithDnD from listwithpreviews import ListWithPreviews __all__ = [ 'translate', 'file_to_xml', 'str_to_bool', diff --git a/openlp/core/lib/imagelist.py b/openlp/core/lib/baselistwithdnd.py similarity index 85% rename from openlp/core/lib/imagelist.py rename to openlp/core/lib/baselistwithdnd.py index 5ddd98d55..533e17bfc 100644 --- a/openlp/core/lib/imagelist.py +++ b/openlp/core/lib/baselistwithdnd.py @@ -23,15 +23,15 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib.toolbar import * from openlp.core.lib import translate -class ImageList(QtGui.QListView): +class BaseListWithDnD(QtGui.QListView): - def __init__(self,parent=None,name=None): + def __init__(self,parent=None): QtGui.QListView.__init__(self,parent) - + assert (self.PluginName) # this must be set by the class which is inheriting def mouseMoveEvent(self, event): """ Drag and drop event does not care what data is selected - as the recepient will use events to request the data move + as the recipient will use events to request the data move just tell it what plugin to call """ if event.buttons() != QtCore.Qt.LeftButton: @@ -39,7 +39,7 @@ class ImageList(QtGui.QListView): drag = QtGui.QDrag(self) mimeData = QtCore.QMimeData() drag.setMimeData(mimeData) - mimeData.setText(u'Image') + mimeData.setText(self.PluginName) dropAction = drag.start(QtCore.Qt.CopyAction) if dropAction == QtCore.Qt.CopyAction: self.close() diff --git a/openlp/core/lib/mediamanageritem.py b/openlp/core/lib/mediamanageritem.py index 7dfb10b4f..cf5758487 100644 --- a/openlp/core/lib/mediamanageritem.py +++ b/openlp/core/lib/mediamanageritem.py @@ -112,15 +112,17 @@ class MediaManagerItem(QtGui.QWidget): ### them cmopletely in your plugin's implementation. Alternatively, call them from your ### plugin before or after you've done etra things that you need to. ### in order for them to work, you need to have setup - # self.translation_context - # self.plugin_text_short # eg "Image" for the image plugin - # self.config_section - where the items in the media manager are stored - # this could potentially be self.plugin_text_short.lower() + # self.TranslationContext + # self.PluginTextShort # eg "Image" for the image plugin + # self.ConfigSection - where the items in the media manager are stored + # this could potentially be self.PluginTextShort.lower() # - # self.on_new_prompt=u'Select Image(s)' - # self.on_new_file_masks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)' + # self.OnNewPrompt=u'Select Image(s)' + # self.OnNewFileMasks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)' # assumes that the new action is to load a file. If not, override onnew - + # self.ListViewWithDnD_class - there is a base list class with DnD assigned to it (openlp.core.lib.BaseListWithDnD()) + # each plugin needs to inherit a class from this and pass that *class* (not an instance) to here + # via the ListViewWithDnD_class member # The assumption is that given that at least two plugins are of the form # "text with an icon" then all this will help # even for plugins of another sort, the setup of the right-click menu, common toolbar @@ -137,105 +139,105 @@ class MediaManagerItem(QtGui.QWidget): # Create buttons for the toolbar ## New Song Button ## self.addToolbarButton( - translate(self.translation_context, u'Load '+self.plugin_text_short), - translate(self.translation_context, u'Load item into openlp.org'), + translate(self.TranslationContext, u'Load '+self.PluginTextShort), + translate(self.TranslationContext, u'Load item into openlp.org'), u':/images/image_load.png', self.onNewClick, u'ImageNewItem') ## Delete Song Button ## self.addToolbarButton( - translate(self.translation_context, u'Delete '+self.plugin_text_short), - translate(self.translation_context, u'Delete the selected item'), + translate(self.TranslationContext, u'Delete '+self.PluginTextShort), + translate(self.TranslationContext, u'Delete the selected item'), u':/images/image_delete.png', self.onDeleteClick, u'DeleteItem') ## Separator Line ## self.addToolbarSeparator() ## Preview Button ## self.addToolbarButton( - translate(self.translation_context, u'Preview '+self.plugin_text_short), - translate(self.translation_context, u'Preview the selected item'), + translate(self.TranslationContext, u'Preview '+self.PluginTextShort), + translate(self.TranslationContext, u'Preview the selected item'), u':/system/system_preview.png', self.onPreviewClick, u'PreviewItem') ## Live Button ## self.addToolbarButton( - translate(self.translation_context, u'Go Live'), - translate(self.translation_context, u'Send the selected item live'), + translate(self.TranslationContext, u'Go Live'), + translate(self.TranslationContext, u'Send the selected item live'), u':/system/system_live.png', self.onLiveClick, u'LiveItem') ## Add Button ## self.addToolbarButton( - translate(self.translation_context, u'Add '+self.plugin_text_short+u' To Service'), - translate(self.translation_context, u'Add the selected item(s) to the service'), - u':/system/system_add.png', self.onAddClick, self.plugin_text_short+u'AddItem') - #Add the Image List widget - self.ImageListView = ImageList() - self.ImageListView.uniformItemSizes = True - self.ImageListData = ListWithPreviews() - self.ImageListView.setModel(self.ImageListData) - self.ImageListView.setGeometry(QtCore.QRect(10, 100, 256, 591)) - self.ImageListView.setSpacing(1) - self.ImageListView.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) - self.ImageListView.setAlternatingRowColors(True) - self.ImageListView.setDragEnabled(True) - self.ImageListView.setObjectName(self.plugin_text_short+u'ListView') - self.PageLayout.addWidget(self.ImageListView) + 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') + #Add the List widget + self.ListView = self.ListViewWithDnD_class() + self.ListView.uniformItemSizes = True + self.ListData = ListWithPreviews() + self.ListView.setModel(self.ListData) + 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(self.PluginTextShort+u'ListView') + self.PageLayout.addWidget(self.ListView) #define and add the context menu - self.ImageListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) - self.ImageListView.addAction(self.contextMenuAction( - self.ImageListView, ':/system/system_preview.png', - translate(self.translation_context, u'&Preview '+self.plugin_text_short), + self.ListView.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.ListView.addAction(self.contextMenuAction( + self.ListView, ':/system/system_preview.png', + translate(self.TranslationContext, u'&Preview '+self.PluginTextShort), self.onPreviewClick)) - self.ImageListView.addAction(self.contextMenuAction( - self.ImageListView, ':/system/system_live.png', - translate(self.translation_context, u'&Show Live'), + self.ListView.addAction(self.contextMenuAction( + self.ListView, ':/system/system_live.png', + translate(self.TranslationContext, u'&Show Live'), self.onLiveClick)) - self.ImageListView.addAction(self.contextMenuAction( - self.ImageListView, ':/system/system_add.png', - translate(self.translation_context, u'&Add to Service'), + self.ListView.addAction(self.contextMenuAction( + self.ListView, ':/system/system_add.png', + translate(self.TranslationContext, u'&Add to Service'), self.onAddClick)) - QtCore.QObject.connect(self.ImageListView, + QtCore.QObject.connect(self.ListView, QtCore.SIGNAL(u'doubleClicked(QModelIndex)'), self.onPreviewClick) def initialise(self): - self.loadList(self.parent.config.load_list(self.config_section)) + self.loadList(self.parent.config.load_list(self.ConfigSection)) def onNewClick(self): files = QtGui.QFileDialog.getOpenFileNames(None, - translate(self.translation_context, self.on_new_prompt), + translate(self.TranslationContext, self.OnNewPrompt), self.parent.config.get_last_dir(), - self.on_new_file_masks) + self.OnNewFileMasks) log.info(u'New files(s)', unicode(files)) if len(files) > 0: self.loadList(files) dir, filename = os.path.split(unicode(files[0])) self.parent.config.set_last_dir(dir) - self.parent.config.set_list(self.config_section, self.ImageListData.getFileList()) + self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList()) def loadList(self, list): for file in list: - self.ImageListData.addRow(file) + self.ListData.addRow(file) def onDeleteClick(self): - indexes = self.ImageListView.selectedIndexes() + indexes = self.ListView.selectedIndexes() for index in indexes: current_row = int(index.row()) - self.ImageListData.removeRow(current_row) - self.parent.config.set_list(self.config_section, self.ImageListData.getFileList()) + self.ListData.removeRow(current_row) + self.parent.config.set_list(self.ConfigSection, self.ListData.getFileList()) def generateSlideData(self): assert (0, 'This fn needs to be defined by the plugin'); def onPreviewClick(self): - log.debug(self.plugin_text_short+u'Preview Requested') + log.debug(self.PluginTextShort+u'Preview Requested') service_item = ServiceItem(self.parent) service_item.addIcon(u':/media/media_image.png') self.generateSlideData(service_item) self.parent.preview_controller.addServiceItem(service_item) def onLiveClick(self): - log.debug(self.plugin_text_short+u' Live Requested') + log.debug(self.PluginTextShort+u' Live Requested') service_item = ServiceItem(self.parent) service_item.addIcon(u':/media/media_image.png') self.generateSlideData(service_item) self.parent.live_controller.addServiceItem(service_item) def onAddClick(self): - log.debug(self.plugin_text_short+u' Add Requested') + log.debug(self.PluginTextShort+u' Add Requested') service_item = ServiceItem(self.parent) service_item.addIcon(u':/media/media_image.png') self.generateSlideData(service_item) diff --git a/openlp/core/lib/plugin.py b/openlp/core/lib/plugin.py index 1585d27fb..e9b9a7ffd 100644 --- a/openlp/core/lib/plugin.py +++ b/openlp/core/lib/plugin.py @@ -21,6 +21,10 @@ Place, Suite 330, Boston, MA 02111-1307 USA import logging from openlp.core.lib import PluginConfig +# why does this not work??? +# from openlp.core.lib import Event, EventType +# so I have to do this??? +from event import Event, EventType class Plugin(object): """ @@ -66,6 +70,9 @@ class Plugin(object): A method used to render something to the screen, given the current theme and screen number. """ + global log + log = logging.getLogger(u'Plugin') + log.info(u'loaded') def __init__(self, name=None, version=None, plugin_helpers=None): """ @@ -95,6 +102,7 @@ class Plugin(object): self.render_manager = plugin_helpers[u'render'] self.service_manager = plugin_helpers[u'service'] self.settings= plugin_helpers[u'settings'] + self.dnd_id=None def check_pre_conditions(self): """ @@ -138,7 +146,23 @@ class Plugin(object): """ Handle the event contained in the event object. """ - pass + def handle_event(self, event): + """ + Handle the event contained in the event object. If you want + to use this default behaviour, you must set self.dnd_id equal + to that sent by the dnd source - eg the MediaItem + """ + # default behaviour - can be overridden if desired + log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload)) + if event.event_type == EventType.LoadServiceItem and event.payload == self.dnd_id: + log.debug(u'Load Service Item received') + self.media_item.onAddClick() + if event.event_type == EventType.PreviewShow and event.payload == self.dnd_id: + log.debug(u'Load Preview Item received') + self.media_item.onPreviewClick() + if event.event_type == EventType.LiveShow and event.payload == self.dnd_id: + log.debug(u'Load Live Show Item received') + self.media_item.onLiveClick() def about(self): """ diff --git a/openlp/core/lib/themexmlhandler.py b/openlp/core/lib/themexmlhandler.py index 74e150369..12880bfa6 100644 --- a/openlp/core/lib/themexmlhandler.py +++ b/openlp/core/lib/themexmlhandler.py @@ -16,8 +16,6 @@ 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 xml.dom.minidom import Document -from xml.etree.ElementTree import ElementTree, XML, dump For XML Schema see wiki.openlp.org """ @@ -256,5 +254,5 @@ class ThemeXML(): s = u'' for k in dir(self): if k[0:1] != u'_': - s += u'%30s : %s\n' %(k,getattr(self,k)) + s += u'%30s : %s\n' %(k, getattr(self, k)) return s diff --git a/openlp/core/theme/theme.py b/openlp/core/theme/theme.py index 84b1d8ae2..3c154f117 100644 --- a/openlp/core/theme/theme.py +++ b/openlp/core/theme/theme.py @@ -1,9 +1,26 @@ +# -*- 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, Carsten Tinggaard + +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 platform -ver = platform.python_version() -if ver >= '2.5': - from xml.etree.ElementTree import ElementTree, XML -else: - from elementtree import ElementTree, XML +import types +from xml.etree.ElementTree import ElementTree, XML from PyQt4 import QtGui @@ -59,7 +76,7 @@ class Theme: FontName : name of font to use FontColor : color for main font FontProportion : size of font - FontUnits : whether size of font is in or + FontUnits : whether size of font is in or Shadow : 0 - no shadow, non-zero use shadow ShadowColor : color for drop shadow @@ -78,52 +95,57 @@ class Theme: # init to defaults self._set_from_XML(blankstylexml) self._set_from_XML(xml) +# print self.__str__() def _get_as_string(self): - s="" + s = u'' keys=dir(self) keys.sort() for k in keys: - if k[0:1] != "_": - s+= "_%s_" %(getattr(self,k)) + if k[0:1] != u'_': + s += u'_%s_' %(getattr(self,k)) return s + def _set_from_XML(self, xml): - root=ElementTree(element=XML(xml)) - iter=root.getiterator() + root = ElementTree(element=XML(xml)) + iter = root.getiterator() for element in iter: - if element.tag != "Theme": - t=element.text -# print element.tag, t, type(t) - if type(t) == type(None): # easy! - val=t - if type(t) == type(u' '): # strings need special handling to sort the colours out -# print "str", - if t[0] == "$": # might be a hex number -# print "hex", + if element.tag != u'Theme': + t = element.text +# print element.tag, t, type(t) + val = 0 + # easy! + if type(t) == type(None): + val = t + # strings need special handling to sort the colours out + if type(t) is types.StringType or type(t) is types.UnicodeType: +# print u'str', + if t[0] == u'$': # might be a hex number +# print u'hex', try: - val=int(t[1:], 16) + val = int(t[1:], 16) except ValueError: # nope -# print "nope", +# print u'nope' pass elif DelphiColors.has_key(t): -# print "colour", - val=DelphiColors[t] +# print u'colour ', t + val = DelphiColors[t] else: try: - val=int(t) + val = int(t) except ValueError: - val=t + val = t if (element.tag.find(u'Color') > 0 or (element.tag.find(u'BackgroundParameter') == 0 and type(val) == type(0))): # convert to a wx.Colour val= QtGui.QColor((val>>16) & 0xFF, (val>>8)&0xFF, val&0xFF) - # print [val] - setattr(self,element.tag, val) - +# print [val] +# print u'>> ', element.tag, val + setattr(self, element.tag, val) def __str__(self): - s="" + s = u'' for k in dir(self): - if k[0:1] != "_": - s+= "%30s : %s\n" %(k,getattr(self,k)) - return s \ No newline at end of file + if k[0:1] != u'_': + s += u'%30s : %s\n' %(k, getattr(self, k)) + return s diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index d6fa68cba..ae49ab2e6 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -104,12 +104,18 @@ class SlideList(QtGui.QListView): def keyPressEvent(self, event): if type(event) == QtGui.QKeyEvent: #here accept the event and do something - if event.key() == QtCore.Qt.Key_PageUp: + if event.key() == QtCore.Qt.Key_Up: self.parent.onSlideSelectedPrevious() event.accept() - elif event.key() == QtCore.Qt.Key_PageDown: + elif event.key() == QtCore.Qt.Key_Down: self.parent.onSlideSelectedNext() event.accept() + elif event.key() == QtCore.Qt.Key_PageUp: + self.parent.onSlideSelectedFirst() + event.accept() + elif event.key() == QtCore.Qt.Key_PageDown: + self.parent.onSlideSelectedLast() + event.accept() event.ignore() else: event.ignore() @@ -225,11 +231,6 @@ class SlideController(QtGui.QWidget): QtCore.SIGNAL(u'clicked(QModelIndex)'), self.onSlideSelected) QtCore.QObject.connect(self.PreviewListView, QtCore.SIGNAL(u'activated(QModelIndex)'), self.onSlideSelected) - QtCore.QObject.connect(self.PreviewListView, - QtCore.SIGNAL(u'entered(QModelIndex)'), self.onTest) - - def onTest(self , item): - print "found", item def onSlideSelectedFirst(self): """ diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index d292f6fe5..49400f97f 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -57,9 +57,9 @@ class ThemeData(QtCore.QAbstractListModel): def insertRow(self, row, filename): self.beginInsertRows(QtCore.QModelIndex(), row, row) - log.info(u'insert row %d:%s' % (row, filename)) + log.debug(u'insert row %d:%s' % (row, filename)) (prefix, shortfilename) = os.path.split(unicode(filename)) - log.info(u'shortfilename = %s' % shortfilename) + log.debug(u'shortfilename = %s' % shortfilename) theme = shortfilename.split(u'.') # create a preview image if os.path.exists(filename): @@ -81,7 +81,7 @@ class ThemeData(QtCore.QAbstractListModel): pixmap.fill(QtCore.Qt.black) # finally create the row self.items.insert(row, (filename, pixmap, shortfilename, theme[0])) - log.info(u'Items: %s' % self.items) + log.debug(u'Items: %s' % self.items) self.endInsertRows() def removeRow(self, row): @@ -190,8 +190,13 @@ class ThemeManager(QtGui.QWidget): try: os.remove(os.path.join(self.path, th)) except: - pass #if not present do not worry - shutil.rmtree(os.path.join(self.path, theme)) + #if not present do not worry + pass + try: + shutil.rmtree(os.path.join(self.path, theme)) + except: + #if not present do not worry + pass self.themeData.clearItems() self.loadThemes() @@ -201,7 +206,7 @@ class ThemeManager(QtGui.QWidget): def onImportTheme(self): files = QtGui.QFileDialog.getOpenFileNames(None, translate(u'ThemeManager', u'Select Theme Import File'), - self.path, u'Theme (*.theme)') + self.path, u'Theme (*.*)') log.info(u'New Themes %s', unicode(files)) if len(files) > 0: for file in files: @@ -335,7 +340,7 @@ class ThemeManager(QtGui.QWidget): outfile = open(theme_file, u'w') outfile.write(theme_xml) outfile.close() - if image_from is not None and image_from is not image_to: + if image_from is not None and image_from != image_to: shutil.copyfile(image_from, image_to) self.generateAndSaveImage(self.path, name, theme_xml) self.themeData.clearItems() diff --git a/openlp/migration/display.py b/openlp/migration/display.py index 7abf54e5e..311674efb 100644 --- a/openlp/migration/display.py +++ b/openlp/migration/display.py @@ -22,14 +22,14 @@ class Display(): global log log=logging.getLogger(u'Display Logger') log.info(u'Display Class loaded') - + @staticmethod def output(string): log.debug(string); print (string) - + @staticmethod def sub_output(string): if not string == None: - log.debug(u' "+string); - print (u' "+string) \ No newline at end of file + log.debug(u' '+string); + print (u' '+string) diff --git a/openlp/migration/migratefiles.py b/openlp/migration/migratefiles.py index 665735c03..f55f08f4a 100644 --- a/openlp/migration/migratefiles.py +++ b/openlp/migration/migratefiles.py @@ -24,18 +24,18 @@ class MigrateFiles(): def process(self): self.display.output(u'Files process started'); self._initial_setup() - self.display.output(u'Files process finished'); - + self.display.output(u'Files process finished'); + def _initial_setup(self): self.display.output(u'Initial Setup started'); ConfigHelper.get_data_path() - self.display.sub_output(u'Config created'); - ConfigHelper.get_config(u'bible", u'data path') - self.display.sub_output(u'Config created'); - ConfigHelper.get_config(u'videos", u'data path') - self.display.sub_output(u'videos created'); - ConfigHelper.get_config(u'images", u'data path') - self.display.sub_output(u'images created'); - ConfigHelper.get_config(u'presentations", u'data path') - self.display.sub_output(u'presentations created'); - self.display.output(u'Initial Setup finished'); \ No newline at end of file + self.display.sub_output(u'Config created'); + ConfigHelper.get_config(u'bible', u'data path') + self.display.sub_output(u'Config created'); + ConfigHelper.get_config(u'videos', u'data path') + self.display.sub_output(u'videos created'); + ConfigHelper.get_config(u'images', u'data path') + self.display.sub_output(u'images created'); + ConfigHelper.get_config(u'presentations', u'data path') + self.display.sub_output(u'presentations created'); + self.display.output(u'Initial Setup finished'); diff --git a/openlp/migration/migratesongs.py b/openlp/migration/migratesongs.py index e5af0bc4e..2465c8b9d 100644 --- a/openlp/migration/migratesongs.py +++ b/openlp/migration/migratesongs.py @@ -16,6 +16,7 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ import os +import sys import logging import sqlite3 from openlp.core.lib import PluginConfig @@ -24,20 +25,81 @@ from sqlalchemy import * from sqlalchemy.sql import select from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker, mapper, relation, clear_mappers - +from openlp.plugins.songs.lib.models import metadata, session, \ + engine, songs_table, Song, Author, Topic, Book from openlp.plugins.songs.lib.tables import * from openlp.plugins.songs.lib.classes import * -clear_mappers() -mapper(Author, authors_table) -mapper(Book, song_books_table) -mapper(Song, songs_table, properties={ - 'authors': relation(Author, backref='songs', - secondary=authors_songs_table), - 'book': relation(Book, backref='songs'), - 'topics': relation(Topic, backref='songs', - secondary=songs_topics_table)}) -mapper(Topic, topics_table) +def init_models(url): + engine = create_engine(url) + metadata.bind = engine + session = scoped_session(sessionmaker(autoflush=True, autocommit=False, + bind=engine)) + mapper(Author, authors_table) + mapper(TAuthor, temp_authors_table) + mapper(Book, song_books_table) + mapper(Song, songs_table, + properties={'authors': relation(Author, backref='songs', + secondary=authors_songs_table), + 'book': relation(Book, backref='songs'), + 'topics': relation(Topic, backref='songs', + secondary=songs_topics_table)}) + mapper(TSong, temp_songs_table) + mapper(TSongAuthor, temp_authors_songs_table) + mapper(Topic, topics_table) + return session + +temp_authors_table = Table(u'authors_temp', metadata, + Column(u'authorid', types.Integer, primary_key=True), + Column(u'authorname', String(40)) +) + +temp_songs_table = Table(u'songs_temp', metadata, + Column(u'songid', types.Integer, primary_key=True), + Column(u'songtitle', String(60)), + Column(u'lyrics', types.UnicodeText), + Column(u'copyrightinfo', String(255)), + Column(u'settingsid', types.Integer) +) + +# Definition of the "authors_songs" table +temp_authors_songs_table = Table(u'songauthors_temp', metadata, + Column(u'authorid', types.Integer, primary_key=True), + Column(u'songid', types.Integer) +) +class BaseModel(object): + """ + BaseModel provides a base object with a set of generic functions + """ + + @classmethod + def populate(cls, **kwargs): + """ + Creates an instance of a class and populates it, returning the instance + """ + me = cls() + keys = kwargs.keys() + for key in keys: + me.__setattr__(key, kwargs[key]) + return me + +class TAuthor(BaseModel): + """ + Author model + """ + pass + +class TSong(BaseModel): + """ + Author model + """ + pass + +class TSongAuthor(BaseModel): + """ + Author model + """ + pass class MigrateSongs(): def __init__(self, display): @@ -55,186 +117,70 @@ class MigrateSongs(): def v_1_9_0(self, database): self.display.output(u'Migration 1.9.0 Started for ' + database) - self._v1_9_0_authors(database) - self._v1_9_0_topics(database) - self._v1_9_0_songbook(database) - self._v1_9_0_songauthors(database) - self._v1_9_0_songtopics(database) - self._v1_9_0_songs(database) + self._v1_9_0_old(database) + self._v1_9_0_new(database) + self._v1_9_0_cleanup(database) self.display.output(u'Migration 1.9.0 Finished for ' + database) - def _v1_9_0_authors(self, database): - self.display.sub_output(u'Authors Started for ' + database) + def _v1_9_0_old(self, database): + self.display.sub_output(u'Rename Tables ' + database) conn = sqlite3.connect(self.data_path + os.sep + database) - conn.execute(u'""alter table authors rename to authors_temp;""') + conn.execute(u'alter table authors rename to authors_temp;') conn.commit() - self.display.sub_output(u'old author renamed to author_temp') - conn.execute(u'""create table authors ( - id integer primary key ASC AUTOINCREMENT, - first_name varchar(128), - last_name varchar(128), - display_name varchar(255) - );""') + conn.execute(u'alter table songs rename to songs_temp;') conn.commit() - self.display.sub_output(u'authors table created') - conn.execute(u'""create index if not exists author1 on authors - (display_name ASC,id ASC);""') + conn.execute(u'alter table songauthors rename to songauthors_temp;') conn.commit() - self.display.sub_output(u'index author1 created') - conn.execute(u'""create index if not exists author2 on authors - (last_name ASC,id ASC);""') - conn.commit() - self.display.sub_output(u'index author2 created') - conn.execute(u'""create index if not exists author3 on authors - (first_name ASC,id ASC);""') - conn.commit() - self.display.sub_output(u'index author3 created') - self.display.sub_output(u'Author Data Migration started') - conn.execute(u'""insert into authors (id, display_name) - select authorid, authorname from authors_temp;""') - conn.commit() - self.display.sub_output(u'authors populated') - c = conn.cursor() - text = c.execute(u'""select * from authors""') .fetchall() - for author in text: - dispname = author[3] - dispname = dispname.replace(u''", u'') - pos = dispname.rfind(u' ') - authorfirstname = dispname[:pos] - authorlastname = dispname[pos + 1:len(dispname)] - s = "update authors set first_name = '" \ - + authorfirstname + "', last_name = '" + authorlastname \ - + "' where id = " + unicode(author[0]) - c.execute(s) - conn.commit() - self.display.sub_output(u'Author Data Migration Completed') - conn.execute(u'""drop table authors_temp;""') - conn.commit() - conn.close() - self.display.sub_output(u'author_temp dropped') - self.display.sub_output(u'Authors Completed') - def _v1_9_0_songbook(self, database): - self.display.sub_output(u'SongBook Started for ' + database) - conn = sqlite3.connect(self.data_path + os.sep + database) - conn.execute(u'""create table if not exists song_books ( - id integer Primary Key ASC AUTOINCREMENT, - name varchar(128), - publisher varchar(128) - );""') - conn.commit() - self.display.sub_output(u'songbook table created') - conn.execute(u'""create index if not exists songbook1 on song_books (name ASC,id ASC);""') - conn.commit() - self.display.sub_output(u'index songbook1 created') - conn.execute(u'""create index if not exists songbook2 on song_books (publisher ASC,id ASC);""') - conn.commit() - conn.close() - self.display.sub_output(u'index songbook2 created') - self.display.sub_output(u'SongBook Completed') + def _v1_9_0_new(self, database): + self.display.sub_output(u'Create new Tables ' + database) + self.db_url = u'sqlite:///' + self.data_path + u'/songs.sqlite' + print self.db_url + self.session = init_models(self.db_url) + if not songs_table.exists(): + metadata.create_all() + results = self.session.query(TSong).order_by(TSong.songid).all() + for songs_temp in results: + song = Song() + song.title = songs_temp.songtitle + song.lyrics = songs_temp.lyrics.replace(u'\r\n', u'\n') + song.copyright = songs_temp.copyrightinfo + song.search_title = u'' + song.search_lyrics = u'' + print songs_temp.songtitle + aa = self.session.execute(u'select * from songauthors_temp where songid =' + unicode(songs_temp.songid) ) + for row in aa: + a = row['authorid'] + author = Author() + authors_temp = self.session.query(TAuthor).get(a) + author.display_name = authors_temp.authorname + song.authors.append(author) + try: + self.session.add(song) + self.session.commit() + except: + self.session.rollback() + print u'Errow thrown = ', sys.exc_info()[1] - def _v1_9_0_songs(self, database): - self.display.sub_output(u'Songs Started for ' + database) + def _v1_9_0_cleanup(self, database): + self.display.sub_output(u'Update Internal Data ' + database) conn = sqlite3.connect(self.data_path + os.sep + database) - conn.execute(u'""alter table songs rename to songs_temp;""') - conn.commit() - conn.execute(u'""create table if not exists songs ( - id integer Primary Key ASC AUTOINCREMENT, - song_book_id integer, - title varchar(255), - lyrics text, - verse_order varchar(128), - copyright varchar(255), - comments text, - ccli_number varchar(64), - song_number varchar(64), - theme_name varchar(128), - search_title varchar(255), - search_lyrics text - );""') - conn.commit() - self.display.sub_output(u'songs table created') - conn.execute(u'""create index if not exists songs1 on songs - (search_lyrics ASC,id ASC);""') - conn.commit() - self.display.sub_output(u'index songs1 created') - conn.execute(u'""create index if not exists songs2 on songs - (search_title ASC,id ASC);""') - conn.commit() - self.display.sub_output(u'index songs2 created') - conn.execute(u'""insert into songs (id, title, lyrics, copyright, - search_title, search_lyrics, song_book_id) - select songid, songtitle, lyrics, copyrightinfo, + conn.execute("""update songs set search_title = replace(replace(replace(replace(replace(replace(replace(replace( - replace(songtitle, '&', 'and'), ',', ''), ';', ''), ':', ''), - '(u', ''), ')', ''), '{', ''), '}',''),'?',''), + replace(title, '&', 'and'), ',', ''), ';', ''), ':', ''), + '(u', ''), ')', ''), '{', ''), '}',''),'?','');""") + conn.execute("""update songs set search_lyrics = replace(replace(replace(replace(replace(replace(replace(replace( replace(lyrics, '&', 'and'), ',', ''), ';', ''), ':', ''), - '(u', ''), ')', ''), '{', ''), '}',''),'?',''), - 0 - from songs_temp;""') + '(u', ''), ')', ''), '{', ''), '}',''),'?','') + ;""") conn.commit() - self.display.sub_output(u'songs populated') - conn.execute(u'""drop table songs_temp;""') + conn.execute(u'drop table authors_temp;') conn.commit() - conn.close() - self.display.sub_output(u'songs_temp dropped') - self.display.sub_output(u'Songs Completed') + conn.execute(u'drop table songs_temp;') + conn.commit() + conn.execute(u'drop table songauthors_temp;') + conn.commit() + conn.execute(u'drop table settings;') - def _v1_9_0_topics(self, database): - self.display.sub_output(u'Topics Started for ' + database) - conn = sqlite3.connect(self.data_path+os.sep+database) - conn.text_factory = str - conn.execute(u'""create table if not exists topics - (id integer Primary Key ASC AUTOINCREMENT, - name varchar(128));""') conn.commit() - self.display.sub_output(u'Topic table created') - conn.execute(u'""create index if not exists topic1 on topics (name ASC,id ASC);""') - conn.commit() - conn.close() - self.display.sub_output(u'index topic1 created') - - self.display.sub_output(u'Topics Completed') - - def _v1_9_0_songauthors(self, database): - self.display.sub_output(u'SongAuthors Started for ' + database); - conn = sqlite3.connect(self.data_path + os.sep + database) - conn.execute(u'""create table if not exists authors_songs - (author_id integer, - song_id integer);""') - conn.commit() - self.display.sub_output(u'authors_songs table created') - conn.execute(u'""insert into authors_songs (author_id, song_id) - select authorid, songid from songauthors;""') - conn.commit() - self.display.sub_output(u'authors_songs populated') - conn.execute(u'""drop table songauthors;""') - conn.commit() - self.display.sub_output(u'songauthors dropped') - conn.close() - self.display.sub_output(u'SongAuthors Completed') - - def _v1_9_0_songtopics(self, database): - self.display.sub_output(u'Songtopics Started for ' + database); - conn = sqlite3.connect(self.data_path+os.sep+database) - conn.execute(u'""create table if not exists song_topics - (song_id integer, - topic_id integer);""') - conn.commit() - self.display.sub_output(u'songtopics table created') - conn.execute(u'""create index if not exists songtopic1 on song_topics (topic_id ASC,song_id ASC);""') - conn.commit() - self.display.sub_output(u'index songtopic1 created') - conn.execute(u'""create index if not exists songtopic2 on song_topics (song_id ASC,topic_id ASC);""') - conn.commit() - conn.close() - self.display.sub_output(u'index songtopic2 created') - self.display.sub_output(u'SongTopics Completed') - - def run_cmd(self, cmd): - filein, fileout = os.popen4(cmd) - out = fileout.readlines() - if len(out) > 0: - for o in range (0, len(out)): - self.display.sub_output(out[o]) \ No newline at end of file diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index fe0f02156..b1f868a5c 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -45,7 +45,6 @@ class BibleList(QtGui.QListWidget): if dropAction == QtCore.Qt.CopyAction: self.close() - class BibleMediaItem(MediaManagerItem): """ This is the custom media manager item for Bibles. diff --git a/openlp/plugins/images/imageplugin.py b/openlp/plugins/images/imageplugin.py index e7fde7eea..a9371524a 100644 --- a/openlp/plugins/images/imageplugin.py +++ b/openlp/plugins/images/imageplugin.py @@ -37,6 +37,7 @@ class ImagePlugin(Plugin): self.icon = QtGui.QIcon() self.icon.addPixmap(QtGui.QPixmap(u':/media/media_image.png'), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.dnd_id = u'Image' # passed with drag and drop messages def get_media_manager_item(self): # Create the MediaManagerItem object @@ -46,17 +47,3 @@ class ImagePlugin(Plugin): def initialise(self): log.info(u'Plugin Initialising') - def handle_event(self, event): - """ - Handle the event contained in the event object. - """ - log.debug(u'Handle event called with event %s with payload %s'%(event.event_type, event.payload)) - if event.event_type == EventType.LoadServiceItem and event.payload == 'Image': - log.debug(u'Load Service Item received') - self.media_item.onImageAddClick() - if event.event_type == EventType.PreviewShow and event.payload == 'Image': - log.debug(u'Load Preview Item received') - self.media_item.onImagePreviewClick() - if event.event_type == EventType.LiveShow and event.payload == 'Image': - log.debug(u'Load Live Show Item received') - self.media_item.onImageLiveClick() diff --git a/openlp/plugins/images/lib/mediaitem.py b/openlp/plugins/images/lib/mediaitem.py index 90524575f..ed6f3bd1a 100644 --- a/openlp/plugins/images/lib/mediaitem.py +++ b/openlp/plugins/images/lib/mediaitem.py @@ -24,8 +24,15 @@ from PyQt4 import QtCore, QtGui # from openlp.plugins.images.lib import ListWithPreviews from listwithpreviews import ListWithPreviews -from openlp.core.lib import MediaManagerItem, ServiceItem, translate +from openlp.core.lib import MediaManagerItem, ServiceItem, translate, BaseListWithDnD +# We have to explicitly create separate classes for each plugin +# in order for DnD to the Service manager to work correctly. +class ImageListView(BaseListWithDnD): + def __init__(self, parent=None): + self.PluginName = u'Image' + BaseListWithDnD.__init__(self, parent) + class ImageMediaItem(MediaManagerItem): """ This is the custom media manager item for images. @@ -35,19 +42,22 @@ class ImageMediaItem(MediaManagerItem): log.info(u'Image Media Item loaded') def __init__(self, parent, icon, title): - self.translation_context = u'ImagePlugin' - self.plugin_text_short =u'Image' - self.config_section=u'images' - self.on_new_prompt=u'Select Image(s)' - self.on_new_file_masks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)' + self.TranslationContext = u'ImagePlugin' + self.PluginTextShort =u'Image' + self.ConfigSection=u'images' + self.OnNewPrompt=u'Select Image(s)' + self.OnNewFileMasks=u'Images (*.jpg *jpeg *.gif *.png *.bmp)' + # this next is a class, not an instance of a class - it will + # be instanced by the base MediaManagerItem + self.ListViewWithDnD_class=ImageListView MediaManagerItem.__init__(self, parent, icon, title) def generateSlideData(self, service_item): - indexes = self.ImageListView.selectedIndexes() + indexes = self.ListView.selectedIndexes() service_item.title = u'Image(s)' for index in indexes: - filename = self.ImageListData.getFilename(index) + filename = self.ListData.getFilename(index) frame = QtGui.QImage(unicode(filename)) (path, name) = os.path.split(filename) service_item.add_from_image(path, name, frame) diff --git a/openlp/plugins/presentations/lib/impresscom.py b/openlp/plugins/presentations/lib/impresscom.py index a2a7ade6c..d522ae1d0 100644 --- a/openlp/plugins/presentations/lib/impresscom.py +++ b/openlp/plugins/presentations/lib/impresscom.py @@ -1,4 +1,4 @@ -from win32com.client import Dispatch +#from win32com.client import Dispatch # OOo API documentation: # http://api.openoffice.org/docs/common/ref/com/sun/star/presentation/XSlideShowController.html @@ -33,26 +33,26 @@ class ImpressCOMApp(object): self._app.Terminate() self._app = None self._sm = None - + 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.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() @@ -63,7 +63,7 @@ class ImpressCOMPres(object): def isActive(self): return self.pres.isRunning() and self.pres.isActive() - + def resume(self): return self.pres.resume() @@ -72,7 +72,7 @@ class ImpressCOMPres(object): def blankScreen(self): self.pres.blankScreen(0) - + def stop(self): self.pres.deactivate() # self.presdoc.end() @@ -83,7 +83,7 @@ class ImpressCOMPres(object): def getSlideNumber(self): return self.pres.getCurrentSlideIndex - + def setSlideNumber(self, slideno): self.pres.gotoSlideIndex(slideno) @@ -112,7 +112,7 @@ class ImpressCOMSlide(object): if __name__ == '__main__': ooo = ImpressCOMApp() - show = ImpressCOMPres(ooo, "c:/test1.ppt') + show = ImpressCOMPres(ooo, u'c:/test1.ppt') show.go() show.resume() - show.nextStep() \ No newline at end of file + show.nextStep() diff --git a/openlp/plugins/songs/forms/topicsform.py b/openlp/plugins/songs/forms/topicsform.py index d5aaafe9d..d18547638 100644 --- a/openlp/plugins/songs/forms/topicsform.py +++ b/openlp/plugins/songs/forms/topicsform.py @@ -51,7 +51,8 @@ class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): Refresh the screen and rest fields """ self.TopicsListWidget.clear() - self.onClearButtonClick() # tidy up screen + # tidy up screen + self.onClearButtonClick() topics = self.songmanager.get_topics() for topic in topics: topic_name = QtGui.QListWidgetItem(topic.name) @@ -77,12 +78,13 @@ class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): """ Sent New or update details to the database """ - if self.topic == None: - self.topic = Topic() - self.topic.name = unicode(self.TopicNameEdit.displayText()) - self.songmanager.save_topic(self.topic) - self.onClearButtonClick() - self.load_form() + if self._validate_form(): + if self.topic == None: + self.topic = Topic() + self.topic.name = unicode(self.TopicNameEdit.displayText()) + self.songmanager.save_topic(self.topic) + self.onClearButtonClick() + self.load_form() def onClearButtonClick(self): """ @@ -91,7 +93,6 @@ class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): self.TopicNameEdit.setText(u'') self.MessageLabel.setText(u'') self.DeleteButton.setEnabled(False) - self.AddUpdateButton.setEnabled(True) self.topic = None self._validate_form() @@ -115,7 +116,10 @@ class TopicsForm(QtGui.QDialog, Ui_TopicsDialog): def _validate_form(self): # We need at lease a display name + valid = True if len(self.TopicNameEdit.displayText()) == 0: - self.AddUpdateButton.setEnabled(False) + valid = False + self.TopicNameEdit.setStyleSheet(u'background-color: red; color: white') else: - self.AddUpdateButton.setEnabled(True) + self.TopicNameEdit.setStyleSheet(u'') + return valid diff --git a/openlp/plugins/songs/lib/tables.py b/openlp/plugins/songs/lib/tables.py index 59605a4b7..617c53b7d 100644 --- a/openlp/plugins/songs/lib/tables.py +++ b/openlp/plugins/songs/lib/tables.py @@ -16,7 +16,7 @@ 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 sqlalchemy import * from sqlalchemy import Column, Table, ForeignKey, types from openlp.plugins.songs.lib.meta import metadata @@ -68,4 +68,13 @@ authors_songs_table = Table(u'authors_songs', metadata, songs_topics_table = Table(u'songs_topics', metadata, Column(u'song_id', types.Integer, ForeignKey(u'songs.id'), primary_key=True), Column(u'topic_id', types.Integer, ForeignKey(u'topics.id'), primary_key=True) -) \ No newline at end of file +) +Index(u'authors_id',authors_table.c.id) +Index(u'authors_display_name_id',authors_table.c.display_name, authors_table.c.id) +Index(u'song_books_id',song_books_table.c.id) +Index(u'songs_id',songs_table.c.id) +Index(u'topics_id',topics_table.c.id) +Index(u'authors_songs_author',authors_songs_table.c.author_id, authors_songs_table.c.song_id) +Index(u'authors_songs_song',authors_songs_table.c.song_id, authors_songs_table.c.author_id) +Index(u'topics_song_topic', songs_topics_table.c.topic_id, songs_topics_table.c.song_id) +Index(u'topics_song_song',songs_topics_table.c.song_id, songs_topics_table.c.topic_id) diff --git a/openlp/plugins/songs/songsplugin.py b/openlp/plugins/songs/songsplugin.py index eb3d2588f..f18f85e0d 100644 --- a/openlp/plugins/songs/songsplugin.py +++ b/openlp/plugins/songs/songsplugin.py @@ -136,4 +136,4 @@ class SongsPlugin(Plugin): self.media_item.onSongLiveClick() if event.event_type == EventType.LoadSongList : log.debug(u'Load Load Song List Item received') - self.media_item.displayResults(self.songmanager.get_songs()) + self.media_item.displayResultsSong(self.songmanager.get_songs()) diff --git a/openlpcnv.pyw b/openlpcnv.pyw index 0b011b83c..333b4281e 100755 --- a/openlpcnv.pyw +++ b/openlpcnv.pyw @@ -1,6 +1,6 @@ #!/usr/bin/env python -import os +import os import sys import logging import time @@ -21,25 +21,25 @@ class Migration(): def __init__(self): """ """ - self.display = Display() - self.stime = time.strftime(u'%Y-%m-%d-%H%M%S", time.localtime()) - self.display.output(u'OpenLp v1.9.0 Migration Utility Started" ) - + self.display = Display() + self.stime = time.strftime(u'%Y-%m-%d-%H%M%S', time.localtime()) + self.display.output(u'OpenLp v1.9.0 Migration Utility Started') + def process(self): - MigrateFiles(self.display).process() + #MigrateFiles(self.display).process() MigrateSongs(self.display).process() - MigrateBibles(self.display).process() - + #MigrateBibles(self.display).process() + def move_log_file(self): fname = 'openlp-migration.log' c = os.path.splitext(fname) b = (c[0]+'-'+ unicode(self.stime) + c[1]) - self.display.output(u'Logfile " +b + " generated') + self.display.output(u'Logfile " +b + " generated') self.display.output(u'Migration Utility Finished ') - os.rename(fname, b) + os.rename(fname, b) + - if __name__ == '__main__': mig = Migration() mig.process() - #mig.move_log_file() \ No newline at end of file + #mig.move_log_file()