OpenLP v2 song DB importer

This commit is contained in:
Jon Tibble 2010-07-20 09:33:22 +01:00
parent 80eb8e36af
commit 7e623ea226
4 changed files with 238 additions and 7 deletions

View File

@ -142,6 +142,7 @@ from songstab import SongsTab
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

View File

@ -0,0 +1,198 @@
# -*- 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 #, AudioFile
log = logging.getLogger(__name__)
class OldAudioFile(BaseModel):
"""
AudioFile model
"""
pass
class OldAuthor(BaseModel):
"""
Author model
"""
pass
class OldBook(BaseModel):
"""
Book 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'audio_files' in source_meta.tables.keys():
has_audio_files = True
else:
has_audio_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_audio_files:
source_audio_files_table = source_meta.tables[u'audio_files']
source_audio_files_songs_table = \
source_meta.tables[u'audio_files_songs']
try:
class_mapper(OldAudioFile)
except UnmappedClassError:
mapper(OldAudioFile, source_audio_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_audio_files:
song_props['audio_files'] = relation(OldAudioFile, backref='songs',
secondary=source_audio_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_audio_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_audio_files:
# if song.audio_files:
# for audio_file in song.audio_files:
# existing_audio_file = \
# self.master_manager.get_object_filtered(AudioFile,
# AudioFile.file_name == audio_file.file_name)
# if existing_audio_file:
# new_song.audio_files.remove(audio_file)
# new_song.audio_files.append(existing_audio_file)
self.master_manager.save_object(new_song)
engine.dispose()

View File

@ -50,7 +50,7 @@ class SongImport(object):
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 @@ class SongImport(object):
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 @@ class SongImport(object):
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 @@ class SongImport(object):
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:

View File

@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui
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:
@ -157,7 +157,19 @@ class SongsPlugin(Plugin):
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 (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 @@ class SongsPlugin(Plugin):
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',