← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~mahfiaz/openlp/easislidesimport into lp:openlp

 

mahfiaz has proposed merging lp:~mahfiaz/openlp/easislidesimport into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~mahfiaz/openlp/easislidesimport/+merge/46508

Easislides import plugin. It's probably violating some of OpenLP high coding standard, but I did my best.
-- 
https://code.launchpad.net/~mahfiaz/openlp/easislidesimport/+merge/46508
Your team OpenLP Core is requested to review the proposed merge of lp:~mahfiaz/openlp/easislidesimport into lp:openlp.
=== modified file 'openlp/plugins/songs/forms/songimportform.py'
--- openlp/plugins/songs/forms/songimportform.py	2011-01-15 19:24:50 +0000
+++ openlp/plugins/songs/forms/songimportform.py	2011-01-17 17:51:48 +0000
@@ -128,6 +128,9 @@
         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)
@@ -177,6 +180,8 @@
         self.addMultiFileSelectItem(u'songsOfFellowship', None, True)
         # Generic Document/Presentation import
         self.addMultiFileSelectItem(u'generic', None, True)
+        # EasySlides
+        self.addSingleFileSelectItem(u'easiSlides')
         # EasyWorship
         self.addSingleFileSelectItem(u'ew')
         # Words of Worship
@@ -226,10 +231,12 @@
             translate('SongsPlugin.ImportWizardForm',
             'Generic Document/Presentation'))
         self.formatComboBox.setItemText(8,
+            translate('SongsPlugin.ImportWizardForm', 'EasiSlides'))
+        self.formatComboBox.setItemText(9,
             translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
-        self.formatComboBox.setItemText(9,
+        self.formatComboBox.setItemText(10,
             translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
-#        self.formatComboBox.setItemText(9,
+#        self.formatComboBox.setItemText(11,
 #            translate('SongsPlugin.ImportWizardForm', 'CSV'))
         self.openLP2FilenameLabel.setText(
             translate('SongsPlugin.ImportWizardForm', 'Filename:'))
@@ -281,6 +288,10 @@
             translate('SongsPlugin.ImportWizardForm', 'The generic document/'
             'presentation importer has been disabled because OpenLP cannot '
             'find OpenOffice.org on your computer.'))
+        self.easiSlidesFilenameLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+        self.easiSlidesBrowseButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Browse...'))
         self.ewFilenameLabel.setText(
             translate('SongsPlugin.ImportWizardForm', 'Filename:'))
         self.ewBrowseButton.setText(
@@ -311,6 +322,8 @@
             QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
         self.openLP1FormLabelSpacer.changeSize(width, 0,
             QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
+        self.easiSlidesFormLabelSpacer.changeSize(width, 0, 
+            QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
         self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
             QtGui.QSizePolicy.Fixed)
 #        self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
@@ -404,6 +417,16 @@
                         'presentation file to import from.'))
                     self.genericAddButton.setFocus()
                     return False
+            elif source_format == SongFormat.EasiSlides:
+                if self.easiSlidesFilenameEdit.text().isEmpty():
+                    QtGui.QMessageBox.critical(self,
+                        translate('SongsPlugin.ImportWizardForm',
+                        'No Easislides Songs file selected'),
+                        translate('SongsPlugin.ImportWizardForm',
+                        'You need to select an xml song file exported from '
+                        'EasiSlides, to import from.'))
+                    self.easiSlidesBrowseButton.setFocus()
+                    return False
             elif source_format == SongFormat.EasyWorship:
                 if self.ewFilenameEdit.text().isEmpty():
                     criticalErrorMessageBox(
@@ -625,6 +648,13 @@
         """
         self.removeSelectedItems(self.genericFileListWidget)
 
+    def onEasiSlidesBrowseButtonClicked(self):
+        self.getFileName(
+            translate('SongsPlugin.ImportWizardForm',
+            'Select EasiSlides songfile'),
+            self.easiSlidesFilenameEdit
+        )
+        
     def onEWBrowseButtonClicked(self):
         """
         Get EasyWorship song database files
@@ -674,6 +704,7 @@
         self.ccliFileListWidget.clear()
         self.songsOfFellowshipFileListWidget.clear()
         self.genericFileListWidget.clear()
+        self.easiSlidesFilenameEdit.setText(u'')
         self.ewFilenameEdit.setText(u'')
         self.songBeamerFileListWidget.clear()
         #self.csvFilenameEdit.setText(u'')
@@ -737,8 +768,13 @@
             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 OpenLP 2.0 database
+            # Import an EasyWorship database
             importer = self.plugin.importSongs(SongFormat.EasyWorship,
                 filename=unicode(self.ewFilenameEdit.text())
             )

=== added file 'openlp/plugins/songs/forms/songimportwizard.py'
--- openlp/plugins/songs/forms/songimportwizard.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/forms/songimportwizard.py	2011-01-17 17:51:48 +0000
@@ -0,0 +1,372 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian      #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble,    #
+# Carsten Tinggaard, Frode Woldsund                                           #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.lib import build_icon, translate
+
+class Ui_SongImportWizard(object):
+    def setupUi(self, songImportWizard):
+        self.openIcon = build_icon(u':/general/general_open.png')
+        self.deleteIcon = build_icon(u':/general/general_delete.png')
+        songImportWizard.setObjectName(u'songImportWizard')
+        songImportWizard.setModal(True)
+        songImportWizard.setWizardStyle(QtGui.QWizard.ModernStyle)
+        songImportWizard.setOptions(
+            QtGui.QWizard.IndependentPages |
+            QtGui.QWizard.NoBackButtonOnStartPage |
+            QtGui.QWizard.NoBackButtonOnLastPage)
+        # Welcome Page
+        self.welcomePage = QtGui.QWizardPage()
+        self.welcomePage.setPixmap(QtGui.QWizard.WatermarkPixmap,
+            QtGui.QPixmap(u':/wizards/wizard_importsong.bmp'))
+        self.welcomePage.setObjectName(u'WelcomePage')
+        self.welcomeLayout = QtGui.QVBoxLayout(self.welcomePage)
+        self.welcomeLayout.setObjectName(u'WelcomeLayout')
+        self.titleLabel = QtGui.QLabel(self.welcomePage)
+        self.titleLabel.setObjectName(u'TitleLabel')
+        self.welcomeLayout.addWidget(self.titleLabel)
+        self.welcomeLayout.addSpacing(40)
+        self.informationLabel = QtGui.QLabel(self.welcomePage)
+        self.informationLabel.setWordWrap(True)
+        self.informationLabel.setObjectName(u'InformationLabel')
+        self.welcomeLayout.addWidget(self.informationLabel)
+        self.welcomeLayout.addStretch()
+        songImportWizard.addPage(self.welcomePage)
+        # Source Page
+        self.sourcePage = QtGui.QWizardPage()
+        self.sourcePage.setObjectName(u'SourcePage')
+        self.sourceLayout = QtGui.QVBoxLayout(self.sourcePage)
+        self.sourceLayout.setObjectName(u'SourceLayout')
+        self.formatLayout = QtGui.QFormLayout()
+        self.formatLayout.setObjectName(u'FormatLayout')
+        self.formatLabel = QtGui.QLabel(self.sourcePage)
+        self.formatLabel.setObjectName(u'FormatLabel')
+        self.formatComboBox = QtGui.QComboBox(self.sourcePage)
+        self.formatComboBox.setObjectName(u'FormatComboBox')
+        self.formatLayout.addRow(self.formatLabel, self.formatComboBox)
+        self.formatSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Minimum)
+        self.formatLayout.setItem(1, QtGui.QFormLayout.LabelRole,
+            self.formatSpacer)
+        self.sourceLayout.addLayout(self.formatLayout)
+        self.formatStack = QtGui.QStackedLayout()
+        self.formatStack.setObjectName(u'FormatStack')
+        # OpenLP 2.0
+        self.addSingleFileSelectItem(u'openLP2')
+        # openlp.org 1.x
+        self.addSingleFileSelectItem(u'openLP1', None, True)
+        # OpenLyrics
+        self.addMultiFileSelectItem(u'openLyrics', u'OpenLyrics', True)
+        # Open Song
+        self.addMultiFileSelectItem(u'openSong', u'OpenSong')
+        # Words of Worship
+        self.addMultiFileSelectItem(u'wordsOfWorship')
+        # CCLI File import
+        self.addMultiFileSelectItem(u'ccli')
+        # Songs of Fellowship
+        self.addMultiFileSelectItem(u'songsOfFellowship', None, True)
+        # Generic Document/Presentation import
+        self.addMultiFileSelectItem(u'generic', None, True)
+        # EasySlides
+        self.addSingleFileSelectItem(u'easiSlides')
+        # EasyWorship
+        self.addSingleFileSelectItem(u'ew')
+        # Words of Worship
+        self.addMultiFileSelectItem(u'songBeamer')
+#        Commented out for future use.
+#        self.addSingleFileSelectItem(u'csv', u'CSV')
+        self.sourceLayout.addLayout(self.formatStack)
+        songImportWizard.addPage(self.sourcePage)
+        # Import Page
+        self.importPage = QtGui.QWizardPage()
+        self.importPage.setObjectName(u'ImportPage')
+        self.importLayout = QtGui.QVBoxLayout(self.importPage)
+        self.importLayout.setMargin(48)
+        self.importLayout.setObjectName(u'ImportLayout')
+        self.importProgressLabel = QtGui.QLabel(self.importPage)
+        self.importProgressLabel.setObjectName(u'ImportProgressLabel')
+        self.importLayout.addWidget(self.importProgressLabel)
+        self.importProgressBar = QtGui.QProgressBar(self.importPage)
+        self.importProgressBar.setObjectName(u'ImportProgressBar')
+        self.importLayout.addWidget(self.importProgressBar)
+        songImportWizard.addPage(self.importPage)
+        self.retranslateUi(songImportWizard)
+        self.formatStack.setCurrentIndex(0)
+        QtCore.QObject.connect(self.formatComboBox,
+            QtCore.SIGNAL(u'currentIndexChanged(int)'),
+            self.formatStack.setCurrentIndex)
+        QtCore.QMetaObject.connectSlotsByName(songImportWizard)
+
+    def retranslateUi(self, songImportWizard):
+        songImportWizard.setWindowTitle(
+            translate('SongsPlugin.ImportWizardForm', 'Song Import Wizard'))
+        self.titleLabel.setText(
+            u'<span style="font-size:14pt; font-weight:600;">%s</span>' % \
+            translate('SongsPlugin.ImportWizardForm',
+                'Welcome to the Song Import Wizard'))
+        self.informationLabel.setText(
+            translate('SongsPlugin.ImportWizardForm',
+                'This wizard will help you to import songs from a variety of '
+                'formats. Click the next button below to start the process by '
+                'selecting a format to import from.'))
+        self.sourcePage.setTitle(
+            translate('SongsPlugin.ImportWizardForm', 'Select Import Source'))
+        self.sourcePage.setSubTitle(
+            translate('SongsPlugin.ImportWizardForm',
+            'Select the import format, and where to import from.'))
+        self.formatLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Format:'))
+        self.formatComboBox.setItemText(0,
+            translate('SongsPlugin.ImportWizardForm', 'OpenLP 2.0'))
+        self.formatComboBox.setItemText(1,
+            translate('SongsPlugin.ImportWizardForm', 'openlp.org 1.x'))
+        self.formatComboBox.setItemText(2,
+            translate('SongsPlugin.ImportWizardForm', 'OpenLyrics'))
+        self.formatComboBox.setItemText(3,
+            translate('SongsPlugin.ImportWizardForm', 'OpenSong'))
+        self.formatComboBox.setItemText(4,
+            translate('SongsPlugin.ImportWizardForm', 'Words of Worship'))
+        self.formatComboBox.setItemText(5,
+            translate('SongsPlugin.ImportWizardForm', 'CCLI/SongSelect'))
+        self.formatComboBox.setItemText(6,
+            translate('SongsPlugin.ImportWizardForm', 'Songs of Fellowship'))
+        self.formatComboBox.setItemText(7,
+            translate('SongsPlugin.ImportWizardForm',
+            'Generic Document/Presentation'))
+        self.formatComboBox.setItemText(8,
+            translate('SongsPlugin.ImportWizardForm', 'EasiSlides'))
+        self.formatComboBox.setItemText(9,
+            translate('SongsPlugin.ImportWizardForm', 'EasyWorship'))
+        self.formatComboBox.setItemText(10,
+            translate('SongsPlugin.ImportWizardForm', 'SongBeamer'))
+#        self.formatComboBox.setItemText(9,
+#            translate('SongsPlugin.ImportWizardForm', 'CSV'))
+        self.openLP2FilenameLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+        self.openLP2BrowseButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Browse...'))
+        self.openLP1FilenameLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+        self.openLP1BrowseButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Browse...'))
+        self.openLP1DisabledLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'The openlp.org 1.x '
+            'importer has been disabled due to a missing Python module. If '
+            'you want to use this importer, you will need to install the '
+            '"python-sqlite" module.'))
+        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 '
+            'find OpenOffice.org on your computer.'))
+        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 '
+            'find OpenOffice.org on your computer.'))
+        self.easiSlidesFilenameLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+        self.easiSlidesBrowseButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Browse...'))
+        self.ewFilenameLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+        self.ewBrowseButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Browse...'))
+        self.songBeamerAddButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Add Files...'))
+        self.songBeamerRemoveButton.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Remove File(s)'))
+#        self.csvFilenameLabel.setText(
+#            translate('SongsPlugin.ImportWizardForm', 'Filename:'))
+#        self.csvBrowseButton.setText(
+#            translate('SongsPlugin.ImportWizardForm', 'Browse...'))
+        self.importPage.setTitle(
+            translate('SongsPlugin.ImportWizardForm', 'Importing'))
+        self.importPage.setSubTitle(
+            translate('SongsPlugin.ImportWizardForm',
+                'Please wait while your songs are imported.'))
+        self.importProgressLabel.setText(
+            translate('SongsPlugin.ImportWizardForm', 'Ready.'))
+        self.importProgressBar.setFormat(
+            translate('SongsPlugin.ImportWizardForm', '%p%'))
+        # Align all QFormLayouts towards each other.
+        width = max(self.formatLabel.minimumSizeHint().width(),
+            self.openLP2FilenameLabel.minimumSizeHint().width())
+        self.formatSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Fixed)
+        self.openLP2FormLabelSpacer.changeSize(width, 0,
+            QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
+        self.openLP1FormLabelSpacer.changeSize(width, 0,
+            QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
+        self.easiSlidesFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Fixed)
+        self.ewFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Fixed)
+#        self.csvFormLabelSpacer.changeSize(width, 0, QtGui.QSizePolicy.Fixed,
+#            QtGui.QSizePolicy.Fixed)
+
+    def addSingleFileSelectItem(self, prefix, obj_prefix=None,
+        can_disable=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.QFormLayout(importWidget)
+        importLayout.setMargin(0)
+        if can_disable:
+            importLayout.setObjectName(obj_prefix + u'ImportLayout')
+        else:
+            importLayout.setObjectName(obj_prefix + u'Layout')
+        filenameLabel = QtGui.QLabel(importWidget)
+        filenameLabel.setObjectName(obj_prefix + u'FilenameLabel')
+        fileLayout = QtGui.QHBoxLayout()
+        fileLayout.setObjectName(obj_prefix + u'FileLayout')
+        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.addRow(filenameLabel, fileLayout)
+        formSpacer = QtGui.QSpacerItem(10, 0, QtGui.QSizePolicy.Fixed,
+            QtGui.QSizePolicy.Minimum)
+        importLayout.setItem(1, QtGui.QFormLayout.LabelRole, formSpacer)
+        self.formatStack.addWidget(page)
+        setattr(self, prefix + u'Page', page)
+        setattr(self, prefix + u'FilenameLabel', filenameLabel)
+        setattr(self, prefix + u'FormLabelSpacer', formSpacer)
+        setattr(self, prefix + u'FileLayout', fileLayout)
+        setattr(self, prefix + u'FilenameEdit', filenameEdit)
+        setattr(self, prefix + u'BrowseButton', browseButton)
+        if can_disable:
+            setattr(self, prefix + u'ImportLayout', importLayout)
+        else:
+            setattr(self, prefix + u'Layout', importLayout)
+        self.formatComboBox.addItem(u'')
+
+    def addMultiFileSelectItem(self, prefix, obj_prefix=None,
+        can_disable=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)
+        if can_disable:
+            importLayout.setObjectName(obj_prefix + u'ImportLayout')
+        else:
+            importLayout.setObjectName(obj_prefix + u'Layout')
+        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)
+        setattr(self, prefix + u'FileListWidget', fileListWidget)
+        setattr(self, prefix + u'ButtonLayout', buttonLayout)
+        setattr(self, prefix + u'AddButton', addButton)
+        setattr(self, prefix + u'RemoveButton', removeButton)
+        if can_disable:
+            setattr(self, prefix + u'ImportLayout', importLayout)
+        else:
+            setattr(self, prefix + u'Layout', 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)
+        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

=== added file 'openlp/plugins/songs/lib/easislidesimport.py'
--- openlp/plugins/songs/lib/easislidesimport.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/lib/easislidesimport.py	2011-01-17 17:51:48 +0000
@@ -0,0 +1,507 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2011 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael      #
+# Gorven, Scott Guerrieri, Meinert Jordan, Andreas Preikschat, Christian      #
+# Richter, Philip Ridout, Maikel Stuivenberg, Martin Thompson, Jon Tibble,    #
+# Carsten Tinggaard, Frode Woldsund                                           #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it     #
+# under the terms of the GNU General Public License as published by the Free  #
+# Software Foundation; version 2 of the License.                              #
+#                                                                             #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    #
+# more details.                                                               #
+#                                                                             #
+# You should have received a copy of the GNU General Public License along     #
+# with this program; if not, write to the Free Software Foundation, Inc., 59  #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
+###############################################################################
+
+import logging
+import os
+from lxml import etree
+from lxml.etree import Error, LxmlError
+import re
+
+from openlp.core.lib import translate
+from openlp.plugins.songs.lib.songimport import SongImport
+
+log = logging.getLogger(__name__)
+
+class EasiSlidesImportError(Exception):
+    pass
+
+class EasiSlidesImport(SongImport):
+    """
+    Import songs exported from EasiSlides
+
+    The format example is here: 
+    http://wiki.openlp.org/Development:EasiSlides_-_Song_Data_Format
+    """
+    def __init__(self, manager, **kwargs):
+        """
+        Initialise the class.
+        """
+        SongImport.__init__(self, manager)
+        self.filename = kwargs[u'filename']
+        self.song = None
+        self.commit = True
+
+    def do_import(self):
+        """
+        Import either each of the files in self.filenames - each element of
+        which can be either a single opensong file, or a zipfile containing
+        multiple opensong files. If `self.commit` is set False, the
+        import will not be committed to the database (useful for test scripts).
+        """
+        success = True
+        
+        self.import_wizard.progressBar.setMaximum(1)
+        
+        log.info(u'Direct import %s', self.filename)
+        self.import_wizard.incrementProgressBar(
+            unicode(translate('SongsPlugin.ImportWizardForm',
+                u'Importing %s...')) % os.path.split(self.filename)[-1])
+        file = open(self.filename)
+        count = file.read().count('<Item>')
+        file.seek(0)
+        self.import_wizard.progressBar.setMaximum(count)
+        self.do_import_file(file)
+        
+        return success
+
+    def do_import_file(self, file):
+        """
+        Process the EasiSlides file - pass in a file-like object,
+        not a filename
+        """
+        self.set_defaults()
+        
+        # determines, if ENTIRELY UPPERCASE lines should be converted to lower
+        self.toLower = False
+        # list of names, which have always to be Uppercase, like Jesus
+        # only used, when self.toLower is True
+        self.backToUpper = [u'Jesus', u'God']
+        # determines, if title should be prepended to lyrics
+        self.titleIsLyrics = False
+        
+        try:
+            context = etree.iterparse(file)
+        except (Error, LxmlError):
+            log.exception(u'Error parsing XML')
+            return
+        
+        data = {}
+        for action, elem in context:
+            if not elem.text:
+                text = None
+            else:
+                text = unicode(elem.text)
+            
+            data[elem.tag.lower()] = text
+            
+            if elem.tag.lower() == u"item":
+                self.parse_song(data)
+                self.import_wizard.incrementProgressBar(
+                    unicode(translate('SongsPlugin.ImportWizardForm',
+                        u'Importing %s, song %s...')) % 
+                        (os.path.split(self.filename)[-1], self.title))
+                if self.commit:
+                    self.finish()
+                data = {}
+        
+    def notCapsLock(self, string):
+        if self.toLower and string.upper() == string:
+            ret = string.lower()
+            if len(self.backToUpper) > 0:
+                for repl in self.backToUpper:
+                    if repl == u'':
+                        continue
+                    ret = ret.replace(repl.lower(), repl)
+            return ret
+        else:
+            return string
+        
+    def notCapsLockTitle(self, string):
+        if self.toLower and string.upper() == string:
+            ret = string.lower()
+            if len(self.backToUpper) > 0:
+                for repl in self.backToUpper:
+                    if repl == u'':
+                        continue
+                    ret = ret.replace(repl.lower(), repl)
+            return u"%s%s" % (ret[0].upper(), ret[1:])
+        else:
+            return string
+    
+    def listHas(self, lst, subitems):
+        for i in subitems:
+            if type(lst) == type({}) and lst.has_key(i):
+                lst = lst[i]
+            elif type(lst) == type([]) and i in lst:
+                lst = lst[i]
+            else:
+                return False
+        return True
+    
+    def extractRegion(self, line):
+        # this was true already: thisline[0:7] == u'[region':
+        right_bracket = line.find(u']')
+        return line[7:right_bracket].strip()
+        
+    def parse_song(self, data):
+        # We should also check if the title is already used, if yes,
+        # maybe user sould be asked if we should import or not
+        
+        # set title
+        self.title = self.notCapsLockTitle(data['title1'])
+        
+        # set alternate title, if present
+        if data['title2'] != None:
+            self.alternate_title = self.notCapsLockTitle(data['title2'])
+        
+        # folder name, we have no use for it, usually only one folder is 
+        # used in easislides and this contains no actual data, easislides 
+        # default database is named English, but usersmay not follow their
+        # example
+        # data['folder']
+        
+        # set song number, if present, empty otherwise
+        # EasiSlides tends to set all not changed song numbers to 0,
+        # so this hardly ever carries any information
+        if data['songnumber'] != None and data['songnumber'] != u'0':
+            self.song_number = int(data['songnumber'])
+        
+        # Don't know how to use Notations
+        # data['notations']
+        
+        # set song authors
+        # we don't have to handle the no author case, it is done afterwards
+        if data['writer'] != None:
+            authors = data['writer'].split(u',')
+            for author in authors:
+                self.authors.append(author.strip())
+        
+        # set copyright data
+        # licenceadmins may contain Public Domain or CCLI, as shown in examples
+        # let's just concatenate these fields, it should be determined, if song
+        # No is actually CCLI nr, if it is set
+        copyright = []
+        if data['copyright']:
+            copyright.append(data['copyright'].strip())
+        if data['licenceadmin1']:
+            copyright.append(data['licenceadmin1'].strip())
+        if data['licenceadmin2']:
+            copyright.append(data['licenceadmin2'].strip())
+        self.add_copyright(u' '.join(copyright))
+
+        # set topic data, I have seen no example, and probably should not do it,
+        # I even was not able to find place to set categories in easislides
+        # but then again, it would not hurt either
+        if data['category']:
+            for topic in data['category'].split(u','):
+                self.topics.append(topic.strip())
+
+        # don't know what to do with timing data
+        # may be either 3/4 or 4/4
+        # data['timing']
+        
+        # don't know what to do with music key
+        # data['musickey'], may be Db, C, G, F#, F#m
+        # data['capo'], is a number from 0 to 11, determing where to
+        # place a capo on guitar neck
+        
+        # set book data
+        if data['bookreference']:
+            self.song_book_name = data['bookreference'].strip()
+        
+        # don't know what to do with user
+        # data['userreference'], this is simple text entry, no 
+        # notable restrictions, no idea what this is used for
+        # U: I have seen one use of this as "searchable field" or similar,
+        # still no use for us
+
+        # there is nothing to do with formatdata, this for sure is a messy
+        # thing, see an example: 
+        # 21=1&gt;23=0&gt;22=2&gt;25=2&gt;26=-16777216&gt;
+        # 27=-16777216&gt;28=11&gt;29=-1&gt;30=-256&gt;31=2&gt;32=2&gt;
+        # 41=16&gt;42=16&gt;43=Microsoft Sans Serif&gt;
+        # 44=Microsoft Sans Serif&gt;45=0&gt;46=45&gt;47=20&gt;48=40&gt;
+        # 50=0&gt;51=&gt;52=50&gt;53=-1&gt;54=0&gt;55=1&gt;61=&gt;62=2&gt;
+        # 63=1&gt;64=2&gt;65=2&gt;66=0&gt;71=0&gt;72=Fade&gt;73=Fade&gt;
+        #
+        # data['formatdata']
+
+        # don't know what to do with settings data either, this is similar
+        # nonsense as formatdata: 10=2;5;0;0;1;0;»126;232;&gt;
+        # data['settings']
+        
+        # LYRICS LYRICS LYRICS
+        # the big and messy part to handle lyrics
+        lyrics = data['contents']
+
+        # we add title to first line, if supposed to do so
+        # we don't use self.title, because this may have changed case
+        if self.titleIsLyrics:
+            lyrics = u"%s\n%s" % (data['title1'], lyrics)
+
+        #if lyrics.find(u'[') != -1:
+        #    # this must have at least one separator
+        #    match = -1
+        #    while True:
+        #        match = lyrics.find(u'[', match+1)
+        #        if match == -1:
+        #            break
+        #        elif lyrics[match:match+7].lower() == u'[region':
+        #            regions = regions+1
+        #        else:
+        #            separators = separators+1
+
+        lines = lyrics.split(u'\n')
+        length = len(lines)
+        
+        # we go over lines first, to determine some information,
+        # which tells us how to parse verses later
+        emptylines = 0
+        regionlines = {}
+        separatorlines = 0
+        uppercaselines = 0
+        notuppercaselines = 0
+        for i in range(length):
+            lines[i] = lines[i].strip()
+            thisline = lines[i]
+            if len(thisline) == 0:
+                emptylines = emptylines + 1
+            elif thisline[0] == u'[':
+                if thisline[1:7] == u'region':
+                    # this is region separator [region 2]
+                    # Easislides song can have only one extra region zone,
+                    # at least by now, but just in case the file happens 
+                    # to have [region 3] or more, we add a possiblity to  
+                    # count these separately, yeah, rather stupid, but 
+                    # count this as a programming exercise
+                    region = self.extractRegion(thisline)
+                    if regionlines.has_key(region):
+                        regionlines[region] = regionlines[region] + 1
+                    else:
+                        regionlines[region] = 1
+                else:
+                    separatorlines = separatorlines + 1
+            elif thisline == thisline.upper():
+                uppercaselines = uppercaselines + 1
+            else:
+                notuppercaselines = notuppercaselines + 1
+
+        # if the whole song is entirely UPPERCASE
+        allUpperCase = (notuppercaselines == 0)
+        # if the song has separators
+        separators = (separatorlines > 0)
+        # the number of regions in song, conting the default as one
+        regions = len(regionlines)+1
+        if regions > 2:
+            log.info(u'EasiSlidesImport: the file contained a song named "%s"'
+                u'with more than two regions, but only two regions are',
+                u'tested, all regions were: %s',
+                self.title, u','.join(regionlines.keys()))
+        # if the song has regions
+        regions = (len(regionlines) > 1)
+        # if the regions are inside verses (more than one )
+        regionsInVerses = (len(regionlines) and \
+                    regionlines[regionlines.keys()[0]] > 1)
+        
+        # data storage while importing
+        verses = {}
+        # keep track of a "default" verse order, in case none is specified
+        # this list contains list as [region, versetype, versenum, instance]
+        our_verse_order = []
+        # default region
+        defaultregion = u'1'
+        reg = defaultregion
+        verses[reg] = {}
+        # instance
+        inst = 1
+        
+        MarkTypes = {
+            u'chorus': u'C',
+            u'verse': u'V',
+            u'intro': u'I',
+            u'ending': u'E',
+            u'bridge': u'B',
+            u'prechorus': u'P',
+            }
+
+        for i in range(length):
+            # we iterate once more over lines
+            thisline = lines[i]
+            if i < length-1:
+                nextline = lines[i+1].strip()
+            else:
+                # there is no nextline at the last line
+                nextline = False
+            
+            
+            if len(thisline) == 0:
+                if separators:
+                    # separators are used, so empty line means slide break
+                    # inside verse
+                    if self.listHas(verses, [reg, vt, vn, inst]):
+                        inst = inst + 1
+                else:
+                    # separators are not used, so empty line starts a new verse
+                    if not allUpperCase and nextline and \
+                        nextline is nextline.upper():
+                        # the next line is all uppercase, it must be chorus
+                        vt = u'C'
+                    else:
+                        # if the next line is not uppercase, 
+                        # or whole song is uppercase, this must be verse
+                        vt = u'V'
+                    
+                    # changing the region is not possible in this case
+
+                    if verses[reg].has_key(vt):
+                        vn = len(verses[reg][vt].keys())+1
+                    else:
+                        vn = u'1'
+                        
+                    inst = 1
+                    if not [reg, vt, vn, inst] in our_verse_order:
+                        our_verse_order.append([reg, vt, vn, inst])
+                    continue
+                continue
+            
+            elif thisline[0:7] == u'[region':
+                reg = self.extractRegion(thisline)
+                if not verses.has_key(reg):
+                    verses[reg] = {}
+                if i == 0:
+                    # the file started with [region 2]
+                    vt = u'V'
+                    vn = u'1'
+                    our_verse_order.append([reg, vt, vn, inst])
+                continue
+                
+            elif thisline[0] == u'[':
+                # this is a normal section marker
+                # drop the square brackets
+                right_bracket = thisline.find(u']')
+                marker = thisline[1:right_bracket].upper()
+                # have we got any digits?
+                # If so, versenumber is everything from the digits
+                # to the end (even if there are some alpha chars on the end)
+                match = re.match(u'(.*)(\d+.*)', marker)
+                if match is not None:
+                    vt = match.group(1).strip()
+                    vn = match.group(2)
+                    if vt == u'':
+                        vt = u'V'
+                    elif MarkTypes.has_key(vt.lower()):
+                        vt = MarkTypes[vt.lower()]
+                    else:
+                        vt = u'O'
+                else:
+                    if marker == u'':
+                        vt = u'V'
+                    elif MarkTypes.has_key(marker.lower()):
+                        vt = MarkTypes[marker.lower()]
+                    else:
+                        vt = u'O'
+                    vn = u'1'
+                    
+                if regionsInVerses:
+                    region = defaultregion
+                
+                inst = 1
+                if self.listHas(verses, [reg, vt, vn, inst]):
+                    inst = len(verses[reg][vt][vn])+1
+                
+                if not [reg, vt, vn, inst] in our_verse_order:
+                    our_verse_order.append([reg, vt, vn, inst])
+                continue
+            
+            if i == 0:
+                # this is the first line, but no separator is found,
+                # we say it's V1
+                vt = u'V'
+                vn = u'1'
+                our_verse_order.append([reg, vt, vn, inst])
+            
+            # We have versetype/number data, if it was there, now
+            # we parse text
+            if not verses[reg].has_key(vt):
+                verses[reg][vt] = {}
+            if not verses[reg][vt].has_key(vn):
+                verses[reg][vt][vn] = {}
+            if not verses[reg][vt][vn].has_key(inst):
+                verses[reg][vt][vn][inst] = []
+            
+            # Tidy text and remove the ____s from extended words
+            words = self.tidy_text(thisline)
+            words = self.notCapsLock(words)
+            
+            verses[reg][vt][vn][inst].append(words)
+        # done parsing
+                
+        versetags = []
+        
+        # we use our_verse_order to ensure, we insert lyrics in the same order
+        # as these appeared originally in the file
+        
+        for tag in our_verse_order:
+            reg = tag[0]
+            vt = tag[1]
+            vn = tag[2]
+            inst = tag[3]
+            
+            if not self.listHas(verses, [reg, vt, vn, inst]):
+                continue
+            versetag = u'%s%s' % (vt, vn)
+            versetags.append(versetag)
+            lines = u'\n'.join(verses[reg][vt][vn][inst])
+            self.verses.append([versetag, lines])
+        
+        # Sequence keys:
+        # numbers refer to verses
+        # p = prechorus
+        # q = prechorus 2
+        # c = chorus
+        # t = chorus 2
+        # b = bridge
+        # w = bridge 2
+        # e = ending
+        SeqTypes = {
+            u'p': u'P1',
+            u'q': u'P2',
+            u'c': u'C1',
+            u't': u'C2',
+            u'b': u'B1',
+            u'w': u'B2',
+            u'e': u'E1'
+            }
+        # Make use of Sequence data, determining the order of verses, choruses
+        # if this is not present, we don't need it either, since the
+        # verses already are in the right order
+        if data['sequence'] != None:
+            order = data['sequence'].split(u',')
+            for tag in order:
+                if tag[0].isdigit():
+                    # it's a verse if it has no prefix, but has a number
+                    tag = u'V' + tag
+                elif SeqTypes.has_key(tag.lower()):
+                    tag = SeqTypes[tag.lower()]
+                else:
+                    # maybe we should continue here instead
+                    tag = u'O1'
+                
+                if not tag in versetags:
+                    log.info(u'Got order %s but not in versetags, dropping this'
+                        u'item from presentation order', tag)
+                else:
+                    self.verse_order_list.append(tag)

=== modified file 'openlp/plugins/songs/lib/importer.py'
--- openlp/plugins/songs/lib/importer.py	2011-01-02 16:42:09 +0000
+++ openlp/plugins/songs/lib/importer.py	2011-01-17 17:51:48 +0000
@@ -25,6 +25,7 @@
 ###############################################################################
 
 from opensongimport import OpenSongImport
+from easislidesimport import EasiSlidesImport
 from olpimport import OpenLPSongImport
 from openlyricsimport import OpenLyricsImport
 from wowimport import WowImport
@@ -65,8 +66,9 @@
     SongsOfFellowship = 6
     Generic = 7
     #CSV = 8
-    EasyWorship = 8
-    SongBeamer = 9
+    EasiSlides = 8
+    EasyWorship = 9
+    SongBeamer = 10
 
     @staticmethod
     def get_class(format):
@@ -92,6 +94,8 @@
             return OooImport
         elif format == SongFormat.CCLI:
             return CCLIFileImport
+        elif format == SongFormat.EasiSlides:
+            return EasiSlidesImport
         elif format == SongFormat.EasyWorship:
             return EasyWorshipSongImport
         elif format == SongFormat.SongBeamer:
@@ -112,6 +116,7 @@
             SongFormat.CCLI,
             SongFormat.SongsOfFellowship,
             SongFormat.Generic,
+            SongFormat.EasiSlides,
             SongFormat.EasyWorship,
             SongFormat.SongBeamer
         ]
@@ -128,4 +133,4 @@
 SongFormat.set_availability(SongFormat.SongsOfFellowship, has_sof)
 SongFormat.set_availability(SongFormat.Generic, has_ooo)
 
-__all__ = [u'SongFormat']
\ No newline at end of file
+__all__ = [u'SongFormat']

=== modified file 'openlp/plugins/songs/lib/opensongimport.py'
--- openlp/plugins/songs/lib/opensongimport.py	2011-01-13 17:55:29 +0000
+++ openlp/plugins/songs/lib/opensongimport.py	2011-01-17 17:51:48 +0000
@@ -129,7 +129,7 @@
             else:
                 numfiles += 1
         log.debug(u'Total number of files: %d', numfiles)
-        self.import_wizard.progressBar.setMaximum(numfiles)
+        self.import_wizard.importProgressBar.setMaximum(numfiles)
         for filename in self.filenames:
             if self.stop_import_flag:
                 success = False

=== modified file 'openlp/plugins/songs/lib/songimport.py'
--- openlp/plugins/songs/lib/songimport.py	2011-01-13 17:55:29 +0000
+++ openlp/plugins/songs/lib/songimport.py	2011-01-17 17:51:48 +0000
@@ -265,6 +265,7 @@
         log.info(u'commiting song %s to database', self.title)
         song = Song()
         song.title = self.title
+        song.alternate_title = self.alternate_title
         song.search_title = self.remove_punctuation(self.title).lower() \
             + '@' + self.remove_punctuation(self.alternate_title).lower()
         song.song_number = self.song_number


Follow ups