Merged in song maintenance improvements.

bzr-revno: 854
This commit is contained in:
Raoul Snyman 2010-06-18 23:56:18 +02:00
commit 7beb4d4b84
4 changed files with 124 additions and 231 deletions

View File

@ -439,58 +439,58 @@ class Ui_EditSongDialog(object):
def retranslateUi(self, EditSongDialog):
EditSongDialog.setWindowTitle(
translate(u'SongsPlugin.EditSongForm', u'Song Editor'))
translate('SongsPlugin.EditSongForm', 'Song Editor'))
self.TitleLabel.setText(
translate(u'SongsPlugin.EditSongForm', u'Title:'))
translate('SongsPlugin.EditSongForm', '&Title:'))
self.AlternativeTitleLabel.setText(
translate(u'SongsPlugin.EditSongForm', u'Alternative Title:'))
translate('SongsPlugin.EditSongForm', 'Alt&ernative Title:'))
self.LyricsLabel.setText(
translate(u'SongsPlugin.EditSongForm', u'Lyrics:'))
translate('SongsPlugin.EditSongForm', '&Lyrics:'))
self.VerseOrderLabel.setText(
translate(u'SongsPlugin.EditSongForm', u'Verse Order:'))
translate('SongsPlugin.EditSongForm', '&Verse Order:'))
self.VerseAddButton.setText(
translate(u'SongsPlugin.EditSongForm', u'Add'))
translate('SongsPlugin.EditSongForm', '&Add'))
self.VerseEditButton.setText(
translate(u'SongsPlugin.EditSongForm', u'Edit'))
translate('SongsPlugin.EditSongForm', '&Edit'))
self.VerseEditAllButton.setText(
translate(u'SongsPlugin.EditSongForm', u'Edit All'))
translate('SongsPlugin.EditSongForm', 'Ed&it All'))
self.VerseDeleteButton.setText(
translate(u'SongsPlugin.EditSongForm', u'Delete'))
translate('SongsPlugin.EditSongForm', '&Delete'))
self.SongTabWidget.setTabText(
self.SongTabWidget.indexOf(self.LyricsTab),
translate(u'SongsPlugin.EditSongForm', u'Title && Lyrics'))
translate('SongsPlugin.EditSongForm', 'Title && Lyrics'))
self.AuthorsGroupBox.setTitle(
translate(u'SongsPlugin.EditSongForm', u'Authors'))
translate('SongsPlugin.EditSongForm', 'Authors'))
self.AuthorAddButton.setText(
translate(u'SongsPlugin.EditSongForm', u'&Add to Song'))
translate('SongsPlugin.EditSongForm', '&Add to Song'))
self.AuthorRemoveButton.setText(
translate(u'SongsPlugin.EditSongForm', u'&Remove'))
self.MaintenanceButton.setText(translate(u'SongsPlugin.EditSongForm',
u'&Manage Authors, Topics, Books'))
translate('SongsPlugin.EditSongForm', '&Remove'))
self.MaintenanceButton.setText(translate('SongsPlugin.EditSongForm',
'&Manage Authors, Topics, Books'))
self.TopicGroupBox.setTitle(
translate(u'SongsPlugin.EditSongForm', u'Topic'))
translate('SongsPlugin.EditSongForm', 'Topic'))
self.TopicAddButton.setText(
translate(u'SongsPlugin.EditSongForm', u'A&dd to Song'))
translate('SongsPlugin.EditSongForm', 'A&dd to Song'))
self.TopicRemoveButton.setText(
translate(u'SongsPlugin.EditSongForm', u'R&emove'))
translate('SongsPlugin.EditSongForm', 'R&emove'))
self.SongBookGroup.setTitle(
translate(u'SongsPlugin.EditSongForm', u'Song Book'))
translate('SongsPlugin.EditSongForm', 'Song Book'))
self.SongTabWidget.setTabText(
self.SongTabWidget.indexOf(self.AuthorsTab),
translate(u'SongsPlugin.EditSongForm', u'Authors, Topics && Book'))
translate('SongsPlugin.EditSongForm', 'Authors, Topics && Book'))
self.ThemeGroupBox.setTitle(
translate(u'SongsPlugin.EditSongForm', u'Theme'))
translate('SongsPlugin.EditSongForm', 'Theme'))
self.ThemeAddButton.setText(
translate(u'SongsPlugin.EditSongForm', u'Add a Theme'))
translate('SongsPlugin.EditSongForm', 'Add a &Theme'))
self.CopyrightGroupBox.setTitle(
translate(u'SongsPlugin.EditSongForm', u'Copyright Information'))
translate('SongsPlugin.EditSongForm', 'Copyright Information'))
self.CopyrightInsertButton.setText(
translate(u'SongsPlugin.EditSongForm', u'\xa9'))
translate('SongsPlugin.EditSongForm', u'\xa9'))
self.CCLILabel.setText(
translate(u'SongsPlugin.EditSongForm', u'CCLI Number:'))
translate('SongsPlugin.EditSongForm', 'CCLI Number:'))
self.CommentsGroupBox.setTitle(
translate(u'SongsPlugin.EditSongForm', u'Comments'))
translate('SongsPlugin.EditSongForm', 'Comments'))
self.SongTabWidget.setTabText(
self.SongTabWidget.indexOf(self.ThemeTab),
translate(u'SongsPlugin.EditSongForm',
u'Theme, Copyright Info && Comments'))
translate('SongsPlugin.EditSongForm',
'Theme, Copyright Info && Comments'))

View File

@ -30,7 +30,7 @@ from PyQt4 import QtCore, QtGui
from openlp.core.lib import SongXMLBuilder, SongXMLParser, Receiver, translate
from openlp.plugins.songs.forms import EditVerseForm
from openlp.plugins.songs.lib.models import Song
from openlp.plugins.songs.lib.models import Song, Author, Topic, Book
from editsongdialog import Ui_EditSongDialog
log = logging.getLogger(__name__)
@ -126,12 +126,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def loadAuthors(self):
authors = self.songmanager.get_authors()
authorsCompleter = QtGui.QCompleter(
[author.display_name for author in authors],
self.AuthorsSelectionComboItem)
authorsCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.AuthorsSelectionComboItem.setCompleter(authorsCompleter)
self.AuthorsSelectionComboItem.clear()
self.AuthorsSelectionComboItem.addItem(u'')
for author in authors:
row = self.AuthorsSelectionComboItem.count()
self.AuthorsSelectionComboItem.addItem(author.display_name)
@ -140,11 +136,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def loadTopics(self):
topics = self.songmanager.get_topics()
topicsCompleter = QtGui.QCompleter(
[topic.name for topic in topics], self.SongTopicCombo)
topicsCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.SongTopicCombo.setCompleter(topicsCompleter)
self.SongTopicCombo.clear()
self.SongTopicCombo.addItem(u'')
for topic in topics:
row = self.SongTopicCombo.count()
self.SongTopicCombo.addItem(topic.name)
@ -152,25 +145,16 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def loadBooks(self):
books = self.songmanager.get_books()
booksCompleter = QtGui.QCompleter(
[book.name for book in books], self.SongbookCombo)
booksCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.SongbookCombo.setCompleter(booksCompleter)
self.SongbookCombo.clear()
self.SongbookCombo.addItem(u' ')
self.SongbookCombo.addItem(u'')
for book in books:
row = self.SongbookCombo.count()
self.SongbookCombo.addItem(book.name)
self.SongbookCombo.setItemData(row, QtCore.QVariant(book.id))
def loadThemes(self, theme_list):
themesCompleter = QtGui.QCompleter(
[theme for theme in theme_list],
self.ThemeSelectionComboItem)
themesCompleter.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.ThemeSelectionComboItem.setCompleter(themesCompleter)
self.ThemeSelectionComboItem.clear()
self.ThemeSelectionComboItem.addItem(u' ')
self.ThemeSelectionComboItem.addItem(u'')
for theme in theme_list:
self.ThemeSelectionComboItem.addItem(theme)
@ -244,6 +228,9 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.VerseListWidget.clear()
self.VerseListWidget.setRowCount(0)
self.VerseListWidget.setColumnWidth(0, self.width)
# This is just because occasionally the lyrics come back as a "buffer"
if isinstance(self.song.lyrics, buffer):
self.song.lyrics = unicode(self.song.lyrics)
if self.song.lyrics.startswith(u'<?xml version='):
songXML = SongXMLParser(self.song.lyrics)
verseList = songXML.get_verses()
@ -299,13 +286,40 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def onAuthorAddButtonClicked(self):
item = int(self.AuthorsSelectionComboItem.currentIndex())
if item > -1:
text = unicode(self.AuthorsSelectionComboItem.currentText())
if item == 0 and text:
if QtGui.QMessageBox.question(self,
translate('SongsPlugin.EditSongForm', 'Add Author'),
translate('SongsPlugin.EditSongForm', 'This author does not '
'exist, do you want to add them?'),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
author = Author.populate(display_name=text)
self.songmanager.save_author(author)
self.song.authors.append(author)
author_item = QtGui.QListWidgetItem(unicode(author.display_name))
author_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id))
self.AuthorsListView.addItem(author_item)
self.loadAuthors()
self.AuthorsSelectionComboItem.setCurrentIndex(0)
else:
return
elif item > 0:
item_id = (self.AuthorsSelectionComboItem.itemData(item)).toInt()[0]
author = self.songmanager.get_author(item_id)
self.song.authors.append(author)
author_item = QtGui.QListWidgetItem(unicode(author.display_name))
author_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(author.id))
self.AuthorsListView.addItem(author_item)
self.AuthorsSelectionComboItem.setCurrentIndex(0)
else:
QtGui.QMessageBox.warning(self,
translate('SongsPlugin.EditSongForm', 'No Author Selected'),
translate('SongsPlugin.EditSongForm', 'You have not selected '
'a valid author. Either select an author from the list, '
'or type in a new author and click the "Add Author to '
'Song" button to add the new author.'),
QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
def onAuthorsListViewPressed(self):
if self.AuthorsListView.count() > 1:
@ -322,13 +336,40 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
def onTopicAddButtonClicked(self):
item = int(self.SongTopicCombo.currentIndex())
if item > -1:
text = unicode(self.SongTopicCombo.currentText())
if item == 0 and text:
if QtGui.QMessageBox.question(self,
translate('SongsPlugin.EditSongForm', 'Add Topic'),
translate('SongsPlugin.EditSongForm', 'This topic does not '
'exist, do you want to add it?'),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.No,
QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes:
topic = Topic.populate(name=text)
self.songmanager.save_topic(topic)
self.song.topics.append(topic)
topic_item = QtGui.QListWidgetItem(unicode(topic.name))
topic_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
self.TopicsListView.addItem(topic_item)
self.loadTopics()
self.SongTopicCombo.setCurrentIndex(0)
else:
return
elif item > 0:
item_id = (self.SongTopicCombo.itemData(item)).toInt()[0]
topic = self.songmanager.get_topic(item_id)
self.song.topics.append(topic)
topic_item = QtGui.QListWidgetItem(unicode(topic.name))
topic_item.setData(QtCore.Qt.UserRole, QtCore.QVariant(topic.id))
self.TopicsListView.addItem(topic_item)
self.SongTopicCombo.setCurrentIndex(0)
else:
QtGui.QMessageBox.warning(self,
translate('SongsPlugin.EditSongForm', 'No Topic Selected'),
translate('SongsPlugin.EditSongForm', 'You have not selected '
'a valid topic. Either select a topic from the list, or '
'type in a new topic and click the "Add Topic to Song" '
'button to add the new topic.'),
QtGui.QMessageBox.Ok, QtGui.QMessageBox.Ok)
def onTopicListViewPressed(self):
self.TopicRemoveButton.setEnabled(True)
@ -343,12 +384,27 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.TopicsListView.takeItem(row)
def onSongBookComboChanged(self, item):
if item == 0:
self.song.song_book_id = 0
else:
item = int(self.SongbookCombo.currentIndex())
text = unicode(self.SongbookCombo.currentText())
if item == 0 and text:
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)
self.songmanager.save_book(book)
self.song.book = book
self.loadBooks()
else:
return
elif item > 1:
item = int(self.SongbookCombo.currentIndex())
self.song.song_book_id = \
(self.SongbookCombo.itemData(item)).toInt()[0]
else:
self.song.song_book_id = 0
def onThemeComboChanged(self, item):
if item == 0:
@ -484,7 +540,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
else:
self.SongTabWidget.setCurrentIndex(0)
self.VerseOrderEdit.setFocus()
return False, translate(u'SongsPlugin.EditSongForm',
return False, translate(u'SongsPlugin.EditSongForm',
u'Invalid verse entry, values must be I,B,T,P,E,O,V,C '
u'followed by a number')
return True, u''

View File

@ -211,28 +211,28 @@ class Ui_SongMaintenanceDialog(object):
def retranslateUi(self, SongMaintenanceDialog):
SongMaintenanceDialog.setWindowTitle(
translate(u'SongsPlugin.SongMaintenanceForm', u'Song Maintenance'))
translate('SongsPlugin.SongMaintenanceForm', 'Song Maintenance'))
self.TypeListWidget.item(0).setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Authors'))
translate('SongsPlugin.SongMaintenanceForm', 'Authors'))
self.TypeListWidget.item(1).setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Topics'))
translate('SongsPlugin.SongMaintenanceForm', 'Topics'))
self.TypeListWidget.item(2).setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Books/Hymnals'))
translate('SongsPlugin.SongMaintenanceForm', 'Books/Hymnals'))
self.AuthorAddButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Add'))
translate('SongsPlugin.SongMaintenanceForm', '&Add'))
self.AuthorEditButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Edit'))
translate('SongsPlugin.SongMaintenanceForm', '&Edit'))
self.AuthorDeleteButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Delete'))
translate('SongsPlugin.SongMaintenanceForm', '&Delete'))
self.TopicAddButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Add'))
translate('SongsPlugin.SongMaintenanceForm', '&Add'))
self.TopicEditButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Edit'))
translate('SongsPlugin.SongMaintenanceForm', '&Edit'))
self.TopicDeleteButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Delete'))
translate('SongsPlugin.SongMaintenanceForm', '&Delete'))
self.BookAddButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Add'))
translate('SongsPlugin.SongMaintenanceForm', '&Add'))
self.BookEditButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Edit'))
translate('SongsPlugin.SongMaintenanceForm', '&Edit'))
self.BookDeleteButton.setText(
translate(u'SongsPlugin.SongMaintenanceForm', u'Delete'))
translate('SongsPlugin.SongMaintenanceForm', '&Delete'))

View File

@ -1,163 +0,0 @@
#!/usr/bin/env python
# -*- 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 #
###############################################################################
import os
import logging
import time
import subprocess
import codecs
if os.name == u'nt':
import win32api
import win32con
from win32com.client import Dispatch
from openlp.core.utils import AppLocation
from openlp.migration.display import *
from openlp.migration.migratefiles import *
from openlp.migration.migratebibles import *
from openlp.migration.migratesongs import *
###############################################################################
# For Windows, requires SQLite ODBC Driver to be installed
# (uses sqlite.exe and sqlite3.exe)
# http://www.ch-werner.de/sqliteodbc/
###############################################################################
logging.basicConfig(level=logging.DEBUG,
format=u'%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
datefmt=u'%m-%d %H:%M',
filename=u'openlp-migration.log',
filemode=u'w')
class Migration(object):
"""
A class to take care of the migration process.
"""
def __init__(self):
"""
Initialise the process.
"""
self.display = Display()
self.stime = time.strftime(u'%Y-%m-%d-%H%M%S', time.localtime())
self.display.output(u'OpenLp v1.9.0 Migration Utility Started')
def process(self):
"""
Perform the conversion.
"""
#MigrateFiles(self.display).process()
MigrateSongs(self.display).process()
MigrateBibles(self.display).process()
def move_log_file(self):
"""
Move the log file to a new location.
"""
fname = u'openlp-migration.log'
c = os.path.splitext(fname)
b = (c[0]+'-'+ unicode(self.stime) + c[1])
self.display.output(u'Logfile ' + b + u' generated')
self.display.output(u'Migration Utility Finished ')
os.rename(fname, b)
def convert_file(self, inname, outname):
"""
Convert a file from another encoding into UTF-8.
``inname``
The name of the file to be opened and converted.
``outname``
The output file name.
"""
infile = codecs.open(inname, u'r', encoding=u'CP1252')
writefile = codecs.open(outname, u'w', encoding=u'utf-8')
for line in infile:
writefile.write(line)
infile.close()
writefile.close()
def convert_sqlite2_to_3(self, olddb, newdb):
print u'Converting sqlite2 ' + olddb + ' to sqlite3 ' + newdb
if os.name == u'nt':
# we can't make this a raw unicode string as the \U within it
# causes much confusion
hKey = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE,
u'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\SQLite ODBC Driver')
value, type = win32api.RegQueryValueEx (hKey, u'UninstallString')
sqlitepath, temp = os.path.split(value)
sqliteexe = os.path.join(sqlitepath, u'sqlite.exe')
else:
sqliteexe = u'sqlite'
cmd = u'%s "%s" .dump' % (sqliteexe, olddb)
if os.name == u'nt':
subprocess.call(cmd, stdout=open(u'sqlite.dmp', u'w'))
else:
subprocess.call(cmd, stdout=open(u'sqlite.dmp', u'w'), shell=True)
self.convert_file(u'sqlite.dmp', u'sqlite3.dmp')
if os.name == u'nt':
sqlite3exe = os.path.join(sqlitepath, u'sqlite3.exe')
else:
sqlite3exe = u'sqlite3'
if os.path.isfile(newdb):
saveddb = newdb + self.stime
os.rename(newdb, saveddb)
cmd = '%s "%s"' % (sqlite3exe, newdb)
if os.name == u'nt':
subprocess.call(cmd, stdin=open(u'sqlite3.dmp', u'r'))
else:
subprocess.call(cmd, stdin=open(u'sqlite3.dmp', u'r'), shell=True)
os.remove(u'sqlite.dmp')
os.remove(u'sqlite3.dmp')
if __name__ == u'__main__':
mig = Migration()
newsongpath = AppLocation.get_section_data_path(u'songs')
newbiblepath = AppLocation.get_section_data_path(u'bibles')
if os.name == u'nt':
if not os.path.isdir(newsongpath):
os.makedirs(newsongpath)
if not os.path.isdir(newbiblepath):
os.makedirs(newbiblepath)
ALL_USERS_APPLICATION_DATA = 35
shell = Dispatch(u'Shell.Application')
folder = shell.Namespace(ALL_USERS_APPLICATION_DATA)
folderitem = folder.Self
oldsongdb = os.path.join(folderitem.path, u'openlp.org', u'Data', u'songs.olp')
oldbiblepath = os.path.join(folderitem.path, u'openlp.org', u'Data', u'Bibles')
else:
oldsongdb = os.path.join(newsongpath, u'songs.olp')
newsongdb = os.path.join(newsongpath, u'songs.sqlite')
mig.convert_sqlite2_to_3(oldsongdb, newsongdb)
files = os.listdir(oldbiblepath)
for file in files:
f = os.path.splitext(os.path.basename(file))[0]
if f != 'kjv': #kjv bible has an autoincrement key not supported in sqlite3
mig.convert_sqlite2_to_3(os.path.join(oldbiblepath, file),
os.path.join(newbiblepath, f + u'.sqlite'))
mig.process()
#mig.move_log_file()