openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #15567
[Merge] lp:~sfindlay/openlp/select-folder-powersong into lp:openlp
Samuel Findlay has proposed merging lp:~sfindlay/openlp/select-folder-powersong into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~sfindlay/openlp/select-folder-powersong/+merge/104915
Changes PowerSong importer to import a folder, rather than a selection of files. This involved implementing a getFolder method in core.ui.OpenLPWizard.
Rationale:
(1) PowerSong users always deal with their song databases as a whole, as a database folder. To ask them to select individual song files may be a foreign idea.
(2) Although PowerSong songs are stored in individual files, the filenames are unintelligible database IDs, not song titles. So there is no easy way for a user to pick and choose which songs to import anyway.
Test:
Download large PowerSong database of 1057 songs. 1050 should import successfully.
<https://docs.google.com/open?id=0B076ddXXPC2WUnA1VXZoY1FCVzA>
--
https://code.launchpad.net/~sfindlay/openlp/select-folder-powersong/+merge/104915
Your team OpenLP Core is requested to review the proposed merge of lp:~sfindlay/openlp/select-folder-powersong into lp:openlp.
=== modified file 'openlp/core/lib/ui.py'
--- openlp/core/lib/ui.py 2012-04-22 19:50:18 +0000
+++ openlp/core/lib/ui.py 2012-05-07 13:49:20 +0000
@@ -94,6 +94,7 @@
self.NewService = translate('OpenLP.Ui', 'New Service')
self.NewTheme = translate('OpenLP.Ui', 'New Theme')
self.NextTrack = translate('OpenLP.Ui', 'Next Track')
+ self.NFdSs = translate('OpenLP.Ui', 'No Folder Selected', 'Singular')
self.NFSs = translate('OpenLP.Ui', 'No File Selected', 'Singular')
self.NFSp = translate('OpenLP.Ui', 'No Files Selected', 'Plural')
self.NISs = translate('OpenLP.Ui', 'No Item Selected', 'Singular')
=== modified file 'openlp/core/ui/wizard.py'
--- openlp/core/ui/wizard.py 2012-05-03 12:50:10 +0000
+++ openlp/core/ui/wizard.py 2012-05-07 13:49:20 +0000
@@ -72,11 +72,14 @@
'importer, you will need to install the "python-sqlite" '
'module.')
OpenTypeFile = unicode(translate('OpenLP.Ui', 'Open %s File'))
+ OpenTypeFolder = unicode(translate('OpenLP.Ui', 'Open %s Folder'))
PercentSymbolFormat = unicode(translate('OpenLP.Ui', '%p%'))
Ready = translate('OpenLP.Ui', 'Ready.')
StartingImport = translate('OpenLP.Ui', 'Starting import...')
YouSpecifyFile = unicode(translate('OpenLP.Ui', 'You need to specify at '
'least one %s file to import from.', 'A file type e.g. OpenSong'))
+ YouSpecifyFolder = unicode(translate('OpenLP.Ui', 'You need to specify a '
+ '%s folder to import from.', 'A file type e.g. OpenSong'))
class OpenLPWizard(QtGui.QWizard):
@@ -254,7 +257,7 @@
The title of the dialog (unicode).
``editbox``
- A editbox (QLineEdit).
+ An editbox (QLineEdit).
``filters``
The file extension filters. It should contain the file description
@@ -265,11 +268,28 @@
if filters:
filters += u';;'
filters += u'%s (*)' % UiStrings().AllFiles
- filename = QtGui.QFileDialog.getOpenFileName(self, title,
+ filename = unicode(QtGui.QFileDialog.getOpenFileName(self, title,
os.path.dirname(SettingsManager.get_last_dir(
- self.plugin.settingsSection, 1)), filters)
+ self.plugin.settingsSection, 1)), filters))
if filename:
editbox.setText(filename)
SettingsManager.set_last_dir(self.plugin.settingsSection,
filename, 1)
+ def getFolder(self, title, editbox):
+ """
+ Opens a QFileDialog and saves the selected folder to the given editbox.
+
+ ``title``
+ The title of the dialog (unicode).
+
+ ``editbox``
+ An editbox (QLineEdit).
+ """
+ folder = unicode(QtGui.QFileDialog.getExistingDirectory(self, title,
+ os.path.dirname(SettingsManager.get_last_dir(
+ self.plugin.settingsSection, 1)), QtGui.QFileDialog.ShowDirsOnly))
+ if folder:
+ editbox.setText(folder)
+ SettingsManager.set_last_dir(self.plugin.settingsSection,
+ folder, 1)
=== modified file 'openlp/plugins/songs/forms/songexportform.py'
--- openlp/plugins/songs/forms/songexportform.py 2012-04-02 19:34:49 +0000
+++ openlp/plugins/songs/forms/songexportform.py 2012-05-07 13:49:20 +0000
@@ -363,11 +363,5 @@
Called when the *directoryButton* was clicked. Opens a dialog and writes
the path to *directoryLineEdit*.
"""
- path = unicode(QtGui.QFileDialog.getExistingDirectory(self,
- translate('SongsPlugin.ExportWizardForm',
- 'Select Destination Folder'),
- SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
- options=QtGui.QFileDialog.ShowDirsOnly))
- SettingsManager.set_last_dir(self.plugin.settingsSection, path, 1)
- self.directoryLineEdit.setText(path)
-
+ self.getFolder(translate('SongsPlugin.ExportWizardForm',
+ 'Select Destination Folder'), self.directoryLineEdit)
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py 2012-05-03 12:50:10 +0000
+++ openlp/plugins/songs/forms/songimportform.py 2012-05-07 13:49:20 +0000
@@ -28,6 +28,7 @@
The song import functions for OpenLP.
"""
import codecs
+import fnmatch
import logging
import os
@@ -105,6 +106,9 @@
QtCore.QObject.connect(self.openLP1BrowseButton,
QtCore.SIGNAL(u'clicked()'),
self.onOpenLP1BrowseButtonClicked)
+ QtCore.QObject.connect(self.powerSongBrowseButton,
+ QtCore.SIGNAL(u'clicked()'),
+ self.onPowerSongBrowseButtonClicked)
QtCore.QObject.connect(self.openLyricsAddButton,
QtCore.SIGNAL(u'clicked()'),
self.onOpenLyricsAddButtonClicked)
@@ -171,12 +175,6 @@
QtCore.QObject.connect(self.foilPresenterRemoveButton,
QtCore.SIGNAL(u'clicked()'),
self.onFoilPresenterRemoveButtonClicked)
- QtCore.QObject.connect(self.powerSongAddButton,
- QtCore.SIGNAL(u'clicked()'),
- self.onPowerSongAddButtonClicked)
- QtCore.QObject.connect(self.powerSongRemoveButton,
- QtCore.SIGNAL(u'clicked()'),
- self.onPowerSongRemoveButtonClicked)
def addCustomPages(self):
"""
@@ -224,7 +222,7 @@
# Open Song
self.addFileSelectItem(u'openSong', u'OpenSong')
# PowerSong
- self.addFileSelectItem(u'powerSong')
+ self.addFileSelectItem(u'powerSong', single_select=True)
# SongBeamer
self.addFileSelectItem(u'songBeamer')
# Song Show Plus
@@ -290,6 +288,9 @@
translate('SongsPlugin.ImportWizardForm', 'Filename:'))
self.openLP1BrowseButton.setText(UiStrings().Browse)
self.openLP1DisabledLabel.setText(WizardStrings.NoSqlite)
+ self.powerSongFilenameLabel.setText(
+ translate('SongsPlugin.ImportWizardForm', 'Folder:'))
+ self.powerSongBrowseButton.setText(UiStrings().Browse)
self.openLyricsAddButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.openLyricsRemoveButton.setText(
@@ -315,10 +316,6 @@
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.dreamBeamRemoveButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
- self.powerSongAddButton.setText(
- translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
- self.powerSongRemoveButton.setText(
- translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
self.songsOfFellowshipAddButton.setText(
translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
self.songsOfFellowshipRemoveButton.setText(
@@ -401,6 +398,14 @@
WizardStrings.YouSpecifyFile % UiStrings().OLPV1)
self.openLP1BrowseButton.setFocus()
return False
+ elif source_format == SongFormat.PowerSong:
+ if self.powerSongFilenameEdit.text().isEmpty() or \
+ not self.isPowerSongFolder(
+ self.powerSongFilenameEdit.text()):
+ critical_error_message_box(UiStrings().NFdSs,
+ WizardStrings.YouSpecifyFolder % WizardStrings.PS)
+ self.powerSongBrowseButton.setFocus()
+ return False
elif source_format == SongFormat.OpenLyrics:
if self.openLyricsFileListWidget.count() == 0:
critical_error_message_box(UiStrings().NFSp,
@@ -431,12 +436,6 @@
WizardStrings.YouSpecifyFile % WizardStrings.DB)
self.dreamBeamAddButton.setFocus()
return False
- elif source_format == SongFormat.PowerSong:
- if self.powerSongFileListWidget.count() == 0:
- critical_error_message_box(UiStrings().NFSp,
- WizardStrings.YouSpecifyFile % WizardStrings.PS)
- self.powerSongAddButton.setFocus()
- return False
elif source_format == SongFormat.SongsOfFellowship:
if self.songsOfFellowshipFileListWidget.count() == 0:
critical_error_message_box(UiStrings().NFSp,
@@ -485,6 +484,16 @@
elif self.currentPage() == self.progressPage:
return True
+ def isPowerSongFolder(self, dir):
+ """
+ Checks if a folder is a PowerSong 1.0 folder
+ """
+ if os.path.isdir(dir):
+ for file in os.listdir(dir):
+ if fnmatch.fnmatch(file, u'*.song'):
+ return True
+ return False
+
def getFiles(self, title, listbox, filters=u''):
"""
Opens a QFileDialog and writes the filenames to the given listbox.
@@ -546,6 +555,13 @@
'openlp.org v1.x Databases')
)
+ def onPowerSongBrowseButtonClicked(self):
+ """
+ Get PowerSong song database folder
+ """
+ self.getFolder(WizardStrings.OpenTypeFolder % WizardStrings.PS,
+ self.powerSongFilenameEdit)
+
def onOpenLyricsAddButtonClicked(self):
"""
Get OpenLyrics song database files
@@ -620,22 +636,6 @@
"""
self.removeSelectedItems(self.dreamBeamFileListWidget)
- def onPowerSongAddButtonClicked(self):
- """
- Get PowerSong song database files
- """
- self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.PS,
- self.powerSongFileListWidget, u'%s (*.song)'
- % translate('SongsPlugin.ImportWizardForm',
- 'PowerSong 1.0 Song Files')
- )
-
- def onPowerSongRemoveButtonClicked(self):
- """
- Remove selected PowerSong files from the import list
- """
- self.removeSelectedItems(self.powerSongFileListWidget)
-
def onSongsOfFellowshipAddButtonClicked(self):
"""
Get Songs of Fellowship song database files
@@ -748,12 +748,12 @@
self.formatComboBox.setCurrentIndex(last_import_type)
self.openLP2FilenameEdit.setText(u'')
self.openLP1FilenameEdit.setText(u'')
+ self.powerSongFilenameEdit.setText(u'')
self.openLyricsFileListWidget.clear()
self.openSongFileListWidget.clear()
self.wordsOfWorshipFileListWidget.clear()
self.ccliFileListWidget.clear()
self.dreamBeamFileListWidget.clear()
- self.powerSongFileListWidget.clear()
self.songsOfFellowshipFileListWidget.clear()
self.genericFileListWidget.clear()
self.easySlidesFilenameEdit.setText(u'')
@@ -794,6 +794,11 @@
filename=unicode(self.openLP1FilenameEdit.text()),
plugin=self.plugin
)
+ elif source_format == SongFormat.PowerSong:
+ # Import PowerSong folder
+ importer = self.plugin.importSongs(SongFormat.PowerSong,
+ filename=unicode(self.powerSongFilenameEdit.text())
+ )
elif source_format == SongFormat.OpenLyrics:
# Import OpenLyrics songs
importer = self.plugin.importSongs(SongFormat.OpenLyrics,
@@ -821,12 +826,6 @@
filenames=self.getListOfFiles(
self.dreamBeamFileListWidget)
)
- elif source_format == SongFormat.PowerSong:
- # Import PowerSong songs
- importer = self.plugin.importSongs(SongFormat.PowerSong,
- filenames=self.getListOfFiles(
- self.powerSongFileListWidget)
- )
elif source_format == SongFormat.SongsOfFellowship:
# Import a Songs of Fellowship RTF file
importer = self.plugin.importSongs(SongFormat.SongsOfFellowship,
=== modified file 'openlp/plugins/songs/lib/powersongimport.py'
--- openlp/plugins/songs/lib/powersongimport.py 2012-05-03 12:50:10 +0000
+++ openlp/plugins/songs/lib/powersongimport.py 2012-05-07 13:49:20 +0000
@@ -29,8 +29,11 @@
PowerSong songs into the OpenLP database.
"""
import logging
+import fnmatch
+import os
from openlp.core.lib import translate
+from openlp.core.ui.wizard import WizardStrings
from openlp.plugins.songs.lib.songimport import SongImport
log = logging.getLogger(__name__)
@@ -71,11 +74,22 @@
def doImport(self):
"""
- Receive a list of files to import.
+ Receive either a list of files or a folder (unicode) to import.
"""
- if not isinstance(self.importSource, list):
+ if isinstance(self.importSource, unicode):
+ if os.path.isdir(self.importSource):
+ dir = self.importSource
+ self.importSource = []
+ for file in os.listdir(dir):
+ if fnmatch.fnmatch(file, u'*.song'):
+ self.importSource.append(os.path.join(dir, file))
+ else:
+ self.importSource = u''
+ if not self.importSource or not isinstance(self.importSource, list):
self.logError(unicode(translate('SongsPlugin.PowerSongImport',
- 'No files to import.')))
+ 'No songs to import.')),
+ unicode(translate('SongsPlugin.PowerSongImport',
+ 'No %s files found.' % WizardStrings.PS)))
return
self.importWizard.progressBar.setMaximum(len(self.importSource))
for file in self.importSource:
@@ -92,9 +106,10 @@
field = self._readString(song_data)
except ValueError:
parse_error = True
- self.logError(file, unicode(
+ self.logError(os.path.basename(file), unicode(
translate('SongsPlugin.PowerSongImport',
- 'Invalid PowerSong file. Unexpected byte value.')))
+ 'Invalid %s file. Unexpected byte value.'
+ % WizardStrings.PS)))
break
else:
if label == u'TITLE':
@@ -110,26 +125,26 @@
continue
# Check that file had TITLE field
if not self.title:
- self.logError(file, unicode(
+ self.logError(os.path.basename(file), unicode(
translate('SongsPlugin.PowerSongImport',
- 'Invalid PowerSong file. Missing "TITLE" header.')))
+ 'Invalid %s file. Missing "TITLE" header.'
+ % WizardStrings.PS)))
continue
# Check that file had COPYRIGHTLINE label
if not found_copyright:
- self.logError(file, unicode(
+ self.logError(self.title, unicode(
translate('SongsPlugin.PowerSongImport',
- '"%s" Invalid PowerSong file. Missing "COPYRIGHTLINE" '
- 'header.' % self.title)))
+ 'Invalid %s file. Missing "COPYRIGHTLINE" '
+ 'header.' % WizardStrings.PS)))
continue
# Check that file had at least one verse
if not self.verses:
- self.logError(file, unicode(
+ self.logError(self.title, unicode(
translate('SongsPlugin.PowerSongImport',
- '"%s" Verses not found. Missing "PART" header.'
- % self.title)))
+ 'Verses not found. Missing "PART" header.')))
continue
if not self.finish():
- self.logError(file)
+ self.logError(self.title)
def _readString(self, file_object):
"""
Follow ups