← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~meths/openlp/testing into lp:openlp

 

Jon Tibble has proposed merging lp:~meths/openlp/testing into lp:openlp.

Requested reviews:
  Tim Bentley (trb143)


Database refactor and importing including SONG DATABASE FLAG DAY

* Add alternate_title field and audio_files table to song database
* Add OpenLP v2 song database importer
* Refactor database query methods
  * Merge get_all_objects_filtered in to get_all_objects
  * Add filter to delete_all_objects
* Remove another now redundant manager.py
* Import, whitespace and unused variable cleanups
* Fix song book edit form ampersands
* Fix songimport comments field
-- 
https://code.launchpad.net/~meths/openlp/testing/+merge/30395
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/db.py'
--- openlp/core/lib/db.py	2010-07-05 11:39:48 +0000
+++ openlp/core/lib/db.py	2010-07-20 12:45:57 +0000
@@ -178,36 +178,24 @@
         """
         return self.session.query(object_class).filter(filter_clause).first()
 
-    def get_all_objects(self, object_class, order_by_ref=None):
+    def get_all_objects(self, object_class, filter_clause=None,
+        order_by_ref=None):
         """
         Returns all the objects from the database
 
         ``object_class``
             The type of objects to return
 
+        ``filter_clause``
+            The filter governing selection of objects to return.  Defaults to
+            None.
+
         ``order_by_ref``
             Any parameters to order the returned objects by.  Defaults to None.
         """
         query = self.session.query(object_class)
-        if order_by_ref is not None:
-            return query.order_by(order_by_ref).all()
-        return query.all()
-
-    def get_all_objects_filtered(self, object_class, filter_clause,
-        order_by_ref=None):
-        """
-        Returns a selection of objects from the database
-
-        ``object_class``
-            The type of objects to return
-
-        ``filter_clause``
-            The filter governing selection of objects to return
-
-        ``order_by_ref``
-            Any parameters to order the returned objects by.  Defaults to None.
-        """
-        query = self.session.query(object_class).filter(filter_clause)
+        if filter_clause:
+            query = query.filter(filter_clause)
         if order_by_ref is not None:
             return query.order_by(order_by_ref).all()
         return query.all()
@@ -235,7 +223,7 @@
         else:
             return True
 
-    def delete_all_objects(self, object_class):
+    def delete_all_objects(self, object_class, filter_clause=None):
         """
         Delete all object records
 
@@ -243,11 +231,13 @@
             The type of object to delete
         """
         try:
-            self.session.query(object_class).delete(synchronize_session=False)
+            query = self.session.query(object_class)
+            if filter_clause:
+                query = query.filter(filter_clause)
+            query.delete(synchronize_session=False)
             self.session.commit()
             return True
         except InvalidRequestError:
             self.session.rollback()
-            log.exception(u'Failed to delete all %s records',
-                object_class.__name__)
+            log.exception(u'Failed to delete %s records', object_class.__name__)
             return False

=== modified file 'openlp/plugins/alerts/forms/alertform.py'
--- openlp/plugins/alerts/forms/alertform.py	2010-07-06 15:26:52 +0000
+++ openlp/plugins/alerts/forms/alertform.py	2010-07-20 12:45:57 +0000
@@ -62,7 +62,8 @@
 
     def loadList(self):
         self.AlertListWidget.clear()
-        alerts = self.manager.get_all_objects(AlertItem, AlertItem.text)
+        alerts = self.manager.get_all_objects(AlertItem,
+            order_by_ref=AlertItem.text)
         for alert in alerts:
             item_name = QtGui.QListWidgetItem(alert.text)
             item_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(alert.id))

=== modified file 'openlp/plugins/bibles/lib/manager.py'
--- openlp/plugins/bibles/lib/manager.py	2010-06-15 00:44:06 +0000
+++ openlp/plugins/bibles/lib/manager.py	2010-07-20 12:45:57 +0000
@@ -198,7 +198,8 @@
                 u'name': book.name,
                 u'chapters': self.db_cache[bible].get_chapter_count(book.name)
             }
-            for book in self.db_cache[bible].get_all_objects(Book, Book.id)
+            for book in self.db_cache[bible].get_all_objects(Book,
+                order_by_ref=Book.id)
         ]
 
     def get_chapter_count(self, bible, book):

=== modified file 'openlp/plugins/bibles/lib/mediaitem.py'
--- openlp/plugins/bibles/lib/mediaitem.py	2010-07-16 09:09:11 +0000
+++ openlp/plugins/bibles/lib/mediaitem.py	2010-07-20 12:45:57 +0000
@@ -508,14 +508,14 @@
             reference = bitem.data(QtCore.Qt.UserRole)
             if isinstance(reference, QtCore.QVariant):
                 reference = reference.toPyObject()
-            bible = self._decodeQtObject(reference, 'bible')
+            #bible = self._decodeQtObject(reference, 'bible')
             book = self._decodeQtObject(reference, 'book')
             chapter = self._decodeQtObject(reference, 'chapter')
             verse = self._decodeQtObject(reference, 'verse')
             text = self._decodeQtObject(reference, 'text')
             version = self._decodeQtObject(reference, 'version')
             copyright = self._decodeQtObject(reference, 'copyright')
-            permission = self._decodeQtObject(reference, 'permission')
+            #permission = self._decodeQtObject(reference, 'permission')
             if self.parent.settings_tab.display_style == 1:
                 verse_text = self.formatVerse(old_chapter, chapter, verse,
                     u'(u', u')')

=== modified file 'openlp/plugins/custom/customplugin.py'
--- openlp/plugins/custom/customplugin.py	2010-07-12 21:11:00 +0000
+++ openlp/plugins/custom/customplugin.py	2010-07-20 12:45:57 +0000
@@ -75,7 +75,7 @@
 
         Returns True if the theme is being used, otherwise returns False.
         """
-        if self.custommanager.get_all_objects_filtered(CustomSlide,
+        if self.custommanager.get_all_objects(CustomSlide,
             CustomSlide.theme_name == theme):
             return True
         return False
@@ -91,8 +91,8 @@
         ``newTheme``
             The new name the plugin should now use.
         """
-        customsUsingTheme = self.custommanager.get_all_objects_filtered(
-            CustomSlide, CustomSlide.theme_name == oldTheme)
+        customsUsingTheme = self.custommanager.get_all_objects(CustomSlide,
+            CustomSlide.theme_name == oldTheme)
         for custom in customsUsingTheme:
             custom.theme_name = newTheme
             self.custommanager.save_object(custom)

=== modified file 'openlp/plugins/custom/lib/mediaitem.py'
--- openlp/plugins/custom/lib/mediaitem.py	2010-07-08 09:14:00 +0000
+++ openlp/plugins/custom/lib/mediaitem.py	2010-07-20 12:45:57 +0000
@@ -73,7 +73,7 @@
 
     def initialise(self):
         self.loadCustomListView(self.parent.custommanager.get_all_objects(
-            CustomSlide, CustomSlide.title))
+            CustomSlide, order_by_ref=CustomSlide.title))
         #Called to redisplay the song list screen edith from a search
         #or from the exit of the Song edit dialog.  If remote editing is active
         #Trigger it and clean up so it will not update again.

=== modified file 'openlp/plugins/songs/forms/editsongform.py'
--- openlp/plugins/songs/forms/editsongform.py	2010-07-20 11:02:03 +0000
+++ openlp/plugins/songs/forms/editsongform.py	2010-07-20 12:45:57 +0000
@@ -118,7 +118,8 @@
         self.TopicRemoveButton.setEnabled(False)
 
     def loadAuthors(self):
-        authors = self.songmanager.get_all_objects(Author, Author.display_name)
+        authors = self.songmanager.get_all_objects(Author,
+            order_by_ref=Author.display_name)
         self.AuthorsSelectionComboItem.clear()
         self.AuthorsSelectionComboItem.addItem(u'')
         for author in authors:
@@ -128,7 +129,8 @@
                 row, QtCore.QVariant(author.id))
 
     def loadTopics(self):
-        topics = self.songmanager.get_all_objects(Topic, Topic.name)
+        topics = self.songmanager.get_all_objects(Topic,
+            order_by_ref=Topic.name)
         self.SongTopicCombo.clear()
         self.SongTopicCombo.addItem(u'')
         for topic in topics:
@@ -137,7 +139,7 @@
             self.SongTopicCombo.setItemData(row, QtCore.QVariant(topic.id))
 
     def loadBooks(self):
-        books = self.songmanager.get_all_objects(Book, Book.name)
+        books = self.songmanager.get_all_objects(Book, order_by_ref=Book.name)
         self.SongbookCombo.clear()
         self.SongbookCombo.addItem(u'')
         for book in books:
@@ -180,7 +182,10 @@
         self.loadBooks()
         self.song = self.songmanager.get_object(Song, id)
         self.TitleEditItem.setText(self.song.title)
-        title = self.song.search_title.split(u'@')
+        if self.song.alternate_title:
+            self.AlternativeEdit.setText(self.song.alternate_title)
+        else:
+            self.AlternativeEdit.setText(u'')
         if self.song.song_book_id != 0:
             book_name = self.songmanager.get_object(Book,
                 self.song.song_book_id)
@@ -198,8 +203,6 @@
                 id = 0
                 self.song.theme_name = None
             self.ThemeSelectionComboItem.setCurrentIndex(id)
-        if len(title) > 1:
-            self.AlternativeEdit.setText(title[1])
         if self.song.copyright:
             self.CopyrightEditItem.setText(self.song.copyright)
         else:
@@ -621,6 +624,7 @@
 
     def saveSong(self):
         self.song.title = unicode(self.TitleEditItem.text())
+        self.song.alternate_title = unicode(self.AlternativeEdit.text())
         self.song.copyright = unicode(self.CopyrightEditItem.text())
         self.song.search_title = self.song.title + u'@' + \
             unicode(self.AlternativeEdit.text())

=== modified file 'openlp/plugins/songs/forms/songbookdialog.py'
--- openlp/plugins/songs/forms/songbookdialog.py	2010-07-17 16:03:59 +0000
+++ openlp/plugins/songs/forms/songbookdialog.py	2010-07-20 12:45:57 +0000
@@ -41,6 +41,7 @@
             QtGui.QFormLayout.LabelRole, self.NameLabel)
         self.NameEdit = QtGui.QLineEdit(SongBookDialog)
         self.NameEdit.setObjectName(u'NameEdit')
+        self.NameLabel.setBuddy(self.NameEdit)
         self.SongBookLayout.setWidget(0,
             QtGui.QFormLayout.FieldRole, self.NameEdit)
         self.PublisherLabel = QtGui.QLabel(SongBookDialog)
@@ -49,6 +50,7 @@
             QtGui.QFormLayout.LabelRole, self.PublisherLabel)
         self.PublisherEdit = QtGui.QLineEdit(SongBookDialog)
         self.PublisherEdit.setObjectName(u'PublisherEdit')
+        self.PublisherLabel.setBuddy(self.PublisherEdit)
         self.SongBookLayout.setWidget(1,
             QtGui.QFormLayout.FieldRole, self.PublisherEdit)
         self.ButtonBox = QtGui.QDialogButtonBox(SongBookDialog)

=== modified file 'openlp/plugins/songs/forms/songmaintenanceform.py'
--- openlp/plugins/songs/forms/songmaintenanceform.py	2010-07-19 15:03:49 +0000
+++ openlp/plugins/songs/forms/songmaintenanceform.py	2010-07-20 12:45:57 +0000
@@ -102,7 +102,8 @@
         Reloads the Authors list.
         """
         self.AuthorsListWidget.clear()
-        authors = self.songmanager.get_all_objects(Author, Author.display_name)
+        authors = self.songmanager.get_all_objects(Author,
+            order_by_ref=Author.display_name)
         for author in authors:
             if author.display_name:
                 author_name = QtGui.QListWidgetItem(author.display_name)
@@ -117,7 +118,8 @@
         Reloads the Topics list.
         """
         self.TopicsListWidget.clear()
-        topics = self.songmanager.get_all_objects(Topic, Topic.name)
+        topics = self.songmanager.get_all_objects(Topic,
+            order_by_ref=Topic.name)
         for topic in topics:
             topic_name = QtGui.QListWidgetItem(topic.name)
             topic_name.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
@@ -128,7 +130,7 @@
         Reloads the Books list.
         """
         self.BooksListWidget.clear()
-        books = self.songmanager.get_all_objects(Book, Book.name)
+        books = self.songmanager.get_all_objects(Book, order_by_ref=Book.name)
         for book in books:
             book_name = QtGui.QListWidgetItem(u'%s (%s)' % (book.name,
                 book.publisher))
@@ -140,7 +142,7 @@
         Returns False if the given Author is already in the list otherwise
         True.
         """
-        authors = self.songmanager.get_all_objects_filtered(Author,
+        authors = self.songmanager.get_all_objects(Author,
             and_(Author.first_name == new_author.first_name,
                 Author.last_name == new_author.last_name,
                 Author.display_name == new_author.display_name))
@@ -162,7 +164,7 @@
         """
         Returns False if the given Topic is already in the list otherwise True.
         """
-        topics = self.songmanager.get_all_objects_filtered(Topic,
+        topics = self.songmanager.get_all_objects(Topic,
             Topic.name == new_topic.name)
         if len(topics) > 0:
             # If we edit an existing Topic, we need to make sure that we do
@@ -182,7 +184,7 @@
         """
         Returns False if the given Book is already in the list otherwise True.
         """
-        books = self.songmanager.get_all_objects_filtered(Book,
+        books = self.songmanager.get_all_objects(Book,
             and_(Book.name == new_book.name,
                 Book.publisher == new_book.publisher))
         if len(books) > 0:
@@ -392,7 +394,7 @@
             and_(Author.first_name == old_author.first_name,
                 Author.last_name == old_author.last_name, 
                 Author.display_name == old_author.display_name))
-        songs = self.songmanager.get_all_objects_filtered(Song,
+        songs = self.songmanager.get_all_objects(Song,
             Song.authors.contains(old_author))
         for song in songs:
             # We check if the song has already existing_author as author. If
@@ -412,7 +414,7 @@
         '''
         existing_topic = self.songmanager.get_object_filtered(Topic,
             Topic.name == old_topic.name)
-        songs = self.songmanager.get_all_objects_filtered(Song,
+        songs = self.songmanager.get_all_objects(Song,
             Song.topics.contains(old_topic))
         for song in songs:
             # We check if the song has already existing_topic as topic. If that
@@ -433,7 +435,7 @@
         existing_book = self.songmanager.get_object_filtered(Book,
             and_(Book.name == old_book.name,
                 Book.publisher == old_book.publisher))
-        songs = self.songmanager.get_all_objects_filtered(Song,
+        songs = self.songmanager.get_all_objects(Song,
             Song.song_book_id == old_book.id)
         for song in songs:
             song.song_book_id = existing_book.id

=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py	2010-07-19 19:35:33 +0000
+++ openlp/plugins/songs/lib/__init__.py	2010-07-20 12:45:57 +0000
@@ -142,6 +142,7 @@
 from mediaitem import SongMediaItem
 from songimport import SongImport
 from opensongimport import OpenSongImport
+from olpimport import OpenLPSongImport
 try:
     from sofimport import SofImport
     from oooimport import OooImport

=== modified file 'openlp/plugins/songs/lib/db.py'
--- openlp/plugins/songs/lib/db.py	2010-07-19 07:54:22 +0000
+++ openlp/plugins/songs/lib/db.py	2010-07-20 12:45:57 +0000
@@ -46,6 +46,12 @@
         return u'<Book id="%s" name="%s" publisher="%s" />' % (
             str(self.id), self.name, self.publisher)
 
+class MediaFile(BaseModel):
+    """
+    MediaFile model
+    """
+    pass
+
 class Song(BaseModel):
     """
     Song model
@@ -75,6 +81,13 @@
         Column(u'display_name', types.Unicode(255), nullable=False)
     )
 
+    # Definition of the "media_files" table
+    media_files_table = Table(u'media_files', metadata,
+        Column(u'id', types.Integer, primary_key=True),
+        Column(u'file_name', types.Unicode(255), nullable=False),
+        Column(u'type', types.Unicode(64), nullable=False, default=u'audio')
+    )
+
     # Definition of the "song_books" table
     song_books_table = Table(u'song_books', metadata,
         Column(u'id', types.Integer, primary_key=True),
@@ -88,6 +101,7 @@
         Column(u'song_book_id', types.Integer,
             ForeignKey(u'song_books.id'), default=0),
         Column(u'title', types.Unicode(255), nullable=False),
+        Column(u'alternate_title', types.Unicode(255)),
         Column(u'lyrics', types.UnicodeText, nullable=False),
         Column(u'verse_order', types.Unicode(128)),
         Column(u'copyright', types.Unicode(255)),
@@ -113,6 +127,14 @@
             ForeignKey(u'songs.id'), primary_key=True)
     )
 
+    # Definition of the "media_files_songs" table
+    media_files_songs_table = Table(u'media_files_songs', metadata,
+        Column(u'media_file_id', types.Integer,
+            ForeignKey(u'media_files.id'), primary_key=True),
+        Column(u'song_id', types.Integer,
+            ForeignKey(u'songs.id'), primary_key=True)
+    )
+
     # Definition of the "songs_topics" table
     songs_topics_table = Table(u'songs_topics', metadata,
         Column(u'song_id', types.Integer,
@@ -125,6 +147,7 @@
     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'media_files_id', media_files_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)
@@ -132,6 +155,10 @@
         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'media_files_songs_file', media_files_songs_table.c.media_file_id,
+        media_files_songs_table.c.song_id)
+    Index(u'media_files_songs_song', media_files_songs_table.c.song_id,
+        media_files_songs_table.c.media_file_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,
@@ -139,12 +166,17 @@
 
     mapper(Author, authors_table)
     mapper(Book, song_books_table)
+    mapper(MediaFile, media_files_table)
     mapper(Song, songs_table,
-        properties={'authors': relation(Author, backref='songs',
-            secondary=authors_songs_table),
+        properties={
+            'authors': relation(Author, backref='songs',
+                secondary=authors_songs_table),
             'book': relation(Book, backref='songs'),
+            'media_files': relation(MediaFile, backref='songs',
+                secondary=media_files_songs_table),
             'topics': relation(Topic, backref='songs',
-            secondary=songs_topics_table)})
+                secondary=songs_topics_table)
+        })
     mapper(Topic, topics_table)
 
     metadata.create_all(checkfirst=True)

=== modified file 'openlp/plugins/songs/lib/mediaitem.py'
--- openlp/plugins/songs/lib/mediaitem.py	2010-07-08 10:26:52 +0000
+++ openlp/plugins/songs/lib/mediaitem.py	2010-07-20 12:45:57 +0000
@@ -164,20 +164,20 @@
         search_type = self.SearchTypeComboBox.currentIndex()
         if search_type == 0:
             log.debug(u'Titles Search')
-            search_results = self.parent.manager.get_all_objects_filtered(Song,
+            search_results = self.parent.manager.get_all_objects(Song,
                 Song.search_title.like(u'%' + search_keywords + u'%'),
                 Song.search_title.asc())
             self.displayResultsSong(search_results)
         elif search_type == 1:
             log.debug(u'Lyrics Search')
-            search_results = self.parent.manager.get_all_objects_filtered(Song,
+            search_results = self.parent.manager.get_all_objects(Song,
                 Song.search_lyrics.like(u'%' + search_keywords + u'%'),
                 Song.search_lyrics.asc())
             self.displayResultsSong(search_results)
         elif search_type == 2:
             log.debug(u'Authors Search')
-            search_results = self.parent.manager.get_all_objects_filtered(
-                Author, Author.display_name.like(u'%' + search_keywords + u'%'),
+            search_results = self.parent.manager.get_all_objects(Author,
+                Author.display_name.like(u'%' + search_keywords + u'%'),
                 Author.display_name.asc())
             self.displayResultsAuthor(search_results)
         #Called to redisplay the song list screen edith from a search

=== added file 'openlp/plugins/songs/lib/olpimport.py'
--- openlp/plugins/songs/lib/olpimport.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/olpimport.py	2010-07-20 12:45:57 +0000
@@ -0,0 +1,200 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2010 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin      #
+# Thompson, Jon Tibble, 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                          #
+###############################################################################
+"""
+The :mod:`olpimport` module provides the functionality for importing OpenLP
+song databases into the current installation database.
+"""
+import logging
+
+from sqlalchemy import create_engine, MetaData
+from sqlalchemy.orm import class_mapper, mapper, relation, scoped_session, \
+    sessionmaker
+from sqlalchemy.orm.exc import UnmappedClassError
+
+from openlp.core.lib.db import BaseModel
+from openlp.plugins.songs.lib.db import Author, Book, Song, Topic #, MediaFile
+
+log = logging.getLogger(__name__)
+
+class OldAuthor(BaseModel):
+    """
+    Author model
+    """
+    pass
+
+class OldBook(BaseModel):
+    """
+    Book model
+    """
+    pass
+
+class OldMediaFile(BaseModel):
+    """
+    MediaFile model
+    """
+    pass
+
+class OldSong(BaseModel):
+    """
+    Song model
+    """
+    pass
+
+class OldTopic(BaseModel):
+    """
+    Topic model
+    """
+    pass
+
+class OpenLPSongImport(object):
+    """
+
+    """
+    def __init__(self, master_manager, source_db):
+        """
+
+        """
+        self.master_manager = master_manager
+        self.import_source = source_db
+        self.source_session = None
+
+    def import_source_v2_db(self):
+        """
+
+        """
+        engine = create_engine(self.import_source)
+        source_meta = MetaData()
+        source_meta.reflect(engine)
+        self.source_session = scoped_session(sessionmaker(bind=engine))
+        if u'media_files' in source_meta.tables.keys():
+            has_media_files = True
+        else:
+            has_media_files = False
+        source_authors_table = source_meta.tables[u'authors']
+        source_song_books_table = source_meta.tables[u'song_books']
+        source_songs_table = source_meta.tables[u'songs']
+        source_topics_table = source_meta.tables[u'topics']
+        source_authors_songs_table = source_meta.tables[u'authors_songs']
+        source_songs_topics_table = source_meta.tables[u'songs_topics']
+        if has_media_files:
+            source_media_files_table = source_meta.tables[u'media_files']
+            source_media_files_songs_table = \
+                source_meta.tables[u'media_files_songs']
+            try:
+                class_mapper(OldMediaFile)
+            except UnmappedClassError:
+                mapper(OldMediaFile, source_media_files_table)
+        song_props = {
+            'authors': relation(OldAuthor, backref='songs',
+                secondary=source_authors_songs_table),
+            'book': relation(OldBook, backref='songs'),
+            'topics': relation(OldTopic, backref='songs',
+                secondary=source_songs_topics_table)
+        }
+        if has_media_files:
+            song_props['media_files'] = relation(OldMediaFile, backref='songs',
+                secondary=source_media_files_songs_table)
+        try:
+            class_mapper(OldAuthor)
+        except UnmappedClassError:
+            mapper(OldAuthor, source_authors_table)
+        try:
+            class_mapper(OldBook)
+        except UnmappedClassError:
+            mapper(OldBook, source_song_books_table)
+        try:
+            class_mapper(OldSong)
+        except UnmappedClassError:
+            mapper(OldSong, source_songs_table, properties=song_props)
+        try:
+            class_mapper(OldTopic)
+        except UnmappedClassError:
+            mapper(OldTopic, source_topics_table)
+
+        source_songs = self.source_session.query(OldSong).all()
+        for song in source_songs:
+            new_song = Song()
+            new_song.title = song.title
+            if has_media_files:
+                new_song.alternate_title = song.alternate_title
+            else:
+                new_song.alternate_title = u''
+            new_song.search_title = song.search_title
+            new_song.song_number = song.song_number
+            new_song.lyrics = song.lyrics
+            new_song.search_lyrics = song.search_lyrics
+            new_song.verse_order = song.verse_order
+            new_song.copyright = song.copyright
+            new_song.comments = song.comments
+            new_song.theme_name = song.theme_name
+            new_song.ccli_number = song.ccli_number
+            if song.authors:
+                for author in song.authors:
+                    existing_author = self.master_manager.get_object_filtered(
+                        Author, Author.display_name == author.display_name)
+                    if existing_author:
+                        new_song.authors.append(existing_author)
+                    else:
+                        new_song.authors.append(Author.populate(
+                            first_name=author.first_name,
+                            last_name=author.last_name,
+                            display_name=author.display_name))
+            else:
+                au = self.master_manager.get_object_filtered(Author,
+                    Author.display_name == u'Author Unknown')
+                if au:
+                    new_song.authors.append(au)
+                else:
+                    new_song.authors.append(Author.populate(
+                        display_name=u'Author Unknown'))
+            if song.song_book_id != 0:
+                existing_song_book = self.master_manager.get_object_filtered(
+                    Book, Book.name == song.book.name)
+                if existing_song_book:
+                    new_song.book = existing_song_book
+                else:
+                    new_song.book = Book.populate(name=song.book.name,
+                        publisher=song.book.publisher)
+            if song.topics:
+                for topic in song.topics:
+                    existing_topic = self.master_manager.get_object_filtered(
+                        Topic, Topic.name == topic.name)
+                    if existing_topic:
+                        new_song.topics.append(existing_topic)
+                    else:
+                        new_song.topics.append(Topic.populate(name=topic.name))
+#            if has_media_files:
+#                if song.media_files:
+#                    for media_file in song.media_files:
+#                        existing_media_file = \
+#                            self.master_manager.get_object_filtered(MediaFile,
+#                                MediaFile.file_name == media_file.file_name)
+#                        if existing_media_file:
+#                            new_song.media_files.append(existing_media_file)
+#                        else:
+#                            new_song.media_files.append(MediaFile.populate(
+#                                file_name=media_file.file_name))
+            self.master_manager.save_object(new_song)
+        engine.dispose()

=== modified file 'openlp/plugins/songs/lib/opensongimport.py'
--- openlp/plugins/songs/lib/opensongimport.py	2010-07-18 19:44:49 +0000
+++ openlp/plugins/songs/lib/opensongimport.py	2010-07-20 12:45:57 +0000
@@ -23,17 +23,13 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 
+import logging
 import os
-import re
-
 from zipfile import ZipFile
-
-from lxml.etree import Element
 from lxml import objectify
 
 from openlp.plugins.songs.lib.songimport import SongImport
 
-import logging
 log = logging.getLogger(__name__)
 
 class OpenSongImportError(Exception):
@@ -148,8 +144,6 @@
                     self.song_import.__setattr__(fn_or_string, ustring)
                 else:
                     fn_or_string(ustring)
-
-        res = []
         if u'theme' in fields:
             self.song_import.topics.append(unicode(root.theme))
         if u'alttheme' in fields:
@@ -218,7 +212,6 @@
         versetypes = verses.keys()
         versetypes.sort()
         versetags = {}
-        verse_renames = {}
         for versetype in versetypes:
             versenums = verses[versetype].keys()
             versenums.sort()
@@ -241,6 +234,7 @@
                 log.warn(u'Got order %s but not in versetags, skipping', tag)
             else:
                 self.song_import.verse_order_list.append(tag)
+
     def finish(self):
         """ Separate function, allows test suite to not pollute database"""
         self.song_import.finish()

=== modified file 'openlp/plugins/songs/lib/songimport.py'
--- openlp/plugins/songs/lib/songimport.py	2010-07-18 19:44:49 +0000
+++ openlp/plugins/songs/lib/songimport.py	2010-07-20 12:45:57 +0000
@@ -50,7 +50,7 @@
         self.song_number = u''
         self.alternate_title = u''
         self.copyright = u''
-        self.comment = u''
+        self.comments = u''
         self.theme_name = u''
         self.ccli_number = u''
         self.authors = []
@@ -253,7 +253,7 @@
         song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
         song.verse_order = u' '.join(self.verse_order_list)
         song.copyright = self.copyright
-        song.comment = self.comment
+        song.comments = self.comments
         song.theme_name = self.theme_name
         song.ccli_number = self.ccli_number
         for authortext in self.authors:
@@ -274,7 +274,8 @@
         for topictext in self.topics:
             if len(topictext) == 0:
                 continue
-            topic = self.manager.get_object_filtered(Topic, Topic.name == topictext)
+            topic = self.manager.get_object_filtered(Topic,
+                Topic.name == topictext)
             if topic is None:
                 topic = Topic.populate(name=topictext)
             song.topics.append(topic)
@@ -303,8 +304,8 @@
             print u'NUMBER: ' + self.song_number
         for topictext in self.topics:
             print u'TOPIC: ' + topictext
-        if self.comment:
-            print u'COMMENT: ' + self.comment
+        if self.comments:
+            print u'COMMENTS: ' + self.comments
         if self.theme_name:
             print u'THEME: ' + self.theme_name
         if self.ccli_number:

=== modified file 'openlp/plugins/songs/lib/songxml.py'
--- openlp/plugins/songs/lib/songxml.py	2010-07-18 19:44:49 +0000
+++ openlp/plugins/songs/lib/songxml.py	2010-07-20 12:45:57 +0000
@@ -28,7 +28,6 @@
 #import os
 
 from types import ListType
-from xml.etree.ElementTree import ElementTree, XML
 
 # Do we need these two lines?
 #sys.path.append(os.path.abspath(u'./../../../..'))

=== modified file 'openlp/plugins/songs/lib/test/test_opensongimport.py'
--- openlp/plugins/songs/lib/test/test_opensongimport.py	2010-07-18 19:27:27 +0000
+++ openlp/plugins/songs/lib/test/test_opensongimport.py	2010-07-20 12:45:57 +0000
@@ -22,11 +22,10 @@
 # with this program; if not, write to the Free Software Foundation, Inc., 59  #
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
+
 from openlp.plugins.songs.lib.opensongimport import OpenSongImport
 from openlp.core.lib.db import Manager
 from openlp.plugins.songs.lib.db import init_schema
-from openlp.plugins.songs.songsplugin import SongsPlugin
-import sys
 
 def test():
     manager = Manager(u'songs', init_schema)

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2010-07-14 20:52:45 +0000
+++ openlp/plugins/songs/songsplugin.py	2010-07-20 12:45:57 +0000
@@ -30,7 +30,7 @@
 from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver, \
     translate
 from openlp.core.lib.db import Manager
-from openlp.plugins.songs.lib import SongMediaItem, SongsTab
+from openlp.plugins.songs.lib import OpenLPSongImport, SongMediaItem, SongsTab
 from openlp.plugins.songs.lib.db import init_schema, Song
 
 try:
@@ -71,7 +71,7 @@
         log.info(u'Songs Initialising')
         Plugin.initialise(self)
         self.mediaItem.displayResultsSong(
-            self.manager.get_all_objects(Song, Song.title))
+            self.manager.get_all_objects(Song, order_by_ref=Song.title))
 
     def getMediaManagerItem(self):
         """
@@ -157,7 +157,19 @@
         import_menu.addAction(self.ImportOpenSongItem)
         QtCore.QObject.connect(self.ImportOpenSongItem,
                 QtCore.SIGNAL(u'triggered()'), self.onImportOpenSongItemClick)
-
+        # OpenLP v2 import menu item - ditto above regarding refactoring into
+        # an import wizard
+        self.ImportOpenLPSongItem = QtGui.QAction(import_menu)
+        self.ImportOpenLPSongItem.setObjectName(u'ImportOpenLPSongItem')
+        self.ImportOpenLPSongItem.setText(translate('SongsPlugin',
+            'OpenLP v2 Songs (temporary)'))
+        self.ImportOpenLPSongItem.setToolTip(translate('SongsPlugin',
+            'Import an OpenLP v2 song database'))
+        self.ImportOpenLPSongItem.setStatusTip(translate('SongsPlugin',
+            'Import an OpenLP v2 song database'))
+        import_menu.addAction(self.ImportOpenLPSongItem)
+        QtCore.QObject.connect(self.ImportOpenLPSongItem,
+            QtCore.SIGNAL(u'triggered()'), self.onImportOpenLPSongItemClick)
 
     def addExportMenuItem(self, export_menu):
         """
@@ -218,6 +230,25 @@
                 QtGui.QMessageBox.Ok)
         Receiver.send_message(u'songs_load_list')
 
+    def onImportOpenLPSongItemClick(self):
+        filenames = QtGui.QFileDialog.getOpenFileNames(None,
+            translate('SongsPlugin', 'Select OpenLP database(s) to import...'),
+            u'', u'OpenLP databases (*.sqlite);;All Files (*)')
+        try:
+            for filename in filenames:
+                db_url = u'sqlite:///%s' % filename
+                importer = OpenLPSongImport(self.manager, db_url)
+                importer.import_source_v2_db()
+            QtGui.QMessageBox.information(None, translate('SongsPlugin',
+                'Database(s) imported'), translate('SongsPlugin', 'Your '
+                'OpenLP v2 song databases have been successfully imported'))
+        except:
+            log.exception(u'Failed to import OpenLP v2 database(s)')
+            QtGui.QMessageBox.critical(None, translate('SongsPlugin',
+                'Import Error'), translate('SongsPlugin',
+                'Error importing OpenLP v2 database(s)'))
+        Receiver.send_message(u'songs_load_list')
+
     def onImportOooItemClick(self):
         filenames = QtGui.QFileDialog.getOpenFileNames(
             None, translate('SongsPlugin',
@@ -239,8 +270,7 @@
 
         Returns True if the theme is being used, otherwise returns False.
         """
-        if self.manager.get_all_objects_filtered(Song,
-            Song.theme_name == theme):
+        if self.manager.get_all_objects(Song, Song.theme_name == theme):
             return True
         return False
 
@@ -255,7 +285,7 @@
         ``newTheme``
             The new name the plugin should now use.
         """
-        songsUsingTheme = self.manager.get_all_objects_filtered(Song,
+        songsUsingTheme = self.manager.get_all_objects(Song,
             Song.theme_name == oldTheme)
         for song in songsUsingTheme:
             song.theme_name = newTheme

=== modified file 'openlp/plugins/songusage/forms/songusagedeleteform.py'
--- openlp/plugins/songusage/forms/songusagedeleteform.py	2010-06-21 18:28:36 +0000
+++ openlp/plugins/songusage/forms/songusagedeleteform.py	2010-07-20 12:45:57 +0000
@@ -25,8 +25,9 @@
 
 from PyQt4 import QtGui
 
+from openlp.core.lib import translate
+from openlp.plugins.songusage.lib.db import SongUsageItem
 from songusagedeletedialog import Ui_SongUsageDeleteDialog
-from openlp.core.lib import translate
 
 class SongUsageDeleteForm(QtGui.QDialog, Ui_SongUsageDeleteDialog):
     """
@@ -52,6 +53,6 @@
             QtGui.QMessageBox.Cancel)
         if ret == QtGui.QMessageBox.Ok:
             deleteDate = self.DeleteCalendar.selectedDate().toPyDate()
-            self.songusagemanager.delete_to_date(deleteDate)
+            self.songusagemanager.delete_all_objects(SongUsageItem,
+                SongUsageItem.usagedate <= deleteDate)
         self.close()
-

=== modified file 'openlp/plugins/songusage/forms/songusagedetailform.py'
--- openlp/plugins/songusage/forms/songusagedetailform.py	2010-06-29 15:25:24 +0000
+++ openlp/plugins/songusage/forms/songusagedetailform.py	2010-07-20 12:45:57 +0000
@@ -27,9 +27,10 @@
 import os
 
 from PyQt4 import QtCore, QtGui
+from sqlalchemy.sql import and_
 
 from openlp.core.lib import SettingsManager, translate
-
+from openlp.plugins.songusage.lib.db import SongUsageItem
 from songusagedetaildialog import Ui_SongUsageDetailDialog
 
 log = logging.getLogger(__name__)
@@ -74,8 +75,11 @@
         filename = u'usage_detail_%s_%s.txt' % (
             self.FromDate.selectedDate().toString(u'ddMMyyyy'),
             self.ToDate.selectedDate().toString(u'ddMMyyyy'))
-        usage = self.parent.songusagemanager.get_songusage_for_period(
-            self.FromDate.selectedDate(), self.ToDate.selectedDate())
+        usage = self.parent.songusagemanager.get_all_objects(
+            SongUsageItem, and_(
+            SongUsageItem.usagedate >= self.FromDate.selectedDate().toPyDate(),
+            SongUsageItem.usagedate < self.ToDate.selectedDate().toPyDate()),
+            [SongUsageItem.usagedate, SongUsageItem.usagetime])
         outname = os.path.join(unicode(self.FileLineEdit.text()), filename)
         file = None
         try:

=== modified file 'openlp/plugins/songusage/lib/__init__.py'
--- openlp/plugins/songusage/lib/__init__.py	2010-06-18 01:26:01 +0000
+++ openlp/plugins/songusage/lib/__init__.py	2010-07-20 12:45:57 +0000
@@ -25,4 +25,3 @@
 """
 The :mod:`lib` module contains the library functions for the songusage plugin.
 """
-from openlp.plugins.songusage.lib.manager import SongUsageManager

=== removed file 'openlp/plugins/songusage/lib/manager.py'
--- openlp/plugins/songusage/lib/manager.py	2010-06-29 15:25:24 +0000
+++ openlp/plugins/songusage/lib/manager.py	1970-01-01 00:00:00 +0000
@@ -1,81 +0,0 @@
-# -*- coding: utf-8 -*-
-# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
-
-###############################################################################
-# OpenLP - Open Source Lyrics Projection                                      #
-# --------------------------------------------------------------------------- #
-# Copyright (c) 2008-2010 Raoul Snyman                                        #
-# Portions copyright (c) 2008-2010 Tim Bentley, Jonathan Corwin, Michael      #
-# Gorven, Scott Guerrieri, Christian Richter, Maikel Stuivenberg, Martin      #
-# Thompson, Jon Tibble, 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                          #
-###############################################################################
-"""
-The :mod:`manager` module provides song usage specific database query code
-"""
-import logging
-
-from sqlalchemy.exceptions import InvalidRequestError
-
-from openlp.core.lib.db import Manager
-from openlp.plugins.songusage.lib.db import init_schema, SongUsageItem
-
-log = logging.getLogger(__name__)
-
-class SongUsageManager(Manager):
-    """
-    The Song Manager provides a central location for all database code. This
-    class takes care of connecting to the database and running all the queries.
-    """
-    log.info(u'SongUsage manager loaded')
-
-    def __init__(self):
-        """
-        Creates the connection to the database, and creates the tables if they
-        don't exist.
-        """
-        log.debug(u'SongUsage Initialising')
-        Manager.__init__(self, u'songusage', init_schema)
-        log.debug(u'SongUsage Initialised')
-
-    def get_songusage_for_period(self, start_date, end_date):
-        """
-        Returns the details of SongUsage for a designated time period
-
-        ``start_date``
-            The start of the period to return
-
-        ``end_date``
-            The end of the period to return
-        """
-        return self.session.query(SongUsageItem) \
-            .filter(SongUsageItem.usagedate >= start_date.toPyDate()) \
-            .filter(SongUsageItem.usagedate < end_date.toPyDate()) \
-            .order_by(SongUsageItem.usagedate, SongUsageItem.usagetime).all()
-
-    def delete_to_date(self, date):
-        """
-        Delete SongUsage records before given date
-        """
-        try:
-            self.session.query(SongUsageItem) \
-                .filter(SongUsageItem.usagedate <= date) \
-                .delete(synchronize_session=False)
-            self.session.commit()
-            return True
-        except InvalidRequestError:
-            self.session.rollback()
-            log.exception(u'Failed to delete all Song Usage items to %s' % date)
-            return False

=== modified file 'openlp/plugins/songusage/songusageplugin.py'
--- openlp/plugins/songusage/songusageplugin.py	2010-07-05 16:00:48 +0000
+++ openlp/plugins/songusage/songusageplugin.py	2010-07-20 12:45:57 +0000
@@ -24,15 +24,15 @@
 ###############################################################################
 
 import logging
-
 from datetime import datetime
+
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.lib import Plugin, Receiver, build_icon, translate
-from openlp.plugins.songusage.lib import SongUsageManager
+from openlp.core.lib.db import Manager
 from openlp.plugins.songusage.forms import SongUsageDetailForm, \
     SongUsageDeleteForm
-from openlp.plugins.songusage.lib.db import SongUsageItem
+from openlp.plugins.songusage.lib.db import init_schema, SongUsageItem
 
 log = logging.getLogger(__name__)
 
@@ -117,7 +117,7 @@
             QtCore.QVariant(False)).toBool()
         self.SongUsageStatus.setChecked(self.SongUsageActive)
         if self.songusagemanager is None:
-            self.songusagemanager = SongUsageManager()
+            self.songusagemanager = Manager(u'songusage', init_schema)
         self.SongUsagedeleteform = SongUsageDeleteForm(self.songusagemanager)
         self.SongUsagedetailform = SongUsageDetailForm(self)
         self.SongUsageMenu.menuAction().setVisible(True)


Follow ups