← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~whydoubt/openlp/importer_split into lp:openlp

 

Jeffrey Smith has proposed merging lp:~whydoubt/openlp/importer_split into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~whydoubt/openlp/importer_split/+merge/65915

Re-factor song import form, making it simpler to add a new importer
-- 
https://code.launchpad.net/~whydoubt/openlp/importer_split/+merge/65915
Your team OpenLP Core is requested to review the proposed merge of lp:~whydoubt/openlp/importer_split into lp:openlp.
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py	2011-06-20 21:57:34 +0000
+++ openlp/plugins/songs/forms/songimportform.py	2011-06-26 20:41:34 +0000
@@ -40,6 +40,317 @@
 
 log = logging.getLogger(__name__)
 
+class SongImportPage(object):
+    format = None
+    name = u''
+    obj_prefix = u''
+    single_select = False
+    can_disable = False
+    disable_text = u''
+    filters = u''
+    invalid_msg = None
+    get_files_title = None
+
+    def customInit(self):
+        if self.can_disable and not SongFormat.get_availability(self.format):
+            self.disabledWidget.setVisible(True)
+            self.importWidget.setVisible(False)
+
+    def customSignals(self):
+        if self.single_select:
+            QtCore.QObject.connect(self.browseButton,
+                QtCore.SIGNAL(u'clicked()'), self.onBrowseButtonClicked)
+        else:
+            QtCore.QObject.connect(self.addButton,
+                QtCore.SIGNAL(u'clicked()'), self.onAddButtonClicked)
+            QtCore.QObject.connect(self.removeButton,
+                QtCore.SIGNAL(u'clicked()'), self.onRemoveButtonClicked)
+    
+    def retranslateUi(self):
+        if self.single_select:
+            self.filenameLabel.setText(
+                translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+            self.browseButton.setText(UiStrings().Browse)
+        else:
+            self.addButton.setText(
+                translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
+            self.removeButton.setText(
+                translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
+        if self.can_disable:
+            self.disabledLabel.setText(self.disable_text)
+    
+    def validate(self):
+        if self.single_select:
+            valid = not self.filenameEdit.text().isEmpty()
+        else:
+            valid = self.fileListWidget.count() > 0
+        if not valid:
+            if self.single_select:
+                invalid_title = UiStrings().NFSs
+                new_focus = self.browseButton
+            else:
+                invalid_title = UiStrings().NFSp
+                new_focus = self.addButton
+            invalid_msg = self.invalid_msg
+            if invalid_msg is None:
+                invalid_msg = WizardStrings.YouSpecifyFile % self.name
+            critical_error_message_box(invalid_title, invalid_msg)
+            new_focus.setFocus()
+        return valid
+    
+    def setDefaults(self):
+        if self.single_select:
+            self.filenameEdit.setText(u'')
+        else:
+            self.fileListWidget.clear()
+
+    def getImporter(self):
+        if self.single_select:
+            return self.parent.plugin.importSongs(self.format,
+                filename=unicode(self.filenameEdit.text()))
+        else:
+            return self.parent.plugin.importSongs(self.format,
+                filenames=self.getListOfFiles(self.fileListWidget))
+
+    def addCustomPages(self, parent):
+        self.parent = parent
+        self.page = QtGui.QWidget()
+        self.page.setObjectName(self.obj_prefix + u'Page')
+        if self.can_disable:
+            self.disablableWidget()
+        else:
+            self.importWidget = self.page
+        self.importLayout = QtGui.QVBoxLayout(self.importWidget)
+        self.importLayout.setMargin(0)
+        self.importLayout.setObjectName(self.obj_prefix + u'ImportLayout')
+        if self.single_select:
+            self.fileLayout = QtGui.QHBoxLayout()
+            self.fileLayout.setObjectName(self.obj_prefix + u'FileLayout')
+            self.filenameLabel = QtGui.QLabel(self.importWidget)
+            self.filenameLabel.setObjectName(self.obj_prefix + u'FilenameLabel')
+            self.fileLayout.addWidget(self.filenameLabel)
+            self.filenameEdit = QtGui.QLineEdit(self.importWidget)
+            self.filenameEdit.setObjectName(self.obj_prefix + u'FilenameEdit')
+            self.fileLayout.addWidget(self.filenameEdit)
+            self.browseButton = QtGui.QToolButton(self.importWidget)
+            self.browseButton.setIcon(self.parent.openIcon)
+            self.browseButton.setObjectName(self.obj_prefix + u'BrowseButton')
+            self.fileLayout.addWidget(self.browseButton)
+            self.importLayout.addLayout(self.fileLayout)
+            self.importLayout.addSpacerItem(self.parent.stackSpacer)
+        else:
+            self.fileListWidget = QtGui.QListWidget(self.importWidget)
+            self.fileListWidget.setSelectionMode(
+                QtGui.QAbstractItemView.ExtendedSelection)
+            self.fileListWidget.setObjectName(
+                self.obj_prefix + u'FileListWidget')
+            self.importLayout.addWidget(self.fileListWidget)
+            self.buttonLayout = QtGui.QHBoxLayout()
+            self.buttonLayout.setObjectName(self.obj_prefix + u'ButtonLayout')
+            self.addButton = QtGui.QPushButton(self.importWidget)
+            self.addButton.setIcon(self.parent.openIcon)
+            self.addButton.setObjectName(self.obj_prefix + u'AddButton')
+            self.buttonLayout.addWidget(self.addButton)
+            self.buttonLayout.addStretch()
+            self.removeButton = QtGui.QPushButton(self.importWidget)
+            self.removeButton.setIcon(self.parent.deleteIcon)
+            self.removeButton.setObjectName(self.obj_prefix + u'RemoveButton')
+            self.buttonLayout.addWidget(self.removeButton)
+            self.importLayout.addLayout(self.buttonLayout)
+        self.parent.formatStack.addWidget(self.page)
+
+    def disablableWidget(self):
+        self.layout = QtGui.QVBoxLayout(self.page)
+        self.layout.setMargin(0)
+        self.layout.setSpacing(0)
+        self.layout.setObjectName(self.obj_prefix + u'Layout')
+        self.disabledWidget = QtGui.QWidget(self.page)
+        self.disabledWidget.setVisible(False)
+        self.disabledWidget.setObjectName(self.obj_prefix + u'DisabledWidget')
+        self.disabledLayout = QtGui.QVBoxLayout(self.disabledWidget)
+        self.disabledLayout.setMargin(0)
+        self.disabledLayout.setObjectName(self.obj_prefix + u'DisabledLayout')
+        self.disabledLabel = QtGui.QLabel(self.disabledWidget)
+        self.disabledLabel.setWordWrap(True)
+        self.disabledLabel.setObjectName(self.obj_prefix + u'DisabledLabel')
+        self.disabledLayout.addWidget(self.disabledLabel)
+        self.disabledLayout.addSpacerItem(self.parent.stackSpacer)
+        self.layout.addWidget(self.disabledWidget)
+        self.importWidget = QtGui.QWidget(self.page)
+        self.importWidget.setObjectName(self.obj_prefix + u'ImportWidget')
+        self.layout.addWidget(self.importWidget)
+
+    def getListOfFiles(self, listbox):
+        """
+        Return a list of file from the listbox
+        """
+        return [unicode(listbox.item(i).text()) for i in range(listbox.count())]
+
+    def onBrowseButtonClicked(self):
+        """
+        Get song database file
+        """
+        get_files_title = self.get_files_title
+        if get_files_title is None:
+            get_files_title = WizardStrings.OpenTypeFile % self.name
+        self.parent.getFileName(get_files_title, self.filenameEdit)
+
+    def onAddButtonClicked(self):
+        """
+        Get song files
+        """
+        get_files_title = self.get_files_title
+        if get_files_title is None:
+            get_files_title = WizardStrings.OpenTypeFile % self.name
+        filters = self.filters
+        if filters:
+            filters += u';;'
+        filters += u'%s (*)' % UiStrings().AllFiles
+        filenames = QtGui.QFileDialog.getOpenFileNames(self.parent,
+            get_files_title,
+            SettingsManager.get_last_dir(self.parent.plugin.settingsSection, 1),
+            filters)
+        if filenames:
+            self.fileListWidget.addItems(filenames)
+            SettingsManager.set_last_dir(self.parent.plugin.settingsSection,
+                os.path.split(unicode(filenames[0]))[0], 1)
+
+    def onRemoveButtonClicked(self):
+        """
+        Remove selected files from the import list
+        """
+        for item in self.fileListWidget.selectedItems():
+            item = self.fileListWidget.takeItem(self.fileListWidget.row(item))
+            del item
+
+
+class SongImportPage_OpenLP2(SongImportPage):
+    format = SongFormat.OpenLP2
+    name = UiStrings().OLPV2
+    obj_prefix = u'openLP2'
+    single_select = True
+    filters = u'%s (*.sqlite)' % translate('SongsPlugin.ImportWizardForm',
+        'OpenLP 2.0 Databases')
+
+class SongImportPage_OpenLP1(SongImportPage):
+    format = SongFormat.OpenLP1
+    name = UiStrings().OLPV1
+    obj_prefix = u'openLP1'
+    single_select = True
+    can_disable = True
+    disable_text = WizardStrings.NoSqlite
+    filters = u'%s (*.olp)' % translate('SongsPlugin.ImportWizardForm',
+        'openlp.org v1.x Databases')
+
+class SongImportPage_OpenLyrics(SongImportPage):
+    format = SongFormat.OpenLyrics
+    name = WizardStrings.OL
+    obj_prefix = u'OpenLyrics'
+
+class SongImportPage_OpenSong(SongImportPage):
+    format = SongFormat.OpenSong
+    name = WizardStrings.OS
+    obj_prefix = u'OpenSong'
+
+class SongImportPage_WordsOfWorship(SongImportPage):
+    format = SongFormat.WordsOfWorship
+    name = WizardStrings.WoW
+    obj_prefix = u'wordsOfWorship'
+    filters = u'%s (*.wsg *.wow-song)' \
+        % translate('SongsPlugin.ImportWizardForm',
+        'Words Of Worship Song Files')
+
+class SongImportPage_CCLI(SongImportPage):
+    format = SongFormat.CCLI
+    name = WizardStrings.CCLI
+    obj_prefix = u'ccli'
+
+class SongImportPage_SongsOfFellowship(SongImportPage):
+    format = SongFormat.SongsOfFellowship
+    name = WizardStrings.SoF
+    obj_prefix = u'songsOfFellowship'
+    can_disable = True
+    disable_text = \
+        translate('SongsPlugin.ImportWizardForm', 'The Songs of '
+        'Fellowship importer has been disabled because OpenLP cannot '
+        'access OpenOffice or LibreOffice.')
+    filters = u'%s (*.rtf)' % translate('SongsPlugin.ImportWizardForm',
+        'Songs Of Fellowship Song Files')
+
+class SongImportPage_Generic(SongImportPage):
+    format = SongFormat.Generic
+    name = translate('SongsPlugin.ImportWizardForm',
+        'Generic Document/Presentation')
+    obj_prefix = u'generic'
+    can_disable = True
+    disable_text = \
+        translate('SongsPlugin.ImportWizardForm', 'The generic document/'
+        'presentation importer has been disabled because OpenLP cannot '
+        'access OpenOffice or LibreOffice.')
+    invalid_msg = translate('SongsPlugin.ImportWizardForm',
+        'You need to specify at least one document or '
+        'presentation file to import from.')
+    get_files_title = translate('SongsPlugin.ImportWizardForm',
+        'Select Document/Presentation Files'),
+
+class SongImportPage_EasiSlides(SongImportPage):
+    format = SongFormat.EasiSlides
+    name = WizardStrings.ES
+    obj_prefix = u'easiSlides'
+    single_select = True
+
+class SongImportPage_EasyWorship(SongImportPage):
+    format = SongFormat.EasyWorship
+    name = WizardStrings.EW
+    obj_prefix = u'ew'
+    single_select = True
+
+class SongImportPage_SongBeamer(SongImportPage):
+    format = SongFormat.SongBeamer
+    name = WizardStrings.SB
+    obj_prefix = u'songBeamer'
+    filters = u'%s (*.sng)' % translate('SongsPlugin.ImportWizardForm',
+        'SongBeamer Files')
+
+class SongImportPage_SongShowPlus(SongImportPage):
+    format = SongFormat.SongShowPlus
+    name = WizardStrings.SSP
+    obj_prefix = u'songShowPlus'
+    filters = u'%s (*.sbsong)' % translate('SongsPlugin.ImportWizardForm',
+        'SongShow Plus Song Files')
+
+class SongImportPage_FoilPresenter(SongImportPage):
+    format = SongFormat.FoilPresenter
+    name = WizardStrings.FP
+    obj_prefix = u'foilPresenter'
+    filters = u'%s (*.foil)' % translate('SongsPlugin.ImportWizardForm',
+        'Foilpresenter Song Files')
+
+#class SongImportPage_CSV(SongImportPage):
+#    format = SongFormat.CSV
+#    name = WizardStrings.CSV
+#    obj_prefix = u'CSV'
+#    single_select = True
+
+# The ordering of formats in the drop-down list is tied to importer_pages,
+# not to the enumeration order of SongFormat.
+importer_pages = [
+    SongImportPage_OpenLP2(),
+    SongImportPage_OpenLP1(),
+    SongImportPage_OpenLyrics(),
+    SongImportPage_OpenSong(),
+    SongImportPage_WordsOfWorship(),
+    SongImportPage_CCLI(),
+    SongImportPage_SongsOfFellowship(),
+    SongImportPage_Generic(),
+    SongImportPage_EasiSlides(),
+    SongImportPage_EasyWorship(),
+    SongImportPage_SongBeamer(),
+    SongImportPage_SongShowPlus(),
+    SongImportPage_FoilPresenter(),
+#    SongImportPage_CSV(),
+]
+
 class SongImportForm(OpenLPWizard):
     """
     This is the Song Import Wizard, which allows easy importing of Songs
@@ -71,100 +382,30 @@
             QtCore.SIGNAL(u'currentIndexChanged(int)'),
             self.onCurrentIndexChanged)
 
-    def onCurrentIndexChanged(self, index):
+    def onCurrentIndexChanged(self, importer_index):
         """
         Called when the format combo box's index changed. We have to check if
         the import is available and accordingly to disable or enable the next
         button.
         """
-        self.formatStack.setCurrentIndex(index)
+        self.formatStack.setCurrentIndex(importer_index)
         next_button = self.button(QtGui.QWizard.NextButton)
-        next_button.setEnabled(SongFormat.get_availability(index))
+        next_button.setEnabled(SongFormat.get_availability(
+            importer_pages[importer_index].format))
 
     def customInit(self):
         """
         Song wizard specific initialisation.
         """
-        if not SongFormat.get_availability(SongFormat.OpenLP1):
-            self.openLP1DisabledWidget.setVisible(True)
-            self.openLP1ImportWidget.setVisible(False)
-        if not SongFormat.get_availability(SongFormat.SongsOfFellowship):
-            self.songsOfFellowshipDisabledWidget.setVisible(True)
-            self.songsOfFellowshipImportWidget.setVisible(False)
-        if not SongFormat.get_availability(SongFormat.Generic):
-            self.genericDisabledWidget.setVisible(True)
-            self.genericImportWidget.setVisible(False)
+        for importer_page in importer_pages:
+            importer_page.customInit()
 
     def customSignals(self):
         """
         Song wizard specific signals.
         """
-        QtCore.QObject.connect(self.openLP2BrowseButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onOpenLP2BrowseButtonClicked)
-        QtCore.QObject.connect(self.openLP1BrowseButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onOpenLP1BrowseButtonClicked)
-        QtCore.QObject.connect(self.openLyricsAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onOpenLyricsAddButtonClicked)
-        QtCore.QObject.connect(self.openLyricsRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onOpenLyricsRemoveButtonClicked)
-        QtCore.QObject.connect(self.openSongAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onOpenSongAddButtonClicked)
-        QtCore.QObject.connect(self.openSongRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onOpenSongRemoveButtonClicked)
-        QtCore.QObject.connect(self.wordsOfWorshipAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onWordsOfWorshipAddButtonClicked)
-        QtCore.QObject.connect(self.wordsOfWorshipRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onWordsOfWorshipRemoveButtonClicked)
-        QtCore.QObject.connect(self.ccliAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onCCLIAddButtonClicked)
-        QtCore.QObject.connect(self.ccliRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onCCLIRemoveButtonClicked)
-        QtCore.QObject.connect(self.songsOfFellowshipAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onSongsOfFellowshipAddButtonClicked)
-        QtCore.QObject.connect(self.songsOfFellowshipRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onSongsOfFellowshipRemoveButtonClicked)
-        QtCore.QObject.connect(self.genericAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onGenericAddButtonClicked)
-        QtCore.QObject.connect(self.genericRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onGenericRemoveButtonClicked)
-        QtCore.QObject.connect(self.easiSlidesBrowseButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onEasiSlidesBrowseButtonClicked)
-        QtCore.QObject.connect(self.ewBrowseButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onEWBrowseButtonClicked)
-        QtCore.QObject.connect(self.songBeamerAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onSongBeamerAddButtonClicked)
-        QtCore.QObject.connect(self.songBeamerRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onSongBeamerRemoveButtonClicked)
-        QtCore.QObject.connect(self.songShowPlusAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onSongShowPlusAddButtonClicked)
-        QtCore.QObject.connect(self.songShowPlusRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onSongShowPlusRemoveButtonClicked)
-        QtCore.QObject.connect(self.foilPresenterAddButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onFoilPresenterAddButtonClicked)
-        QtCore.QObject.connect(self.foilPresenterRemoveButton,
-            QtCore.SIGNAL(u'clicked()'),
-            self.onFoilPresenterRemoveButtonClicked)
+        for importer_page in importer_pages:
+            importer_page.customSignals()
 
     def addCustomPages(self):
         """
@@ -191,34 +432,9 @@
             QtGui.QSizePolicy.Expanding)
         self.formatStack = QtGui.QStackedLayout()
         self.formatStack.setObjectName(u'FormatStack')
-        # OpenLP 2.0
-        self.addFileSelectItem(u'openLP2', single_select=True)
-        # openlp.org 1.x
-        self.addFileSelectItem(u'openLP1', None, True, True)
-        # OpenLyrics
-        self.addFileSelectItem(u'openLyrics', u'OpenLyrics', True)
-        # Open Song
-        self.addFileSelectItem(u'openSong', u'OpenSong')
-        # Words of Worship
-        self.addFileSelectItem(u'wordsOfWorship')
-        # CCLI File import
-        self.addFileSelectItem(u'ccli')
-        # Songs of Fellowship
-        self.addFileSelectItem(u'songsOfFellowship', None, True)
-        # Generic Document/Presentation import
-        self.addFileSelectItem(u'generic', None, True)
-        # EasySlides
-        self.addFileSelectItem(u'easiSlides', single_select=True)
-        # EasyWorship
-        self.addFileSelectItem(u'ew', single_select=True)
-        # Words of Worship
-        self.addFileSelectItem(u'songBeamer')
-        # Song Show Plus
-        self.addFileSelectItem(u'songShowPlus')
-        # Foilpresenter
-        self.addFileSelectItem(u'foilPresenter')
-#        Commented out for future use.
-#        self.addFileSelectItem(u'csv', u'CSV', single_select=True)
+        for importer_page in importer_pages:
+            importer_page.addCustomPages(self)
+            self.formatComboBox.addItem(u'')
         self.sourceLayout.addLayout(self.formatStack)
         self.addPage(self.sourcePage)
 
@@ -238,95 +454,9 @@
         self.sourcePage.setTitle(WizardStrings.ImportSelect)
         self.sourcePage.setSubTitle(WizardStrings.ImportSelectLong)
         self.formatLabel.setText(WizardStrings.FormatLabel)
-        self.formatComboBox.setItemText(SongFormat.OpenLP2, UiStrings().OLPV2)
-        self.formatComboBox.setItemText(SongFormat.OpenLP1, UiStrings().OLPV1)
-        self.formatComboBox.setItemText(
-            SongFormat.OpenLyrics, WizardStrings.OL)
-        self.formatComboBox.setItemText(SongFormat.OpenSong, WizardStrings.OS)
-        self.formatComboBox.setItemText(
-            SongFormat.WordsOfWorship, WizardStrings.WoW)
-        self.formatComboBox.setItemText(SongFormat.CCLI, WizardStrings.CCLI)
-        self.formatComboBox.setItemText(
-            SongFormat.SongsOfFellowship, WizardStrings.SoF)
-        self.formatComboBox.setItemText(SongFormat.Generic,
-            translate('SongsPlugin.ImportWizardForm',
-            'Generic Document/Presentation'))
-        self.formatComboBox.setItemText(
-            SongFormat.EasiSlides, WizardStrings.ES)
-        self.formatComboBox.setItemText(
-            SongFormat.EasyWorship, WizardStrings.EW)
-        self.formatComboBox.setItemText(
-            SongFormat.SongBeamer, WizardStrings.SB)
-        self.formatComboBox.setItemText(
-            SongFormat.SongShowPlus, WizardStrings.SSP)
-        self.formatComboBox.setItemText(
-            SongFormat.FoilPresenter, WizardStrings.FP)
-#        self.formatComboBox.setItemText(SongFormat.CSV, WizardStrings.CSV)
-        self.openLP2FilenameLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
-        self.openLP2BrowseButton.setText(UiStrings().Browse)
-        self.openLP1FilenameLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
-        self.openLP1BrowseButton.setText(UiStrings().Browse)
-        self.openLP1DisabledLabel.setText(WizardStrings.NoSqlite)
-        self.openLyricsAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.openLyricsRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.openLyricsDisabledLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'The OpenLyrics '
-            'importer has not yet been developed, but as you can see, we are '
-            'still intending to do so. Hopefully it will be in the next '
-            'release.'))
-        self.openSongAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.openSongRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.wordsOfWorshipAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.wordsOfWorshipRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.ccliAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.ccliRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.songsOfFellowshipAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.songsOfFellowshipRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.songsOfFellowshipDisabledLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'The Songs of '
-            'Fellowship importer has been disabled because OpenLP cannot '
-            'access OpenOffice or LibreOffice.'))
-        self.genericAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.genericRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.genericDisabledLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'The generic document/'
-            'presentation importer has been disabled because OpenLP cannot '
-            'access OpenOffice or LibreOffice.'))
-        self.easiSlidesFilenameLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
-        self.easiSlidesBrowseButton.setText(UiStrings().Browse)
-        self.ewFilenameLabel.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
-        self.ewBrowseButton.setText(UiStrings().Browse)
-        self.songBeamerAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.songBeamerRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.songShowPlusAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.songShowPlusRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-        self.foilPresenterAddButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
-        self.foilPresenterRemoveButton.setText(
-            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
-#        self.csvFilenameLabel.setText(
-#            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
-#        self.csvBrowseButton.setText(UiStrings().Browse)
+        for importer_num, importer_page in enumerate(importer_pages):
+            self.formatComboBox.setItemText(importer_num, importer_page.name)
+            importer_page.retranslateUi()
         self.progressPage.setTitle(WizardStrings.Importing)
         self.progressPage.setSubTitle(
             translate('SongsPlugin.ImportWizardForm',
@@ -339,7 +469,7 @@
             'Save to File'))
         # Align all QFormLayouts towards each other.
         width = max(self.formatLabel.minimumSizeHint().width(),
-            self.openLP2FilenameLabel.minimumSizeHint().width())
+            importer_pages[0].filenameLabel.minimumSizeHint().width())
         self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
             QtGui.QSizePolicy.Fixed)
 
@@ -357,297 +487,11 @@
         if self.currentPage() == self.welcomePage:
             return True
         elif self.currentPage() == self.sourcePage:
-            source_format = self.formatComboBox.currentIndex()
-            if source_format == SongFormat.OpenLP2:
-                if self.openLP2FilenameEdit.text().isEmpty():
-                    critical_error_message_box(UiStrings().NFSs,
-                        WizardStrings.YouSpecifyFile % UiStrings().OLPV2)
-                    self.openLP2BrowseButton.setFocus()
-                    return False
-            elif source_format == SongFormat.OpenLP1:
-                if self.openLP1FilenameEdit.text().isEmpty():
-                    critical_error_message_box(UiStrings().NFSs,
-                        WizardStrings.YouSpecifyFile % UiStrings().OLPV1)
-                    self.openLP1BrowseButton.setFocus()
-                    return False
-            elif source_format == SongFormat.OpenLyrics:
-                if self.openLyricsFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.OL)
-                    self.openLyricsAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.OpenSong:
-                if self.openSongFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.OS)
-                    self.openSongAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.WordsOfWorship:
-                if self.wordsOfWorshipFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.WoW)
-                    self.wordsOfWorshipAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.CCLI:
-                if self.ccliFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.CCLI)
-                    self.ccliAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.SongsOfFellowship:
-                if self.songsOfFellowshipFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.SoF)
-                    self.songsOfFellowshipAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.Generic:
-                if self.genericFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        translate('SongsPlugin.ImportWizardForm',
-                        'You need to specify at least one document or '
-                        'presentation file to import from.'))
-                    self.genericAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.EasiSlides:
-                if self.easiSlidesFilenameEdit.text().isEmpty():
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.ES)
-                    self.easiSlidesBrowseButton.setFocus()
-                    return False
-            elif source_format == SongFormat.EasyWorship:
-                if self.ewFilenameEdit.text().isEmpty():
-                    critical_error_message_box(UiStrings().NFSs,
-                        WizardStrings.YouSpecifyFile % WizardStrings.EW)
-                    self.ewBrowseButton.setFocus()
-                    return False
-            elif source_format == SongFormat.SongBeamer:
-                if self.songBeamerFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.SB)
-                    self.songBeamerAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.SongShowPlus:
-                if self.songShowPlusFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.SSP)
-                    self.wordsOfWorshipAddButton.setFocus()
-                    return False
-            elif source_format == SongFormat.FoilPresenter:
-                if self.foilPresenterFileListWidget.count() == 0:
-                    critical_error_message_box(UiStrings().NFSp,
-                        WizardStrings.YouSpecifyFile % WizardStrings.FP)
-                    self.foilPresenterAddButton.setFocus()
-                    return False
-            return True
+            importer_index = self.formatComboBox.currentIndex()
+            return importer_pages[importer_index].validate()
         elif self.currentPage() == self.progressPage:
             return True
 
-    def getFiles(self, title, listbox, filters=u''):
-        """
-        Opens a QFileDialog and writes the filenames to the given listbox.
-
-        ``title``
-            The title of the dialog (unicode).
-
-        ``listbox``
-            A listbox (QListWidget).
-
-        ``filters``
-            The file extension filters. It should contain the file descriptions
-            as well as the file extensions. For example::
-
-                u'SongBeamer Files (*.sng)'
-        """
-        if filters:
-            filters += u';;'
-        filters += u'%s (*)' % UiStrings().AllFiles
-        filenames = QtGui.QFileDialog.getOpenFileNames(self, title,
-            SettingsManager.get_last_dir(self.plugin.settingsSection, 1),
-            filters)
-        if filenames:
-            listbox.addItems(filenames)
-            SettingsManager.set_last_dir(self.plugin.settingsSection,
-                os.path.split(unicode(filenames[0]))[0], 1)
-
-    def getListOfFiles(self, listbox):
-        """
-        Return a list of file from the listbox
-        """
-        return [unicode(listbox.item(i).text()) for i in range(listbox.count())]
-
-    def removeSelectedItems(self, listbox):
-        """
-        Remove selected listbox items
-        """
-        for item in listbox.selectedItems():
-            item = listbox.takeItem(listbox.row(item))
-            del item
-
-    def onOpenLP2BrowseButtonClicked(self):
-        """
-        Get OpenLP v2 song database file
-        """
-        self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV2,
-            self.openLP2FilenameEdit, u'%s (*.sqlite)'
-            % (translate('SongsPlugin.ImportWizardForm',
-            'OpenLP 2.0 Databases'))
-        )
-
-    def onOpenLP1BrowseButtonClicked(self):
-        """
-        Get OpenLP v1 song database file
-        """
-        self.getFileName(WizardStrings.OpenTypeFile % UiStrings().OLPV1,
-            self.openLP1FilenameEdit, u'%s (*.olp)'
-            % translate('SongsPlugin.ImportWizardForm',
-            'openlp.org v1.x Databases')
-        )
-
-    def onOpenLyricsAddButtonClicked(self):
-        """
-        Get OpenLyrics song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OL,
-            self.openLyricsFileListWidget)
-
-    def onOpenLyricsRemoveButtonClicked(self):
-        """
-        Remove selected OpenLyrics files from the import list
-        """
-        self.removeSelectedItems(self.openLyricsFileListWidget)
-
-    def onOpenSongAddButtonClicked(self):
-        """
-        Get OpenSong song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.OS,
-            self.openSongFileListWidget)
-
-    def onOpenSongRemoveButtonClicked(self):
-        """
-        Remove selected OpenSong files from the import list
-        """
-        self.removeSelectedItems(self.openSongFileListWidget)
-
-    def onWordsOfWorshipAddButtonClicked(self):
-        """
-        Get Words of Worship song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.WoW,
-            self.wordsOfWorshipFileListWidget, u'%s (*.wsg *.wow-song)'
-            % translate('SongsPlugin.ImportWizardForm',
-            'Words Of Worship Song Files')
-        )
-
-    def onWordsOfWorshipRemoveButtonClicked(self):
-        """
-        Remove selected Words of Worship files from the import list
-        """
-        self.removeSelectedItems(self.wordsOfWorshipFileListWidget)
-
-    def onCCLIAddButtonClicked(self):
-        """
-        Get CCLI song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.CCLI,
-            self.ccliFileListWidget)
-
-    def onCCLIRemoveButtonClicked(self):
-        """
-        Remove selected CCLI files from the import list
-        """
-        self.removeSelectedItems(self.ccliFileListWidget)
-
-    def onSongsOfFellowshipAddButtonClicked(self):
-        """
-        Get Songs of Fellowship song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SoF,
-            self.songsOfFellowshipFileListWidget, u'%s (*.rtf)'
-            % translate('SongsPlugin.ImportWizardForm',
-            'Songs Of Fellowship Song Files')
-        )
-
-    def onSongsOfFellowshipRemoveButtonClicked(self):
-        """
-        Remove selected Songs of Fellowship files from the import list
-        """
-        self.removeSelectedItems(self.songsOfFellowshipFileListWidget)
-
-    def onGenericAddButtonClicked(self):
-        """
-        Get song database files
-        """
-        self.getFiles(
-            translate('SongsPlugin.ImportWizardForm',
-            'Select Document/Presentation Files'),
-            self.genericFileListWidget
-        )
-
-    def onGenericRemoveButtonClicked(self):
-        """
-        Remove selected files from the import list
-        """
-        self.removeSelectedItems(self.genericFileListWidget)
-
-    def onEasiSlidesBrowseButtonClicked(self):
-        self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.ES,
-            self.easiSlidesFilenameEdit)
-
-    def onEWBrowseButtonClicked(self):
-        """
-        Get EasyWorship song database files
-        """
-        self.getFileName(WizardStrings.OpenTypeFile % WizardStrings.EW,
-            self.ewFilenameEdit)
-
-    def onSongBeamerAddButtonClicked(self):
-        """
-        Get SongBeamer song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SB,
-            self.songBeamerFileListWidget, u'%s (*.sng)' %
-            translate('SongsPlugin.ImportWizardForm', 'SongBeamer Files')
-        )
-
-    def onSongBeamerRemoveButtonClicked(self):
-        """
-        Remove selected SongBeamer files from the import list
-        """
-        self.removeSelectedItems(self.songBeamerFileListWidget)
-
-    def onSongShowPlusAddButtonClicked(self):
-        """
-        Get SongShow Plus song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.SSP,
-            self.songShowPlusFileListWidget, u'%s (*.sbsong)'
-            % translate('SongsPlugin.ImportWizardForm',
-            'SongShow Plus Song Files')
-        )
-
-    def onSongShowPlusRemoveButtonClicked(self):
-        """
-        Remove selected SongShow Plus files from the import list
-        """
-        self.removeSelectedItems(self.songShowPlusFileListWidget)
-
-    def onFoilPresenterAddButtonClicked(self):
-        """
-        Get FoilPresenter song database files
-        """
-        self.getFiles(WizardStrings.OpenTypeFile % WizardStrings.FP,
-            self.foilPresenterFileListWidget, u'%s (*.foil)'
-            % translate('SongsPlugin.ImportWizardForm',
-            'Foilpresenter Song Files')
-        )
-
-    def onFoilPresenterRemoveButtonClicked(self):
-        """
-        Remove selected FoilPresenter files from the import list
-        """
-        self.removeSelectedItems(self.foilPresenterFileListWidget)
-
     def setDefaults(self):
         """
         Set default form values for the song import wizard.
@@ -656,20 +500,8 @@
         self.finishButton.setVisible(False)
         self.cancelButton.setVisible(True)
         self.formatComboBox.setCurrentIndex(0)
-        self.openLP2FilenameEdit.setText(u'')
-        self.openLP1FilenameEdit.setText(u'')
-        self.openLyricsFileListWidget.clear()
-        self.openSongFileListWidget.clear()
-        self.wordsOfWorshipFileListWidget.clear()
-        self.ccliFileListWidget.clear()
-        self.songsOfFellowshipFileListWidget.clear()
-        self.genericFileListWidget.clear()
-        self.easiSlidesFilenameEdit.setText(u'')
-        self.ewFilenameEdit.setText(u'')
-        self.songBeamerFileListWidget.clear()
-        self.songShowPlusFileListWidget.clear()
-        self.foilPresenterFileListWidget.clear()
-        #self.csvFilenameEdit.setText(u'')
+        for importer_page in importer_pages:
+            importer_page.setDefaults()
         self.errorReportTextEdit.clear()
         self.errorReportTextEdit.setHidden(True)
         self.errorCopyToButton.setHidden(True)
@@ -689,75 +521,8 @@
         class, and then runs the ``do_import`` method of the importer to do
         the actual importing.
         """
-        source_format = self.formatComboBox.currentIndex()
-        importer = None
-        if source_format == SongFormat.OpenLP2:
-            # Import an OpenLP 2.0 database
-            importer = self.plugin.importSongs(SongFormat.OpenLP2,
-                filename=unicode(self.openLP2FilenameEdit.text())
-            )
-        elif source_format == SongFormat.OpenLP1:
-            # Import an openlp.org database
-            importer = self.plugin.importSongs(SongFormat.OpenLP1,
-                filename=unicode(self.openLP1FilenameEdit.text())
-            )
-        elif source_format == SongFormat.OpenLyrics:
-            # Import OpenLyrics songs
-            importer = self.plugin.importSongs(SongFormat.OpenLyrics,
-                filenames=self.getListOfFiles(self.openLyricsFileListWidget)
-            )
-        elif source_format == SongFormat.OpenSong:
-            # Import OpenSong songs
-            importer = self.plugin.importSongs(SongFormat.OpenSong,
-                filenames=self.getListOfFiles(self.openSongFileListWidget)
-            )
-        elif source_format == SongFormat.WordsOfWorship:
-            # Import Words Of Worship songs
-            importer = self.plugin.importSongs(SongFormat.WordsOfWorship,
-                filenames=self.getListOfFiles(
-                    self.wordsOfWorshipFileListWidget)
-            )
-        elif source_format == SongFormat.CCLI:
-            # Import Words Of Worship songs
-            importer = self.plugin.importSongs(SongFormat.CCLI,
-                filenames=self.getListOfFiles(self.ccliFileListWidget)
-            )
-        elif source_format == SongFormat.SongsOfFellowship:
-            # Import a Songs of Fellowship RTF file
-            importer = self.plugin.importSongs(SongFormat.SongsOfFellowship,
-                filenames=self.getListOfFiles(
-                    self.songsOfFellowshipFileListWidget)
-            )
-        elif source_format == SongFormat.Generic:
-            # Import a generic document or presentation
-            importer = self.plugin.importSongs(SongFormat.Generic,
-                filenames=self.getListOfFiles(self.genericFileListWidget)
-            )
-        elif source_format == SongFormat.EasiSlides:
-            # Import an EasiSlides export file
-            importer = self.plugin.importSongs(SongFormat.EasiSlides,
-                filename=unicode(self.easiSlidesFilenameEdit.text())
-            )
-        elif source_format == SongFormat.EasyWorship:
-            # Import an EasyWorship database
-            importer = self.plugin.importSongs(SongFormat.EasyWorship,
-                filename=unicode(self.ewFilenameEdit.text())
-            )
-        elif source_format == SongFormat.SongBeamer:
-            # Import SongBeamer songs
-            importer = self.plugin.importSongs(SongFormat.SongBeamer,
-                filenames=self.getListOfFiles(self.songBeamerFileListWidget)
-            )
-        elif source_format == SongFormat.SongShowPlus:
-            # Import ShongShow Plus songs
-            importer = self.plugin.importSongs(SongFormat.SongShowPlus,
-                filenames=self.getListOfFiles(self.songShowPlusFileListWidget)
-            )
-        elif source_format == SongFormat.FoilPresenter:
-            # Import Foilpresenter songs
-            importer = self.plugin.importSongs(SongFormat.FoilPresenter,
-                filenames=self.getListOfFiles(self.foilPresenterFileListWidget)
-            )
+        importer_index = self.formatComboBox.currentIndex()
+        importer = importer_pages[importer_index].getImporter()
         importer.do_import()
         if importer.error_log:
             self.progressLabel.setText(translate(
@@ -783,90 +548,3 @@
         report_file.write(self.errorReportTextEdit.toPlainText())
         report_file.close()
 
-    def addFileSelectItem(self, prefix, obj_prefix=None, can_disable=False,
-        single_select=False):
-        if not obj_prefix:
-            obj_prefix = prefix
-        page = QtGui.QWidget()
-        page.setObjectName(obj_prefix + u'Page')
-        if can_disable:
-            importWidget = self.disablableWidget(page, prefix, obj_prefix)
-        else:
-            importWidget = page
-        importLayout = QtGui.QVBoxLayout(importWidget)
-        importLayout.setMargin(0)
-        importLayout.setObjectName(obj_prefix + u'ImportLayout')
-        if single_select:
-            fileLayout = QtGui.QHBoxLayout()
-            fileLayout.setObjectName(obj_prefix + u'FileLayout')
-            filenameLabel = QtGui.QLabel(importWidget)
-            filenameLabel.setObjectName(obj_prefix + u'FilenameLabel')
-            fileLayout.addWidget(filenameLabel)
-            filenameEdit = QtGui.QLineEdit(importWidget)
-            filenameEdit.setObjectName(obj_prefix + u'FilenameEdit')
-            fileLayout.addWidget(filenameEdit)
-            browseButton = QtGui.QToolButton(importWidget)
-            browseButton.setIcon(self.openIcon)
-            browseButton.setObjectName(obj_prefix + u'BrowseButton')
-            fileLayout.addWidget(browseButton)
-            importLayout.addLayout(fileLayout)
-            importLayout.addSpacerItem(self.stackSpacer)
-        else:
-            fileListWidget = QtGui.QListWidget(importWidget)
-            fileListWidget.setSelectionMode(
-                QtGui.QAbstractItemView.ExtendedSelection)
-            fileListWidget.setObjectName(obj_prefix + u'FileListWidget')
-            importLayout.addWidget(fileListWidget)
-            buttonLayout = QtGui.QHBoxLayout()
-            buttonLayout.setObjectName(obj_prefix + u'ButtonLayout')
-            addButton = QtGui.QPushButton(importWidget)
-            addButton.setIcon(self.openIcon)
-            addButton.setObjectName(obj_prefix + u'AddButton')
-            buttonLayout.addWidget(addButton)
-            buttonLayout.addStretch()
-            removeButton = QtGui.QPushButton(importWidget)
-            removeButton.setIcon(self.deleteIcon)
-            removeButton.setObjectName(obj_prefix + u'RemoveButton')
-            buttonLayout.addWidget(removeButton)
-            importLayout.addLayout(buttonLayout)
-        self.formatStack.addWidget(page)
-        setattr(self, prefix + u'Page', page)
-        if single_select:
-            setattr(self, prefix + u'FilenameLabel', filenameLabel)
-            setattr(self, prefix + u'FileLayout', fileLayout)
-            setattr(self, prefix + u'FilenameEdit', filenameEdit)
-            setattr(self, prefix + u'BrowseButton', browseButton)
-        else:
-            setattr(self, prefix + u'FileListWidget', fileListWidget)
-            setattr(self, prefix + u'ButtonLayout', buttonLayout)
-            setattr(self, prefix + u'AddButton', addButton)
-            setattr(self, prefix + u'RemoveButton', removeButton)
-        setattr(self, prefix + u'ImportLayout', importLayout)
-        self.formatComboBox.addItem(u'')
-
-    def disablableWidget(self, page, prefix, obj_prefix):
-        layout = QtGui.QVBoxLayout(page)
-        layout.setMargin(0)
-        layout.setSpacing(0)
-        layout.setObjectName(obj_prefix + u'Layout')
-        disabledWidget = QtGui.QWidget(page)
-        disabledWidget.setVisible(False)
-        disabledWidget.setObjectName(obj_prefix + u'DisabledWidget')
-        disabledLayout = QtGui.QVBoxLayout(disabledWidget)
-        disabledLayout.setMargin(0)
-        disabledLayout.setObjectName(obj_prefix + u'DisabledLayout')
-        disabledLabel = QtGui.QLabel(disabledWidget)
-        disabledLabel.setWordWrap(True)
-        disabledLabel.setObjectName(obj_prefix + u'DisabledLabel')
-        disabledLayout.addWidget(disabledLabel)
-        disabledLayout.addSpacerItem(self.stackSpacer)
-        layout.addWidget(disabledWidget)
-        importWidget = QtGui.QWidget(page)
-        importWidget.setObjectName(obj_prefix + u'ImportWidget')
-        layout.addWidget(importWidget)
-        setattr(self, prefix + u'Layout', layout)
-        setattr(self, prefix + u'DisabledWidget', disabledWidget)
-        setattr(self, prefix + u'DisabledLayout', disabledLayout)
-        setattr(self, prefix + u'DisabledLabel', disabledLabel)
-        setattr(self, prefix + u'ImportWidget', importWidget)
-        return importWidget


Follow ups