Beispiel #1
0
    def _process_songbooks(self, foilpresenterfolie, song):
        """
        Adds the song book and song number specified in the XML to the song.

        :param foilpresenterfolie: The property object (lxml.objectify.ObjectifiedElement).
        :param song: The song object.
        """
        song.song_book_id = 0
        song.song_number = ''
        try:
            for bucheintrag in foilpresenterfolie.buch.bucheintrag:
                book_name = to_str(bucheintrag.name)
                if book_name:
                    book = self.manager.get_object_filtered(
                        Book, Book.name == book_name)
                    if book is None:
                        # We need to create a book, because it does not exist.
                        book = Book.populate(name=book_name, publisher='')
                        self.manager.save_object(book)
                    song.song_book_id = book.id
                    try:
                        if to_str(bucheintrag.nummer):
                            song.song_number = to_str(bucheintrag.nummer)
                    except AttributeError:
                        pass
                    # We only support one song book, so take the first one.
                    break
        except AttributeError:
            pass
Beispiel #2
0
    def _process_songbooks(self, properties, song):
        """
        Adds the song book and song number specified in the XML to the song.

        ``properties``
            The property object (lxml.objectify.ObjectifiedElement).

        ``song``
            The song object.
        """
        song.song_book_id = None
        song.song_number = u''
        if hasattr(properties, u'songbooks'):
            for songbook in properties.songbooks.songbook:
                book_name = songbook.get(u'name', u'')
                if book_name:
                    book = self.manager.get_object_filtered(Book, Book.name == book_name)
                    if book is None:
                        # We need to create a book, because it does not exist.
                        book = Book.populate(name=book_name, publisher=u'')
                        self.manager.save_object(book)
                    song.song_book_id = book.id
                    song.song_number = songbook.get(u'entry', u'')
                    # We only support one song book, so take the first one.
                    break
Beispiel #3
0
    def test_add_songbooks(self):
        """
        Test that adding songbooks to a song works correctly
        """
        # GIVEN: A mocked song and songbook
        song = Song()
        song.songbook_entries = []
        songbook = Book()
        songbook.name = "Thy Word"

        # WHEN: We add two songbooks to a Song
        song.add_songbook_entry(songbook, "120")
        song.add_songbook_entry(songbook, "550A")

        # THEN: The song should have two songbook entries
        self.assertEqual(len(song.songbook_entries), 2, 'There should be two Songbook entries.')
Beispiel #4
0
    def _process_songbooks(self, foilpresenterfolie, song):
        """
        Adds the song book and song number specified in the XML to the song.

        :param foilpresenterfolie: The property object (lxml.objectify.ObjectifiedElement).
        :param song: The song object.
        """
        song.song_book_id = 0
        song.song_number = ''
        try:
            for bucheintrag in foilpresenterfolie.buch.bucheintrag:
                book_name = self._child(bucheintrag.name)
                if book_name:
                    book = self.manager.get_object_filtered(Book, Book.name == book_name)
                    if book is None:
                        # We need to create a book, because it does not exist.
                        book = Book.populate(name=book_name, publisher='')
                        self.manager.save_object(book)
                    song.song_book_id = book.id
                    try:
                        if self._child(bucheintrag.nummer):
                            song.song_number = self._child(bucheintrag.nummer)
                    except AttributeError:
                        pass
                    # We only support one song book, so take the first one.
                    break
        except AttributeError:
            pass
Beispiel #5
0
    def test_add_songbooks(self):
        """
        Test that adding songbooks to a song works correctly
        """
        # GIVEN: A mocked song and songbook
        song = Song()
        song.songbook_entries = []
        songbook = Book()
        songbook.name = "Thy Word"

        # WHEN: We add two songbooks to a Song
        song.add_songbook_entry(songbook, "120")
        song.add_songbook_entry(songbook, "550A")

        # THEN: The song should have two songbook entries
        self.assertEqual(len(song.songbook_entries), 2, 'There should be two Songbook entries.')
 def on_add_book_button_clicked(self):
     """
     Add a book to the list.
     """
     if self.song_book_form.exec_():
         book = Book.populate(name=self.song_book_form.name_edit.text(),
                              publisher=self.song_book_form.publisher_edit.text())
         if self.check_song_book_exists(book):
             if self.manager.save_object(book):
                 self.reset_song_books()
             else:
                 critical_error_message_box(
                     message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your book.'))
         else:
             critical_error_message_box(
                 message=translate('SongsPlugin.SongMaintenanceForm', 'This book already exists.'))
Beispiel #7
0
 def on_add_book_button_clicked(self):
     """
     Add a book to the list.
     """
     if self.song_book_form.exec():
         book = Book.populate(name=self.song_book_form.name_edit.text(),
                              publisher=self.song_book_form.publisher_edit.text())
         if self.check_song_book_exists(book):
             if self.manager.save_object(book):
                 self.reset_song_books()
             else:
                 critical_error_message_box(
                     message=translate('SongsPlugin.SongMaintenanceForm', 'Could not add your book.'))
         else:
             critical_error_message_box(
                 message=translate('SongsPlugin.SongMaintenanceForm', 'This book already exists.'))
    def _process_songbooks(self, properties, song):
        """
        Adds the song book and song number specified in the XML to the song.

        :param properties: The property object (lxml.objectify.ObjectifiedElement).
        :param song: The song object.
        """
        if hasattr(properties, 'songbooks'):
            for songbook in properties.songbooks.songbook:
                book_name = songbook.get('name', '')
                if book_name:
                    book = self.manager.get_object_filtered(Book, Book.name == book_name)
                    if book is None:
                        # We need to create a book, because it does not exist.
                        book = Book.populate(name=book_name, publisher='')
                        self.manager.save_object(book)
                    song.add_songbook_entry(book, songbook.get('entry', ''))
Beispiel #9
0
    def _process_songbooks(self, properties, song):
        """
        Adds the song book and song number specified in the XML to the song.

        :param properties: The property object (lxml.objectify.ObjectifiedElement).
        :param song: The song object.
        """
        if hasattr(properties, 'songbooks'):
            for songbook in properties.songbooks.songbook:
                book_name = songbook.get('name', '')
                if book_name:
                    book = self.manager.get_object_filtered(Book, Book.name == book_name)
                    if book is None:
                        # We need to create a book, because it does not exist.
                        book = Book.populate(name=book_name, publisher='')
                        self.manager.save_object(book)
                    song.add_songbook_entry(book, songbook.get('entry', ''))
Beispiel #10
0
 def _validate_song(self):
     """
     Check the validity of the song.
     """
     # This checks data in the form *not* self.song. self.song is still
     # None at this point.
     log.debug('Validate Song')
     # Lets be nice and assume the data is correct.
     if not self.title_edit.text():
         self.song_tab_widget.setCurrentIndex(0)
         self.title_edit.setFocus()
         critical_error_message_box(
             message=translate('SongsPlugin.EditSongForm', 'You need to type in a song title.'))
         return False
     if self.verse_list_widget.rowCount() == 0:
         self.song_tab_widget.setCurrentIndex(0)
         self.verse_list_widget.setFocus()
         critical_error_message_box(
             message=translate('SongsPlugin.EditSongForm', 'You need to type in at least one verse.'))
         return False
     if self.authors_list_view.count() == 0:
         self.song_tab_widget.setCurrentIndex(1)
         self.authors_list_view.setFocus()
         critical_error_message_box(
             message=translate('SongsPlugin.EditSongForm', 'You need to have an author for this song.'))
         return False
     if self.verse_order_edit.text():
         result = self._validate_verse_list(self.verse_order_edit.text(), self.verse_list_widget.rowCount())
         if not result:
             return False
     text = self.song_book_combo_box.currentText()
     if self.song_book_combo_box.findText(text, QtCore.Qt.MatchExactly) < 0:
         if QtGui.QMessageBox.question(self, translate('SongsPlugin.EditSongForm', 'Add Book'),
                 translate('SongsPlugin.EditSongForm', 'This song book does not exist, do you want to add it?'),
                 QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
             book = Book.populate(name=text, publisher='')
             self.manager.save_object(book)
         else:
             return False
     return True
Beispiel #11
0
    def do_import(self, progress_dialog=None):
        """
        Run the import for an OpenLP version 2 song database.

        :param progress_dialog: The QProgressDialog used when importing songs from the FRW.
        """

        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

        # Check the file type
        if not self.import_source.endswith('.sqlite'):
            self.log_error(self.import_source, translate('SongsPlugin.OpenLPSongImport',
                                                         'Not a valid OpenLP 2.0 song database.'))
            return
        self.import_source = 'sqlite:///%s' % self.import_source
        # Load the db file
        engine = create_engine(self.import_source)
        source_meta = MetaData()
        source_meta.reflect(engine)
        self.source_session = scoped_session(sessionmaker(bind=engine))
        if 'media_files' in list(source_meta.tables.keys()):
            has_media_files = True
        else:
            has_media_files = False
        source_authors_table = source_meta.tables['authors']
        source_song_books_table = source_meta.tables['song_books']
        source_songs_table = source_meta.tables['songs']
        source_topics_table = source_meta.tables['topics']
        source_authors_songs_table = source_meta.tables['authors_songs']
        source_songs_topics_table = source_meta.tables['songs_topics']
        source_media_files_songs_table = None
        if has_media_files:
            source_media_files_table = source_meta.tables['media_files']
            source_media_files_songs_table = source_meta.tables.get('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:
            if isinstance(source_media_files_songs_table, Table):
                song_props['media_files'] = relation(OldMediaFile, backref='songs',
                                                     secondary=source_media_files_songs_table)
            else:
                song_props['media_files'] = \
                    relation(OldMediaFile, backref='songs',
                             foreign_keys=[source_media_files_table.c.song_id],
                             primaryjoin=source_songs_table.c.id == source_media_files_table.c.song_id)
        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()
        if self.import_wizard:
            self.import_wizard.progress_bar.setMaximum(len(source_songs))
        for song in source_songs:
            new_song = Song()
            new_song.title = song.title
            if has_media_files and hasattr(song, 'alternate_title'):
                new_song.alternate_title = song.alternate_title
            else:
                old_titles = song.search_title.split('@')
                if len(old_titles) > 1:
                    new_song.alternate_title = old_titles[1]
            # Values will be set when cleaning the song.

            if hasattr(song, 'song_key'):
                new_song.song_key = song.song_key
            if hasattr(song, 'transpose_by'):
                new_song.transpose_by = song.transpose_by

            new_song.search_title = ''
            new_song.search_lyrics = ''
            new_song.song_number = song.song_number
            new_song.lyrics = song.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
            for author in song.authors:
                existing_author = self.manager.get_object_filtered(Author, Author.display_name == author.display_name)
                if existing_author is None:
                    existing_author = Author.populate(
                        first_name=author.first_name,
                        last_name=author.last_name,
                        display_name=author.display_name)
                new_song.add_author(existing_author)
            if song.book:
                existing_song_book = self.manager.get_object_filtered(Book, Book.name == song.book.name)
                if existing_song_book is None:
                    existing_song_book = Book.populate(name=song.book.name, publisher=song.book.publisher)
                new_song.book = existing_song_book
            if song.topics:
                for topic in song.topics:
                    existing_topic = self.manager.get_object_filtered(Topic, Topic.name == topic.name)
                    if existing_topic is None:
                        existing_topic = Topic.populate(name=topic.name)
                    new_song.topics.append(existing_topic)
            if has_media_files:
                if song.media_files:
                    for media_file in song.media_files:
                        existing_media_file = self.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))
            clean_song(self.manager, new_song)
            self.manager.save_object(new_song)
            if progress_dialog:
                progress_dialog.setValue(progress_dialog.value() + 1)
                progress_dialog.setLabelText(WizardStrings.ImportingType % new_song.title)
            else:
                self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % new_song.title)
            if self.stop_import_flag:
                break
        self.source_session.close()
        engine.dispose()
Beispiel #12
0
 def finish(self):
     """
     All fields have been set to this song. Write the song to disk.
     """
     if not self.check_complete():
         self.set_defaults()
         return False
     log.info(
         'committing song {title} to database'.format(title=self.title))
     song = Song()
     song.title = self.title
     if self.import_wizard is not None:
         # TODO: Verify format() with template variables
         self.import_wizard.increment_progress_bar(
             WizardStrings.ImportingType % song.title)
     song.alternate_title = self.alternate_title
     # Values will be set when cleaning the song.
     song.search_title = ''
     song.search_lyrics = ''
     song.verse_order = ''
     song.song_number = self.song_number
     verses_changed_to_other = {}
     sxml = SongXML()
     other_count = 1
     for (verse_def, verse_text, lang) in self.verses:
         if verse_def[0].lower() in VerseType.tags:
             verse_tag = verse_def[0].lower()
         else:
             new_verse_def = '{tag}{count:d}'.format(
                 tag=VerseType.tags[VerseType.Other], count=other_count)
             verses_changed_to_other[verse_def] = new_verse_def
             other_count += 1
             verse_tag = VerseType.tags[VerseType.Other]
             log.info('Versetype {old} changing to {new}'.format(
                 old=verse_def, new=new_verse_def))
             verse_def = new_verse_def
         sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text,
                                  lang)
     song.lyrics = str(sxml.extract_xml(), 'utf-8')
     if not self.verse_order_list and self.verse_order_list_generated_useful:
         self.verse_order_list = self.verse_order_list_generated
     self.verse_order_list = [
         verses_changed_to_other.get(v, v) for v in self.verse_order_list
     ]
     song.verse_order = ' '.join(self.verse_order_list)
     song.copyright = self.copyright
     song.comments = self.comments
     song.theme_name = self.theme_name
     song.ccli_number = self.ccli_number
     for author_text, author_type in self.authors:
         author = self.manager.get_object_filtered(
             Author, Author.display_name == author_text)
         if not author:
             author = Author.populate(display_name=author_text,
                                      last_name=author_text.split(' ')[-1],
                                      first_name=' '.join(
                                          author_text.split(' ')[:-1]))
         song.add_author(author, author_type)
     if self.song_book_name:
         song_book = self.manager.get_object_filtered(
             Book, Book.name == self.song_book_name)
         if song_book is None:
             song_book = Book.populate(name=self.song_book_name,
                                       publisher=self.song_book_pub)
         song.add_songbook_entry(song_book, song.song_number)
     for topic_text in self.topics:
         if not topic_text:
             continue
         topic = self.manager.get_object_filtered(Topic,
                                                  Topic.name == topic_text)
         if topic is None:
             topic = Topic.populate(name=topic_text)
         song.topics.append(topic)
     # We need to save the song now, before adding the media files, so that
     # we know where to save the media files to.
     clean_song(self.manager, song)
     self.manager.save_object(song)
     # Now loop through the media files, copy them to the correct location,
     # and save the song again.
     for filename, weight in self.media_files:
         media_file = self.manager.get_object_filtered(
             MediaFile, MediaFile.file_name == filename)
         if not media_file:
             if os.path.dirname(filename):
                 filename = self.copy_media_file(song.id, filename)
             song.media_files.append(
                 MediaFile.populate(file_name=filename, weight=weight))
     self.manager.save_object(song)
     self.set_defaults()
     return True
Beispiel #13
0
    def do_import(self, progress_dialog=None):
        """
        Run the import for an OpenLP version 2 song database.

        :param progress_dialog: The QProgressDialog used when importing songs from the FRW.
        """

        class OldAuthor(BaseModel):
            """
            Maps to the authors table
            """
            pass

        class OldBook(BaseModel):
            """
            Maps to the songbooks table
            """
            pass

        class OldMediaFile(BaseModel):
            """
            Maps to the media_files table
            """
            pass

        class OldSong(BaseModel):
            """
            Maps to the songs table
            """
            pass

        class OldTopic(BaseModel):
            """
            Maps to the topics table
            """
            pass

        class OldSongBookEntry(BaseModel):
            """
            Maps to the songs_songbooks table
            """
            pass

        # Check the file type
        if not isinstance(self.import_source, str) or not self.import_source.endswith('.sqlite'):
            self.log_error(self.import_source, translate('SongsPlugin.OpenLPSongImport',
                                                         'Not a valid OpenLP 2 song database.'))
            return
        self.import_source = 'sqlite:///{url}'.format(url=self.import_source)
        # Load the db file and reflect it
        engine = create_engine(self.import_source)
        source_meta = MetaData()
        source_meta.reflect(engine)
        self.source_session = scoped_session(sessionmaker(bind=engine))
        # Run some checks to see which version of the database we have
        if 'media_files' in list(source_meta.tables.keys()):
            has_media_files = True
        else:
            has_media_files = False
        if 'songs_songbooks' in list(source_meta.tables.keys()):
            has_songs_books = True
        else:
            has_songs_books = False
        # Load up the tabls and map them out
        source_authors_table = source_meta.tables['authors']
        source_song_books_table = source_meta.tables['song_books']
        source_songs_table = source_meta.tables['songs']
        source_topics_table = source_meta.tables['topics']
        source_authors_songs_table = source_meta.tables['authors_songs']
        source_songs_topics_table = source_meta.tables['songs_topics']
        source_media_files_songs_table = None
        # Set up media_files relations
        if has_media_files:
            source_media_files_table = source_meta.tables['media_files']
            source_media_files_songs_table = source_meta.tables.get('media_files_songs')
            try:
                class_mapper(OldMediaFile)
            except UnmappedClassError:
                mapper(OldMediaFile, source_media_files_table)
        if has_songs_books:
            source_songs_songbooks_table = source_meta.tables['songs_songbooks']
            try:
                class_mapper(OldSongBookEntry)
            except UnmappedClassError:
                mapper(OldSongBookEntry, source_songs_songbooks_table, properties={'songbook': relation(OldBook)})
        # Set up the songs relationships
        song_props = {
            'authors': relation(OldAuthor, backref='songs', secondary=source_authors_songs_table),
            'topics': relation(OldTopic, backref='songs', secondary=source_songs_topics_table)
        }
        if has_media_files:
            if isinstance(source_media_files_songs_table, Table):
                song_props['media_files'] = relation(OldMediaFile, backref='songs',
                                                     secondary=source_media_files_songs_table)
            else:
                song_props['media_files'] = \
                    relation(OldMediaFile, backref='songs',
                             foreign_keys=[source_media_files_table.c.song_id],
                             primaryjoin=source_songs_table.c.id == source_media_files_table.c.song_id)
        if has_songs_books:
            song_props['songbook_entries'] = relation(OldSongBookEntry, backref='song', cascade='all, delete-orphan')
        else:
            song_props['book'] = relation(OldBook, backref='songs')
        # Map the rest of the tables
        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()
        if self.import_wizard:
            self.import_wizard.progress_bar.setMaximum(len(source_songs))
        for song in source_songs:
            new_song = Song()
            new_song.title = song.title
            if has_media_files and hasattr(song, 'alternate_title'):
                new_song.alternate_title = song.alternate_title
            else:
                old_titles = song.search_title.split('@')
                if len(old_titles) > 1:
                    new_song.alternate_title = old_titles[1]
            # Transfer the values to the new song object
            new_song.search_title = ''
            new_song.search_lyrics = ''
            new_song.lyrics = song.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 hasattr(song, 'song_number') and song.song_number:
                new_song.song_number = song.song_number
            # Find or create all the authors and add them to the new song object
            for author in song.authors:
                existing_author = self.manager.get_object_filtered(Author, Author.display_name == author.display_name)
                if not existing_author:
                    existing_author = Author.populate(
                        first_name=author.first_name,
                        last_name=author.last_name,
                        display_name=author.display_name)
                new_song.add_author(existing_author)
            # Find or create all the topics and add them to the new song object
            if song.topics:
                for topic in song.topics:
                    existing_topic = self.manager.get_object_filtered(Topic, Topic.name == topic.name)
                    if not existing_topic:
                        existing_topic = Topic.populate(name=topic.name)
                    new_song.topics.append(existing_topic)
            # Find or create all the songbooks and add them to the new song object
            if has_songs_books and song.songbook_entries:
                for entry in song.songbook_entries:
                    existing_book = self.manager.get_object_filtered(Book, Book.name == entry.songbook.name)
                    if not existing_book:
                        existing_book = Book.populate(name=entry.songbook.name, publisher=entry.songbook.publisher)
                    new_song.add_songbook_entry(existing_book, entry.entry)
            elif song.book:
                existing_book = self.manager.get_object_filtered(Book, Book.name == song.book.name)
                if not existing_book:
                    existing_book = Book.populate(name=song.book.name, publisher=song.book.publisher)
                new_song.add_songbook_entry(existing_book, '')
            # Find or create all the media files and add them to the new song object
            if has_media_files and song.media_files:
                for media_file in song.media_files:
                    existing_media_file = self.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))
            clean_song(self.manager, new_song)
            self.manager.save_object(new_song)
            if progress_dialog:
                progress_dialog.setValue(progress_dialog.value() + 1)
                # TODO: Verify format() with template strings
                progress_dialog.setLabelText(WizardStrings.ImportingType % new_song.title)
            else:
                # TODO: Verify format() with template strings
                self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % new_song.title)
            if self.stop_import_flag:
                break
        self.source_session.close()
        engine.dispose()
Beispiel #14
0
 def finish(self):
     """
     All fields have been set to this song. Write the song to disk.
     """
     if not self.checkComplete():
         self.setDefaults()
         return False
     log.info('committing song %s to database', self.title)
     song = Song()
     song.title = self.title
     if self.import_wizard is not None:
         self.import_wizard.increment_progress_bar(WizardStrings.ImportingType % song.title)
     song.alternate_title = self.alternate_title
     # Values will be set when cleaning the song.
     song.search_title = ''
     song.search_lyrics = ''
     song.verse_order = ''
     song.song_number = self.songNumber
     verses_changed_to_other = {}
     sxml = SongXML()
     other_count = 1
     for (verse_def, verse_text, lang) in self.verses:
         if verse_def[0].lower() in VerseType.tags:
             verse_tag = verse_def[0].lower()
         else:
             new_verse_def = '%s%d' % (VerseType.tags[VerseType.Other], other_count)
             verses_changed_to_other[verse_def] = new_verse_def
             other_count += 1
             verse_tag = VerseType.tags[VerseType.Other]
             log.info('Versetype %s changing to %s', verse_def, new_verse_def)
             verse_def = new_verse_def
         sxml.add_verse_to_lyrics(verse_tag, verse_def[1:], verse_text, lang)
     song.lyrics = str(sxml.extract_xml(), 'utf-8')
     if not self.verseOrderList and self.verseOrderListGeneratedUseful:
         self.verseOrderList = self.verseOrderListGenerated
     self.verseOrderList = [verses_changed_to_other.get(v, v) for v in self.verseOrderList]
     song.verse_order = ' '.join(self.verseOrderList)
     song.copyright = self.copyright
     song.comments = self.comments
     song.theme_name = self.themeName
     song.ccli_number = self.ccliNumber
     for authortext in self.authors:
         author = self.manager.get_object_filtered(Author, Author.display_name == authortext)
         if not author:
             author = Author.populate(display_name=authortext,
                 last_name=authortext.split(' ')[-1],
                 first_name=' '.join(authortext.split(' ')[:-1]))
         song.authors.append(author)
     if self.songBookName:
         song_book = self.manager.get_object_filtered(Book, Book.name == self.songBookName)
         if song_book is None:
             song_book = Book.populate(name=self.songBookName, publisher=self.songBookPub)
         song.book = song_book
     for topictext in self.topics:
         if not topictext:
             continue
         topic = self.manager.get_object_filtered(Topic, Topic.name == topictext)
         if topic is None:
             topic = Topic.populate(name=topictext)
         song.topics.append(topic)
     # We need to save the song now, before adding the media files, so that
     # we know where to save the media files to.
     clean_song(self.manager, song)
     self.manager.save_object(song)
     # Now loop through the media files, copy them to the correct location,
     # and save the song again.
     for filename, weight in self.mediaFiles:
         media_file = self.manager.get_object_filtered(MediaFile, MediaFile.file_name == filename)
         if not media_file:
             if os.path.dirname(filename):
                 filename = self.copyMediaFile(song.id, filename)
             song.media_files.append(MediaFile.populate(file_name=filename, weight=weight))
     self.manager.save_object(song)
     self.setDefaults()
     return True
Beispiel #15
0
    def do_import(self, progress_dialog=None):
        """
        Run the import for an OpenLP version 2 song database.

        :param progress_dialog: The QProgressDialog used when importing songs from the FRW.
        """
        class OldAuthorSong(BaseModel):
            """
            Maps to the authors_songs table
            """
            pass

        class OldAuthor(BaseModel):
            """
            Maps to the authors table
            """
            pass

        class OldBook(BaseModel):
            """
            Maps to the songbooks table
            """
            pass

        class OldMediaFile(BaseModel):
            """
            Maps to the media_files table
            """
            pass

        class OldSong(BaseModel):
            """
            Maps to the songs table
            """
            pass

        class OldTopic(BaseModel):
            """
            Maps to the topics table
            """
            pass

        class OldSongBookEntry(BaseModel):
            """
            Maps to the songs_songbooks table
            """
            pass

        # Check the file type
        if self.import_source.suffix != '.sqlite':
            self.log_error(
                self.import_source,
                translate('SongsPlugin.OpenLPSongImport',
                          'Not a valid OpenLP 2 song database.'))
            return
        self.import_source = 'sqlite:///{url}'.format(url=self.import_source)
        # Load the db file and reflect it
        engine = create_engine(self.import_source)
        source_meta = MetaData()
        source_meta.reflect(engine)
        self.source_session = scoped_session(sessionmaker(bind=engine))
        # Run some checks to see which version of the database we have
        table_list = list(source_meta.tables.keys())
        if 'media_files' in table_list:
            has_media_files = True
        else:
            has_media_files = False
        if 'songs_songbooks' in table_list:
            has_songs_books = True
        else:
            has_songs_books = False
        if 'authors_songs' in table_list:
            has_authors_songs = True
        else:
            has_authors_songs = False
        # Load up the tabls and map them out
        try:
            source_authors_table = source_meta.tables['authors']
            source_song_books_table = source_meta.tables['song_books']
            source_songs_table = source_meta.tables['songs']
            source_topics_table = source_meta.tables['topics']
            source_authors_songs_table = source_meta.tables['authors_songs']
            source_songs_topics_table = source_meta.tables['songs_topics']
            source_media_files_songs_table = None
        except KeyError:
            self.log_error(
                self.import_source,
                translate('SongsPlugin.OpenLPSongImport',
                          'Not a valid OpenLP 2 song database.'))
            return
        # Set up media_files relations
        if has_media_files:
            source_media_files_table = source_meta.tables['media_files']
            source_media_files_songs_table = source_meta.tables.get(
                'media_files_songs')
            try:
                class_mapper(OldMediaFile)
            except UnmappedClassError:
                mapper(OldMediaFile, source_media_files_table)
        if has_songs_books:
            source_songs_songbooks_table = source_meta.tables[
                'songs_songbooks']
            try:
                class_mapper(OldSongBookEntry)
            except UnmappedClassError:
                mapper(OldSongBookEntry,
                       source_songs_songbooks_table,
                       properties={'songbook': relation(OldBook)})
        if has_authors_songs:
            try:
                class_mapper(OldAuthorSong)
            except UnmappedClassError:
                mapper(OldAuthorSong, source_authors_songs_table)
        if has_authors_songs and 'author_type' in source_authors_songs_table.c.keys(
        ):
            has_author_type = True
        else:
            has_author_type = False
        # Set up the songs relationships
        song_props = {
            'authors':
            relation(OldAuthor,
                     backref='songs',
                     secondary=source_authors_songs_table),
            'topics':
            relation(OldTopic,
                     backref='songs',
                     secondary=source_songs_topics_table)
        }
        if has_media_files:
            if isinstance(source_media_files_songs_table, Table):
                song_props['media_files'] = relation(
                    OldMediaFile,
                    backref='songs',
                    secondary=source_media_files_songs_table)
            else:
                song_props['media_files'] = \
                    relation(OldMediaFile, backref='songs',
                             foreign_keys=[source_media_files_table.c.song_id],
                             primaryjoin=source_songs_table.c.id == source_media_files_table.c.song_id)
        if has_songs_books:
            song_props['songbook_entries'] = relation(
                OldSongBookEntry, backref='song', cascade='all, delete-orphan')
        else:
            song_props['book'] = relation(OldBook, backref='songs')
        if has_authors_songs:
            song_props['authors_songs'] = relation(OldAuthorSong)
        # Map the rest of the tables
        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()
        if self.import_wizard:
            self.import_wizard.progress_bar.setMaximum(len(source_songs))
        for song in source_songs:
            new_song = Song()
            new_song.title = song.title
            if has_media_files and hasattr(song, 'alternate_title'):
                new_song.alternate_title = song.alternate_title
            else:
                old_titles = song.search_title.split('@')
                if len(old_titles) > 1:
                    new_song.alternate_title = old_titles[1]
            # Transfer the values to the new song object
            new_song.search_title = ''
            new_song.search_lyrics = ''
            new_song.lyrics = song.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 hasattr(song, 'song_number') and song.song_number:
                new_song.song_number = song.song_number
            # Find or create all the authors and add them to the new song object
            for author in song.authors:
                existing_author = self.manager.get_object_filtered(
                    Author, Author.display_name == author.display_name)
                if not existing_author:
                    existing_author = Author.populate(
                        first_name=author.first_name,
                        last_name=author.last_name,
                        display_name=author.display_name)
                # If this is a new database, we need to import the author_type too
                author_type = None
                if has_author_type:
                    for author_song in song.authors_songs:
                        if author_song.author_id == author.id:
                            author_type = author_song.author_type
                            break
                new_song.add_author(existing_author, author_type)
            # Find or create all the topics and add them to the new song object
            if song.topics:
                for topic in song.topics:
                    existing_topic = self.manager.get_object_filtered(
                        Topic, Topic.name == topic.name)
                    if not existing_topic:
                        existing_topic = Topic.populate(name=topic.name)
                    new_song.topics.append(existing_topic)
            # Find or create all the songbooks and add them to the new song object
            if has_songs_books and song.songbook_entries:
                for entry in song.songbook_entries:
                    existing_book = self.manager.get_object_filtered(
                        Book, Book.name == entry.songbook.name)
                    if not existing_book:
                        existing_book = Book.populate(
                            name=entry.songbook.name,
                            publisher=entry.songbook.publisher)
                    new_song.add_songbook_entry(existing_book, entry.entry)
            elif hasattr(song, 'book') and song.book:
                existing_book = self.manager.get_object_filtered(
                    Book, Book.name == song.book.name)
                if not existing_book:
                    existing_book = Book.populate(
                        name=song.book.name, publisher=song.book.publisher)
                # Get the song_number from "songs" table "song_number" field. (This is db structure from 2.2.1)
                # If there's a number, add it to the song, otherwise it will be "".
                existing_number = song.song_number if hasattr(
                    song, 'song_number') else ''
                if existing_number:
                    new_song.add_songbook_entry(existing_book, existing_number)
                else:
                    new_song.add_songbook_entry(existing_book, '')
            # Find or create all the media files and add them to the new song object
            if has_media_files and song.media_files:
                for media_file in song.media_files:
                    existing_media_file = self.manager.get_object_filtered(
                        MediaFile, MediaFile.file_path == media_file.file_path)
                    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))
            clean_song(self.manager, new_song)
            self.manager.save_object(new_song)
            if progress_dialog:
                progress_dialog.setValue(progress_dialog.value() + 1)
                progress_dialog.setLabelText(
                    WizardStrings.ImportingType.format(source=new_song.title))
            else:
                self.import_wizard.increment_progress_bar(
                    WizardStrings.ImportingType.format(source=new_song.title))
            if self.stop_import_flag:
                break
        self.source_session.close()
        engine.dispose()