From bf4dcdde925eec005a0ec3988591abacd5f25333 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Mon, 7 May 2012 20:36:39 +1000 Subject: [PATCH 01/12] Added getFolder to OpenLPWizard --- openlp/core/ui/wizard.py | 23 +++++++++++++++++--- openlp/plugins/songs/forms/songexportform.py | 10 ++------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index 500d958fd..5f81e670d 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -254,7 +254,7 @@ class OpenLPWizard(QtGui.QWizard): 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 +265,28 @@ class OpenLPWizard(QtGui.QWizard): 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) \ No newline at end of file diff --git a/openlp/plugins/songs/forms/songexportform.py b/openlp/plugins/songs/forms/songexportform.py index 397b52cfc..dcca098dc 100644 --- a/openlp/plugins/songs/forms/songexportform.py +++ b/openlp/plugins/songs/forms/songexportform.py @@ -363,11 +363,5 @@ class SongExportForm(OpenLPWizard): 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) From 28d9a057319e947f5526dbdff914be88bc1e76d3 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Mon, 7 May 2012 21:24:46 +1000 Subject: [PATCH 02/12] Adapted all PowerSong import widgets for select folder --- openlp/core/lib/ui.py | 1 + openlp/core/ui/wizard.py | 3 + openlp/plugins/songs/forms/songimportform.py | 66 ++++++++------------ 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/openlp/core/lib/ui.py b/openlp/core/lib/ui.py index c4b1181b1..c0472cce8 100644 --- a/openlp/core/lib/ui.py +++ b/openlp/core/lib/ui.py @@ -94,6 +94,7 @@ class UiStrings(object): 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') diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index 5f81e670d..7382fb7e0 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -72,11 +72,14 @@ class WizardStrings(object): '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): diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index d5f7715ea..063efe34e 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -105,6 +105,9 @@ class SongImportForm(OpenLPWizard): 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 +174,6 @@ class SongImportForm(OpenLPWizard): 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 +221,7 @@ class SongImportForm(OpenLPWizard): # 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 +287,9 @@ class SongImportForm(OpenLPWizard): 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 +315,6 @@ class SongImportForm(OpenLPWizard): 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 +397,12 @@ class SongImportForm(OpenLPWizard): WizardStrings.YouSpecifyFile % UiStrings().OLPV1) self.openLP1BrowseButton.setFocus() return False + elif source_format == SongFormat.PowerSong: + if self.powerSongFilenameEdit.text().isEmpty(): + 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 +433,6 @@ class SongImportForm(OpenLPWizard): 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, @@ -546,6 +542,13 @@ class SongImportForm(OpenLPWizard): '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 +623,6 @@ class SongImportForm(OpenLPWizard): """ 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 +735,12 @@ class SongImportForm(OpenLPWizard): 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 +781,11 @@ class SongImportForm(OpenLPWizard): 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 +813,6 @@ class SongImportForm(OpenLPWizard): 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, From 3483231a3217521cccc3ea723dd4cb404a130134 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Mon, 7 May 2012 23:10:26 +1000 Subject: [PATCH 03/12] Adapted PowerSongImport class to receive a folder --- openlp/plugins/songs/forms/songimportform.py | 3 +- openlp/plugins/songs/lib/powersongimport.py | 44 +++++++++++++------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 063efe34e..cf9b876bb 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -398,7 +398,8 @@ class SongImportForm(OpenLPWizard): self.openLP1BrowseButton.setFocus() return False elif source_format == SongFormat.PowerSong: - if self.powerSongFilenameEdit.text().isEmpty(): + if self.powerSongFilenameEdit.text().isEmpty() or \ + not os.path.isdir(self.powerSongFilenameEdit.text()): critical_error_message_box(UiStrings().NFdSs, WizardStrings.YouSpecifyFolder % WizardStrings.PS) self.powerSongBrowseButton.setFocus() diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index 31491398c..901aaa737 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -29,8 +29,12 @@ The :mod:`powersongimport` module provides the functionality for importing PowerSong songs into the OpenLP database. """ import logging +import glob +import os +import fnmatch 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 +75,22 @@ class PowerSongImport(SongImport): 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 +107,10 @@ class PowerSongImport(SongImport): 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 +126,26 @@ class PowerSongImport(SongImport): 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): """ From 31debbe23840a8d1ad57aa3e3a300acab5f213a4 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Mon, 7 May 2012 23:26:52 +1000 Subject: [PATCH 04/12] Improved PowerSong import wizard validation --- openlp/plugins/songs/forms/songimportform.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index cf9b876bb..8428daa70 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -28,6 +28,7 @@ The song import functions for OpenLP. """ import codecs +import fnmatch import logging import os @@ -399,7 +400,8 @@ class SongImportForm(OpenLPWizard): return False elif source_format == SongFormat.PowerSong: if self.powerSongFilenameEdit.text().isEmpty() or \ - not os.path.isdir(self.powerSongFilenameEdit.text()): + not self.isPowerSongFolder( + self.powerSongFilenameEdit.text()): critical_error_message_box(UiStrings().NFdSs, WizardStrings.YouSpecifyFolder % WizardStrings.PS) self.powerSongBrowseButton.setFocus() @@ -482,6 +484,16 @@ class SongImportForm(OpenLPWizard): 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. From a03af240dfa1a0bfe30544852a8c4002b5123e9a Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Mon, 7 May 2012 23:38:02 +1000 Subject: [PATCH 05/12] Minor fixes --- openlp/core/ui/wizard.py | 2 +- openlp/plugins/songs/lib/powersongimport.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/openlp/core/ui/wizard.py b/openlp/core/ui/wizard.py index 7382fb7e0..0b4e8ec37 100644 --- a/openlp/core/ui/wizard.py +++ b/openlp/core/ui/wizard.py @@ -292,4 +292,4 @@ class OpenLPWizard(QtGui.QWizard): if folder: editbox.setText(folder) SettingsManager.set_last_dir(self.plugin.settingsSection, - folder, 1) \ No newline at end of file + folder, 1) diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index 901aaa737..b80cf4497 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -29,9 +29,8 @@ The :mod:`powersongimport` module provides the functionality for importing PowerSong songs into the OpenLP database. """ import logging -import glob -import os import fnmatch +import os from openlp.core.lib import translate from openlp.core.ui.wizard import WizardStrings From cdd867a755c80575e2f0f161f6a4b89f2015483b Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sat, 19 May 2012 20:43:19 +1000 Subject: [PATCH 06/12] Added static method isValidSource so importers can validate their input. Also tidyup: removed SongImport.errorLog --- openlp/plugins/songs/forms/songimportform.py | 23 +++++--------------- openlp/plugins/songs/lib/powersongimport.py | 15 +++++++++++++ openlp/plugins/songs/lib/songimport.py | 13 +++++++++-- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 8428daa70..17c854791 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -386,6 +386,7 @@ class SongImportForm(OpenLPWizard): source_format = self.formatComboBox.currentIndex() QtCore.QSettings().setValue(u'songs/last import type', source_format) + import_class = SongFormat.get_class(source_format) if source_format == SongFormat.OpenLP2: if self.openLP2FilenameEdit.text().isEmpty(): critical_error_message_box(UiStrings().NFSs, @@ -400,8 +401,8 @@ class SongImportForm(OpenLPWizard): return False elif source_format == SongFormat.PowerSong: if self.powerSongFilenameEdit.text().isEmpty() or \ - not self.isPowerSongFolder( - self.powerSongFilenameEdit.text()): + not import_class.isValidSource( + folder=self.powerSongFilenameEdit.text()): critical_error_message_box(UiStrings().NFdSs, WizardStrings.YouSpecifyFolder % WizardStrings.PS) self.powerSongBrowseButton.setFocus() @@ -484,16 +485,6 @@ class SongImportForm(OpenLPWizard): 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. @@ -797,7 +788,7 @@ class SongImportForm(OpenLPWizard): elif source_format == SongFormat.PowerSong: # Import PowerSong folder importer = self.plugin.importSongs(SongFormat.PowerSong, - filename=unicode(self.powerSongFilenameEdit.text()) + folder=unicode(self.powerSongFilenameEdit.text()) ) elif source_format == SongFormat.OpenLyrics: # Import OpenLyrics songs @@ -863,11 +854,7 @@ class SongImportForm(OpenLPWizard): filenames=self.getListOfFiles(self.foilPresenterFileListWidget) ) importer.doImport() - if importer.errorLog: - self.progressLabel.setText(translate( - 'SongsPlugin.SongImportForm', 'Your song import failed.')) - else: - self.progressLabel.setText(WizardStrings.FinishedImport) + self.progressLabel.setText(WizardStrings.FinishedImport) def onErrorCopyToButtonClicked(self): """ diff --git a/openlp/plugins/songs/lib/powersongimport.py b/openlp/plugins/songs/lib/powersongimport.py index b80cf4497..9946d273d 100644 --- a/openlp/plugins/songs/lib/powersongimport.py +++ b/openlp/plugins/songs/lib/powersongimport.py @@ -72,6 +72,21 @@ class PowerSongImport(SongImport): * .song """ + @staticmethod + def isValidSource(**kwargs): + """ + Checks if source is a PowerSong 1.0 folder: + * is a directory + * contains at least one *.song file + """ + if u'folder' in kwargs: + dir = kwargs[u'folder'] + if os.path.isdir(dir): + for file in os.listdir(dir): + if fnmatch.fnmatch(file, u'*.song'): + return True + return False + def doImport(self): """ Receive either a list of files or a folder (unicode) to import. diff --git a/openlp/plugins/songs/lib/songimport.py b/openlp/plugins/songs/lib/songimport.py index 9bfdce124..ac6818184 100644 --- a/openlp/plugins/songs/lib/songimport.py +++ b/openlp/plugins/songs/lib/songimport.py @@ -50,6 +50,13 @@ class SongImport(QtCore.QObject): whether the authors etc already exist and add them or refer to them as necessary """ + @staticmethod + def isValidSource(**kwargs): + """ + Override this method to validate the source prior to import. + """ + pass + def __init__(self, manager, **kwargs): """ Initialise and create defaults for properties @@ -65,14 +72,16 @@ class SongImport(QtCore.QObject): self.importSource = kwargs[u'filename'] elif u'filenames' in kwargs: self.importSource = kwargs[u'filenames'] + elif u'folder' in kwargs: + self.importSource = kwargs[u'folder'] else: - raise KeyError(u'Keyword arguments "filename[s]" not supplied.') + raise KeyError( + u'Keyword arguments "filename[s]" or "folder" not supplied.') log.debug(self.importSource) self.importWizard = None self.song = None self.stopImportFlag = False self.setDefaults() - self.errorLog = [] QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_stop_wizard'), self.stopImport) From e01995eafd5e2cc6fc2ee6b1846ee2641e965e07 Mon Sep 17 00:00:00 2001 From: Samuel Findlay Date: Sun, 20 May 2012 11:42:07 +1000 Subject: [PATCH 07/12] Tidy up --- openlp/plugins/songs/forms/songimportform.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openlp/plugins/songs/forms/songimportform.py b/openlp/plugins/songs/forms/songimportform.py index 17c854791..4bdabd1a2 100644 --- a/openlp/plugins/songs/forms/songimportform.py +++ b/openlp/plugins/songs/forms/songimportform.py @@ -28,7 +28,6 @@ The song import functions for OpenLP. """ import codecs -import fnmatch import logging import os From 9fa14f3e3ab9ebcef372fd51d09994874634b369 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sun, 20 May 2012 17:52:21 +0200 Subject: [PATCH 08/12] attempt to fix bug 923496 Fixes: https://launchpad.net/bugs/923496 --- openlp/core/__init__.py | 3 ++- openlp/core/ui/mainwindow.py | 18 +++++++++++++----- openlp/core/ui/slidecontroller.py | 4 ++-- openlp/core/utils/__init__.py | 3 +-- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 71c27a1d0..c26757535 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -127,7 +127,7 @@ class OpenLP(QtGui.QApplication): # make sure Qt really display the splash screen self.processEvents() # start the main app window - self.mainWindow = MainWindow(self.clipboard(), self.args) + self.mainWindow = MainWindow(self) self.mainWindow.show() if show_splash: # now kill the splashscreen @@ -146,6 +146,7 @@ class OpenLP(QtGui.QApplication): Receiver.send_message(u'live_display_blank_check') self.mainWindow.appStartup() # Skip exec_() for gui tests + self.eventLoopIsActive = True if not testing: return self.exec_() diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index e4a4e1616..8e9d2be88 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -542,14 +542,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ log.info(u'MainWindow loaded') - def __init__(self, clipboard, arguments): + def __init__(self, parent): """ This constructor sets up the interface, the various managers, and the plugins. """ QtGui.QMainWindow.__init__(self) - self.clipboard = clipboard - self.arguments = arguments + self.parent = lambda: parent + self.clipboard = self.parent().clipboard() + self.arguments = self.parent().args # Set up settings sections for the main application # (not for use by plugins) self.uiSettingsSection = u'user interface' @@ -830,7 +831,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): translate('OpenLP.MainWindow', 'OpenLP Main Display Blanked'), translate('OpenLP.MainWindow', - 'The Main Display has been blanked out')) + 'The Main Display has been blanked out')) def onErrorMessage(self, data): Receiver.send_message(u'close_splash') @@ -1132,6 +1133,11 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ Hook to close the main window and display windows on exit """ + # The MainApplication did not even enter the event loop (this happens + # when OpenLP is not fully loaded). Just ignore the event. + if not hasattr(self.parent(), u'eventLoopIsActive'): + event.ignore() + return # If we just did a settings import, close without saving changes. if self.settingsImported: event.accept() @@ -1184,7 +1190,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): # Save settings self.saveSettings() # Close down the display - self.liveController.display.close() + if self.liveController.display: + self.liveController.display.close() + self.liveController.display = None def serviceChanged(self, reset=False, serviceName=None): """ diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 1dc005aa6..66e0c6515 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -73,6 +73,7 @@ class Controller(QtGui.QWidget): controller = self Receiver.send_message('%s' % sender, [controller, args]) + class SlideController(Controller): """ SlideController is the slide controller widget. This widget is what the @@ -577,8 +578,7 @@ class SlideController(Controller): # rebuild display as screen size changed if self.display: self.display.close() - self.display = MainDisplay(self, self.imageManager, self.isLive, - self) + self.display = MainDisplay(self, self.imageManager, self.isLive, self) self.display.setup() if self.isLive: self.__addActionsToWidget(self.display) diff --git a/openlp/core/utils/__init__.py b/openlp/core/utils/__init__.py index 9d00e22b7..f73237c06 100644 --- a/openlp/core/utils/__init__.py +++ b/openlp/core/utils/__init__.py @@ -34,7 +34,6 @@ import os import re from subprocess import Popen, PIPE import sys -import time import urllib2 from PyQt4 import QtGui, QtCore @@ -69,7 +68,7 @@ class VersionThread(QtCore.QThread): """ Run the thread. """ - time.sleep(1) + self.sleep(1) app_version = get_application_version() version = check_latest_version(app_version) if LooseVersion(str(version)) > LooseVersion(str(app_version[u'full'])): From 1c57abf8abef22a24bc6e88e1b1f56f7f1970cbf Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Sun, 20 May 2012 22:56:11 +0200 Subject: [PATCH 09/12] Refactored ScreenList into a true Pythonic singleton, though I sadly had to go with a "create" classmethod in order to retain the functionality of the previous constructor.. --- openlp/core/__init__.py | 2 +- openlp/core/lib/dockwidget.py | 2 +- openlp/core/lib/imagemanager.py | 4 +-- openlp/core/lib/renderer.py | 2 +- openlp/core/ui/generaltab.py | 2 +- openlp/core/ui/maindisplay.py | 2 +- openlp/core/ui/mainwindow.py | 2 +- openlp/core/ui/screen.py | 42 +++++++++++++++++-------------- openlp/core/ui/slidecontroller.py | 2 +- 9 files changed, 32 insertions(+), 28 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 71c27a1d0..d40d7c758 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -109,7 +109,7 @@ class OpenLP(QtGui.QApplication): QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'cursor_normal'), self.setNormalCursor) # Decide how many screens we have and their size - screens = ScreenList(self.desktop()) + screens = ScreenList.create(self.desktop()) # First time checks in settings has_run_wizard = QtCore.QSettings().value( u'general/has run wizard', QtCore.QVariant(False)).toBool() diff --git a/openlp/core/lib/dockwidget.py b/openlp/core/lib/dockwidget.py index e08b5eee5..23ce9efcb 100644 --- a/openlp/core/lib/dockwidget.py +++ b/openlp/core/lib/dockwidget.py @@ -52,7 +52,7 @@ class OpenLPDockWidget(QtGui.QDockWidget): if icon: self.setWindowIcon(build_icon(icon)) # Sort out the minimum width. - screens = ScreenList.get_instance() + screens = ScreenList() mainwindow_docbars = screens.current[u'size'].width() / 5 if mainwindow_docbars > 300: self.setMinimumWidth(300) diff --git a/openlp/core/lib/imagemanager.py b/openlp/core/lib/imagemanager.py index b32e36194..47a7ed3f6 100644 --- a/openlp/core/lib/imagemanager.py +++ b/openlp/core/lib/imagemanager.py @@ -163,7 +163,7 @@ class ImageManager(QtCore.QObject): def __init__(self): QtCore.QObject.__init__(self) - current_screen = ScreenList.get_instance().current + current_screen = ScreenList().current self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() self._cache = {} @@ -177,7 +177,7 @@ class ImageManager(QtCore.QObject): Screen has changed size so rebuild the cache to new size. """ log.debug(u'update_display') - current_screen = ScreenList.get_instance().current + current_screen = ScreenList().current self.width = current_screen[u'size'].width() self.height = current_screen[u'size'].height() # Mark the images as dirty for a rebuild by setting the image and byte diff --git a/openlp/core/lib/renderer.py b/openlp/core/lib/renderer.py index 8694ca6b6..aa39e779b 100644 --- a/openlp/core/lib/renderer.py +++ b/openlp/core/lib/renderer.py @@ -69,7 +69,7 @@ class Renderer(object): log.debug(u'Initialisation started') self.themeManager = themeManager self.imageManager = imageManager - self.screens = ScreenList.get_instance() + self.screens = ScreenList() self.service_theme = u'' self.theme_level = u'' self.override_background = None diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index baf28f40f..d0647d829 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -42,7 +42,7 @@ class GeneralTab(SettingsTab): """ Initialise the general settings tab """ - self.screens = ScreenList.get_instance() + self.screens = ScreenList() self.iconPath = u':/icon/openlp-logo-16x16.png' generalTranslated = translate('OpenLP.GeneralTab', 'General') SettingsTab.__init__(self, parent, u'General', generalTranslated) diff --git a/openlp/core/ui/maindisplay.py b/openlp/core/ui/maindisplay.py index 15fb9eefe..a04203387 100644 --- a/openlp/core/ui/maindisplay.py +++ b/openlp/core/ui/maindisplay.py @@ -119,7 +119,7 @@ class MainDisplay(Display): def __init__(self, parent, imageManager, live, controller): Display.__init__(self, parent, live, controller) self.imageManager = imageManager - self.screens = ScreenList.get_instance() + self.screens = ScreenList() self.plugins = PluginManager.get_instance().plugins self.rebuildCSS = False self.hideMode = None diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index e4a4e1616..bff9203db 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -795,7 +795,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): if answer == QtGui.QMessageBox.No: return Receiver.send_message(u'cursor_busy') - screens = ScreenList.get_instance() + screens = ScreenList() FirstTimeForm(screens, self).exec_() self.firstTime() for plugin in self.pluginManager.plugins: diff --git a/openlp/core/ui/screen.py b/openlp/core/ui/screen.py index 21fbd6144..72c88908e 100644 --- a/openlp/core/ui/screen.py +++ b/openlp/core/ui/screen.py @@ -41,36 +41,40 @@ class ScreenList(object): """ Wrapper to handle the parameters of the display screen. - To get access to the screen list call ``ScreenList.get_instance()``. + To get access to the screen list call ``ScreenList()``. """ log.info(u'Screen loaded') - instance = None + __instance__ = None - @staticmethod - def get_instance(): - return ScreenList.instance + def __new__(cls): + if not cls.__instance__: + cls.__instance__ = object.__new__(cls) + return cls.__instance__ - def __init__(self, desktop): + @classmethod + def create(cls, desktop): """ Initialise the screen list. ``desktop`` A ``QDesktopWidget`` object. """ - ScreenList.instance = self - self.desktop = desktop - self.preview = None - self.current = None - self.override = None - self.screen_list = [] - self.display_count = 0 - self.screen_count_changed() - self._load_screen_settings() + screen_list = cls() + screen_list.desktop = desktop + screen_list.preview = None + screen_list.current = None + screen_list.override = None + screen_list.screen_list = [] + screen_list.display_count = 0 + screen_list.screen_count_changed() + screen_list._load_screen_settings() QtCore.QObject.connect(desktop, - QtCore.SIGNAL(u'resized(int)'), self.screen_resolution_changed) + QtCore.SIGNAL(u'resized(int)'), + screen_list.screen_resolution_changed) QtCore.QObject.connect(desktop, QtCore.SIGNAL(u'screenCountChanged(int)'), - self.screen_count_changed) + screen_list.screen_count_changed) + return screen_list def screen_resolution_changed(self, number): """ @@ -233,8 +237,8 @@ class ScreenList(object): y = window.y() + (window.height() / 2) for screen in self.screen_list: size = screen[u'size'] - if x >= size.x() and x <= (size.x() + size.width()) \ - and y >= size.y() and y <= (size.y() + size.height()): + if x >= size.x() and x <= (size.x() + size.width()) and \ + y >= size.y() and y <= (size.y() + size.height()): return screen[u'number'] def _load_screen_settings(self): diff --git a/openlp/core/ui/slidecontroller.py b/openlp/core/ui/slidecontroller.py index 1dc005aa6..99f2c8ad6 100644 --- a/openlp/core/ui/slidecontroller.py +++ b/openlp/core/ui/slidecontroller.py @@ -83,7 +83,7 @@ class SlideController(Controller): Set up the Slide Controller. """ Controller.__init__(self, parent, isLive) - self.screens = ScreenList.get_instance() + self.screens = ScreenList() try: self.ratio = float(self.screens.current[u'size'].width()) / \ float(self.screens.current[u'size'].height()) From 45c05e700d8ca0707ae40ec8db9e5c148b9f8749 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 23 May 2012 18:53:04 +0200 Subject: [PATCH 10/12] clean ups --- openlp/core/__init__.py | 3 ++- openlp/core/ui/mainwindow.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openlp/core/__init__.py b/openlp/core/__init__.py index 88f31b2ad..96520195d 100644 --- a/openlp/core/__init__.py +++ b/openlp/core/__init__.py @@ -91,6 +91,7 @@ class OpenLP(QtGui.QApplication): """ Override exec method to allow the shared memory to be released on exit """ + self.eventLoopIsActive = True QtGui.QApplication.exec_() self.sharedMemory.detach() @@ -98,6 +99,7 @@ class OpenLP(QtGui.QApplication): """ Run the OpenLP application. """ + self.eventLoopIsActive = False # On Windows, the args passed into the constructor are # ignored. Not very handy, so set the ones we want to use. self.args.extend(args) @@ -146,7 +148,6 @@ class OpenLP(QtGui.QApplication): Receiver.send_message(u'live_display_blank_check') self.mainWindow.appStartup() # Skip exec_() for gui tests - self.eventLoopIsActive = True if not testing: return self.exec_() diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 3b26820e9..6deb769af 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -549,8 +549,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ QtGui.QMainWindow.__init__(self) self.parent = lambda: parent - self.clipboard = self.parent().clipboard() - self.arguments = self.parent().args + self.clipboard = self.mainwindow().clipboard() + self.arguments = self.mainwindow().args # Set up settings sections for the main application # (not for use by plugins) self.uiSettingsSection = u'user interface' @@ -1135,7 +1135,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ # The MainApplication did not even enter the event loop (this happens # when OpenLP is not fully loaded). Just ignore the event. - if not hasattr(self.parent(), u'eventLoopIsActive'): + if not self.mainwindow().eventLoopIsActive: event.ignore() return # If we just did a settings import, close without saving changes. From 0517f3d8d7ca87868648343aa71f8eaad29a6211 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Wed, 23 May 2012 18:59:28 +0200 Subject: [PATCH 11/12] renamed attribute --- openlp/core/ui/mainwindow.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 6deb769af..20a2551d0 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -542,15 +542,15 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ log.info(u'MainWindow loaded') - def __init__(self, parent): + def __init__(self, application): """ This constructor sets up the interface, the various managers, and the plugins. """ QtGui.QMainWindow.__init__(self) - self.parent = lambda: parent - self.clipboard = self.mainwindow().clipboard() - self.arguments = self.mainwindow().args + self.application = lambda: application + self.clipboard = self.application().clipboard() + self.arguments = self.application().args # Set up settings sections for the main application # (not for use by plugins) self.uiSettingsSection = u'user interface' @@ -1135,7 +1135,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ # The MainApplication did not even enter the event loop (this happens # when OpenLP is not fully loaded). Just ignore the event. - if not self.mainwindow().eventLoopIsActive: + if not self.application().eventLoopIsActive: event.ignore() return # If we just did a settings import, close without saving changes. From 56b02b02b1ba4fd2b03e52e3c0f4765837c6f836 Mon Sep 17 00:00:00 2001 From: Andreas Preikschat Date: Sat, 26 May 2012 19:12:01 +0200 Subject: [PATCH 12/12] attribute instead of method --- openlp/core/ui/mainwindow.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openlp/core/ui/mainwindow.py b/openlp/core/ui/mainwindow.py index 20a2551d0..fe0d69c32 100644 --- a/openlp/core/ui/mainwindow.py +++ b/openlp/core/ui/mainwindow.py @@ -548,9 +548,9 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): plugins. """ QtGui.QMainWindow.__init__(self) - self.application = lambda: application - self.clipboard = self.application().clipboard() - self.arguments = self.application().args + self.application = application + self.clipboard = self.application.clipboard() + self.arguments = self.application.args # Set up settings sections for the main application # (not for use by plugins) self.uiSettingsSection = u'user interface' @@ -1135,7 +1135,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow): """ # The MainApplication did not even enter the event loop (this happens # when OpenLP is not fully loaded). Just ignore the event. - if not self.application().eventLoopIsActive: + if not self.application.eventLoopIsActive: event.ignore() return # If we just did a settings import, close without saving changes.