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 mediaitem import SongMediaItem
from songimport import SongImport from songimport import SongImport
from opensongimport import OpenSongImport from opensongimport import OpenSongImport
from olpimport import OpenLPSongImport
try: try:
from sofimport import SofImport from sofimport import SofImport
from oooimport import OooImport 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.song_number = u''
self.alternate_title = u'' self.alternate_title = u''
self.copyright = u'' self.copyright = u''
self.comment = u'' self.comments = u''
self.theme_name = u'' self.theme_name = u''
self.ccli_number = u'' self.ccli_number = u''
self.authors = [] self.authors = []
@ -253,7 +253,7 @@ class SongImport(object):
song.lyrics = unicode(sxml.extract_xml(), u'utf-8') song.lyrics = unicode(sxml.extract_xml(), u'utf-8')
song.verse_order = u' '.join(self.verse_order_list) song.verse_order = u' '.join(self.verse_order_list)
song.copyright = self.copyright song.copyright = self.copyright
song.comment = self.comment song.comments = self.comments
song.theme_name = self.theme_name song.theme_name = self.theme_name
song.ccli_number = self.ccli_number song.ccli_number = self.ccli_number
for authortext in self.authors: for authortext in self.authors:
@ -274,7 +274,8 @@ class SongImport(object):
for topictext in self.topics: for topictext in self.topics:
if len(topictext) == 0: if len(topictext) == 0:
continue 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: if topic is None:
topic = Topic.populate(name=topictext) topic = Topic.populate(name=topictext)
song.topics.append(topic) song.topics.append(topic)
@ -303,8 +304,8 @@ class SongImport(object):
print u'NUMBER: ' + self.song_number print u'NUMBER: ' + self.song_number
for topictext in self.topics: for topictext in self.topics:
print u'TOPIC: ' + topictext print u'TOPIC: ' + topictext
if self.comment: if self.comments:
print u'COMMENT: ' + self.comment print u'COMMENTS: ' + self.comments
if self.theme_name: if self.theme_name:
print u'THEME: ' + self.theme_name print u'THEME: ' + self.theme_name
if self.ccli_number: 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, \ from openlp.core.lib import Plugin, build_icon, PluginStatus, Receiver, \
translate translate
from openlp.core.lib.db import Manager 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 from openlp.plugins.songs.lib.db import init_schema, Song
try: try:
@ -157,7 +157,19 @@ class SongsPlugin(Plugin):
import_menu.addAction(self.ImportOpenSongItem) import_menu.addAction(self.ImportOpenSongItem)
QtCore.QObject.connect(self.ImportOpenSongItem, QtCore.QObject.connect(self.ImportOpenSongItem,
QtCore.SIGNAL(u'triggered()'), self.onImportOpenSongItemClick) 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): def addExportMenuItem(self, export_menu):
""" """
@ -218,6 +230,25 @@ class SongsPlugin(Plugin):
QtGui.QMessageBox.Ok) QtGui.QMessageBox.Ok)
Receiver.send_message(u'songs_load_list') 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): def onImportOooItemClick(self):
filenames = QtGui.QFileDialog.getOpenFileNames( filenames = QtGui.QFileDialog.getOpenFileNames(
None, translate('SongsPlugin', None, translate('SongsPlugin',