← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~raoul-snyman/openlp/special-song-importer into lp:openlp

 

Raoul Snyman has proposed merging lp:~raoul-snyman/openlp/special-song-importer into lp:openlp.

Requested reviews:
  Andreas Preikschat (googol)
  John Cegalis (jseagull1)

For more details, see:
https://code.launchpad.net/~raoul-snyman/openlp/special-song-importer/+merge/107531

This is a very special song importer *wink wink* which appears in the Tools menu.
-- 
https://code.launchpad.net/~raoul-snyman/openlp/special-song-importer/+merge/107531
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/__init__.py'
--- openlp/core/__init__.py	2012-05-23 16:53:04 +0000
+++ openlp/core/__init__.py	2012-05-26 18:22:20 +0000
@@ -92,8 +92,9 @@
         Override exec method to allow the shared memory to be released on exit
         """
         self.eventLoopIsActive = True
-        QtGui.QApplication.exec_()
+        result = QtGui.QApplication.exec_()
         self.sharedMemory.detach()
+        return result
 
     def run(self, args, testing=False):
         """

=== modified file 'openlp/core/resources.py'
--- openlp/core/resources.py	2012-02-25 11:11:59 +0000
+++ openlp/core/resources.py	2012-05-26 18:22:20 +0000
@@ -60533,6 +60533,43 @@
 \x7d\x05\x51\x09\xe2\xbe\xfe\x09\xa2\x12\x44\x25\x38\xdd\x96\xe5\
 \x3a\xcf\xd3\x74\x19\xc7\x1c\xed\x7b\x03\x2c\xc0\x04\x0b\x8e\x16\
 \xcd\xfc\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x02\x30\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x10\x00\x00\x00\x10\x08\x03\x00\x00\x00\x28\x2d\x0f\x53\
+\x00\x00\x01\x02\x50\x4c\x54\x45\xff\xff\xff\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x01\x01\x01\x00\x00\x00\x04\x04\x04\x0a\x0a\x0a\
+\x00\x00\x00\x10\x10\x10\x11\x11\x11\x0b\x0b\x0b\x0e\x0e\x0e\x12\
+\x12\x12\x1b\x1b\x1b\x1f\x1f\x1f\x01\x01\x01\x13\x13\x13\x15\x15\
+\x15\x16\x16\x16\x17\x17\x17\x18\x18\x18\x1b\x1b\x1b\x1c\x1c\x1c\
+\x23\x23\x23\x24\x24\x24\x26\x25\x23\x27\x27\x27\x28\x28\x28\x2b\
+\x2b\x2b\x2c\x2c\x2c\x2d\x2d\x2d\x32\x32\x32\x34\x32\x31\x36\x28\
+\x1e\x36\x28\x1f\x36\x2a\x24\x36\x36\x36\x38\x28\x1f\x39\x2c\x25\
+\x3c\x30\x28\x45\x42\x40\x48\x21\x00\x4a\x4a\x4a\x4d\x4d\x4d\x4e\
+\x29\x09\x4e\x4e\x4e\x53\x33\x1c\x55\x53\x52\x56\x56\x56\x59\x48\
+\x3d\x68\x58\x4d\x68\x68\x68\x69\x57\x46\x69\x69\x69\x6a\x6a\x6a\
+\x72\x70\x6f\x73\x73\x73\x76\x62\x52\x78\x78\x78\x81\x7e\x7d\x84\
+\x40\x07\x84\x57\x34\x86\x43\x0b\x87\x5b\x3b\x90\x49\x0b\x90\x61\
+\x3d\x91\x62\x3f\x95\x72\x54\xab\x91\x7a\x7b\xc4\x3a\x99\x00\x00\
+\x00\x20\x74\x52\x4e\x53\x00\x01\x08\x0a\x13\x14\x19\x24\x26\x29\
+\x47\x62\x81\x8e\x93\x98\x9d\xa5\xbe\xcc\xcf\xd1\xeb\xec\xed\xf3\
+\xf3\xf4\xf6\xf6\xfb\xfc\x8d\xdd\x50\x49\x00\x00\x00\xbd\x49\x44\
+\x41\x54\x78\xda\x8d\x8b\xd9\x12\x81\x00\x18\x85\x7f\x5b\x48\xa9\
+\xc8\xbe\x44\xb2\x24\x59\x93\xa5\x6c\x51\x2a\xd9\xeb\xfd\x5f\x45\
+\xc6\xb8\xe6\xbb\x38\x73\xbe\x33\x73\xe0\x3f\x12\x69\x0c\x00\x4b\
+\x27\xbe\x8e\x30\x47\x3e\x1e\xe3\x8f\x0c\xf2\x71\x34\xd3\x1f\x34\
+\x2a\x95\x86\xd8\xcf\xa0\x6f\x8f\x56\x2d\x51\xe1\x8c\x1d\xa7\x88\
+\x56\x35\xea\x0f\xd4\x54\x35\x86\xeb\x7a\x4d\x1d\x1a\xea\x94\xf2\
+\x0f\xec\xc1\x39\x75\x84\x66\x53\xe8\x9c\x9c\x03\x8b\x42\x6a\x2b\
+\xc9\x9a\xd9\xee\xf5\x5a\xa6\x26\x4b\xdb\x14\xe4\xe6\x9b\xc7\x6d\
+\xcf\xd1\x34\xb7\xbf\x3c\x37\xb3\x2c\xe4\x27\xcb\xeb\xdd\x2e\x87\
+\xc3\x65\xfb\x7e\x5e\x8d\xf3\x80\x77\x75\xd7\x5b\x24\x01\x92\x0b\
+\xcf\xd5\xbb\x38\x04\x89\xe2\xa8\x44\x86\x00\x42\x64\x69\x54\x20\
+\x82\x00\x10\x88\x04\xfc\xfc\x96\xdf\xbc\x00\xcf\xc7\x18\xc5\xbf\
+\x53\x62\x83\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
 \x00\x00\x02\x7c\
 \x89\
 \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -61231,6 +61268,45 @@
 \x24\x97\xcb\x6b\xd3\x30\x87\x4a\x22\x25\x03\xc9\x64\xf2\x92\x94\
 \x32\x24\xa5\xdc\xcc\xcb\x07\x8b\xf4\xff\x53\xcc\x7a\xe6\x37\xb9\
 \xdd\x0f\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x02\x4f\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xff\x61\
+\x00\x00\x02\x16\x49\x44\x41\x54\x78\xda\xb5\x92\x5d\x48\x53\x01\
+\x14\xc7\x6f\x3d\x74\x6d\xd5\xca\xb1\xe5\x98\xd2\x96\x73\x73\x92\
+\x8d\x16\xb9\xe5\x88\x5a\xb0\x30\x86\xcd\x9a\x6b\xde\x3b\x90\x7a\
+\xa8\x66\xb1\x5c\x49\x21\x0e\x32\x11\x0c\x73\x33\xbb\x36\x65\x9b\
+\x8d\xda\xee\xdc\xb0\x9c\x33\x4a\xb4\x8f\x11\x99\x31\xca\x8f\x96\
+\xf9\x01\x7d\x3c\xf5\x56\x2f\x3e\x46\x0f\xfe\xd3\xf5\x20\xd1\x43\
+\x2d\xf0\x0f\x7f\x38\x70\xce\xef\x70\x38\xe7\x10\xab\xaa\x42\x6b\
+\x94\x90\xd1\x61\x6b\x81\x25\x78\x25\x63\x58\x56\x15\xe4\x4a\x4d\
+\xbe\xb0\xe4\xc8\x4d\x88\x0d\x6d\xc8\x08\x96\xd3\xbd\x9a\x7c\x93\
+\xf7\x73\x99\x23\x88\xee\xe1\xf7\x10\x6a\xed\xf8\x47\x30\xb2\x56\
+\x46\x85\x1b\x8a\xe8\xe0\x0f\x87\xe7\x19\x62\x93\x5f\x30\xb0\x64\
+\xde\x0e\x13\xfe\x3e\x32\xdd\x9b\x2b\xab\x62\x13\xfb\xce\xdd\x83\
+\x3b\x36\x85\xd0\x8b\x0f\x60\x47\x3f\x82\x7d\xf9\x09\x1b\xb7\x69\
+\xc1\x2d\xd0\x23\xbb\xd8\x0c\x81\xda\x86\xad\xa5\xb5\xe0\xab\xcf\
+\x2e\xac\xc0\x14\x6b\x94\x53\xc1\x6f\x96\xc6\x07\xe8\x88\x8f\xa3\
+\xeb\x51\x0a\xde\xe1\x19\xf8\x1f\xcf\xc1\xff\x64\x3e\x6d\xdf\xc8\
+\x2c\xba\x87\xa6\xc1\x0c\x4e\xc0\xd5\x37\x06\x9e\xea\x24\xd2\xb0\
+\xd4\x1c\x60\x8a\xad\xb7\x17\xcf\xb4\xc6\xd1\x74\x27\x81\x6b\x91\
+\x57\x70\xdd\x1f\x47\xc7\x60\x0a\x9d\x0f\x67\xe0\x19\x9a\x5d\x76\
+\x3a\xbe\x31\xf0\x16\xcd\xa1\x31\x58\x9d\x21\x6c\xde\x49\xfd\x6a\
+\xb0\xbd\xe2\x16\xa3\x38\xd6\xbe\x78\xfc\x72\x00\x76\x57\x1c\x4e\
+\x7f\x02\xcd\x6c\x12\xad\x7d\x53\x70\xc5\xde\xa1\xad\x7f\x1a\x2d\
+\xd1\x14\x9c\x81\x37\xb0\xb9\x13\x28\xbf\x18\x81\x86\x76\x63\x93\
+\xe2\xe8\xca\x5e\xf2\xf4\x57\xcb\x45\x07\xea\xbf\x16\x1a\x1a\xa1\
+\xaf\x09\xc0\xdc\x10\xc7\x89\x96\xa7\xa8\x69\x1f\xc5\xf9\xce\x24\
+\x1c\x9e\xd7\xb0\x33\x49\x9c\xba\xfe\x1c\x95\x4b\x39\x6d\x35\x03\
+\x8e\xf4\xf0\xef\x8b\xcd\x29\xb5\x0b\x05\x25\xa7\x47\x24\xba\x0b\
+\x30\xd6\x45\x97\x8b\xd3\x60\x7d\x4f\x0a\xeb\xb6\x48\x40\x0a\x8a\
+\x90\x25\x2a\x01\x47\x72\x10\x9c\xfc\x43\xc8\x12\xeb\x16\xfe\xb8\
+\x04\x4f\x55\xbd\x26\x5b\x49\xd5\xf1\x95\x96\xef\x65\xb6\x2e\x5c\
+\xf2\x4d\xa2\x89\x9d\x07\xc9\x57\x64\xf6\x48\x5c\xb9\x61\xd7\x06\
+\x89\x6e\x4e\x65\xa8\x85\xb3\x67\x02\x64\x8e\x12\x44\xa6\xe2\x88\
+\xf7\x73\xd6\xe7\xed\xf5\x92\xa2\x3d\x20\x85\xbb\x41\xfc\xaf\x48\
+\x91\xda\x48\xe6\x6a\xee\x12\xab\xa5\x9f\xba\xf5\x07\x44\xaf\xca\
+\xa8\xbb\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
 \x00\x00\x02\x9a\
 \x89\
 \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -82224,6 +82300,10 @@
 \x00\x73\
 \x00\x6f\x00\x6e\x00\x67\x00\x5f\x00\x73\x00\x65\x00\x61\x00\x72\x00\x63\x00\x68\x00\x5f\x00\x6c\x00\x79\x00\x72\x00\x69\x00\x63\
 \x00\x73\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x10\
+\x06\x8c\xe5\xe7\
+\x00\x73\
+\x00\x6f\x00\x6e\x00\x67\x00\x5f\x00\x73\x00\x73\x00\x5f\x00\x66\x00\x69\x00\x6e\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
 \x00\x14\
 \x07\xde\x82\x27\
 \x00\x73\
@@ -82275,6 +82355,10 @@
 \x01\x6a\xa4\x07\
 \x00\x74\
 \x00\x6f\x00\x70\x00\x69\x00\x63\x00\x5f\x00\x61\x00\x64\x00\x64\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0d\
+\x03\x57\xfd\xa7\
+\x00\x73\
+\x00\x6f\x00\x6e\x00\x67\x00\x5f\x00\x62\x00\x61\x00\x63\x00\x6b\x00\x2e\x00\x70\x00\x6e\x00\x67\
 \x00\x10\
 \x0b\xd5\xa4\x07\
 \x00\x74\
@@ -82598,10 +82682,10 @@
 
 qt_resource_struct = "\
 \x00\x00\x00\x00\x00\x02\x00\x00\x00\x12\x00\x00\x00\x01\
-\x00\x00\x00\xe6\x00\x02\x00\x00\x00\x06\x00\x00\x00\x83\
-\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x7f\
-\x00\x00\x00\xb4\x00\x02\x00\x00\x00\x03\x00\x00\x00\x7c\
-\x00\x00\x00\xd6\x00\x02\x00\x00\x00\x14\x00\x00\x00\x68\
+\x00\x00\x00\xe6\x00\x02\x00\x00\x00\x06\x00\x00\x00\x85\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x81\
+\x00\x00\x00\xb4\x00\x02\x00\x00\x00\x03\x00\x00\x00\x7e\
+\x00\x00\x00\xd6\x00\x02\x00\x00\x00\x16\x00\x00\x00\x68\
 \x00\x00\x00\x2c\x00\x02\x00\x00\x00\x02\x00\x00\x00\x66\
 \x00\x00\x00\x14\x00\x02\x00\x00\x00\x02\x00\x00\x00\x64\
 \x00\x00\x00\xf4\x00\x02\x00\x00\x00\x05\x00\x00\x00\x5f\
@@ -82621,68 +82705,68 @@
 \x00\x00\x03\xec\x00\x00\x00\x00\x00\x01\x00\x05\x65\x6d\
 \x00\x00\x04\x1a\x00\x00\x00\x00\x00\x01\x00\x08\x06\x4f\
 \x00\x00\x03\xbc\x00\x00\x00\x00\x00\x01\x00\x02\xc4\x8b\
-\x00\x00\x0f\x2c\x00\x00\x00\x00\x00\x01\x00\x13\x7f\x12\
-\x00\x00\x0f\x9c\x00\x00\x00\x00\x00\x01\x00\x13\x86\x5d\
-\x00\x00\x0e\xdc\x00\x00\x00\x00\x00\x01\x00\x13\x79\xb6\
-\x00\x00\x10\x7a\x00\x00\x00\x00\x00\x01\x00\x13\x98\xdb\
-\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x01\x00\x13\x8e\x73\
-\x00\x00\x0e\x84\x00\x00\x00\x00\x00\x01\x00\x13\x72\x7f\
-\x00\x00\x10\xcc\x00\x00\x00\x00\x00\x01\x00\x13\x9e\xe2\
-\x00\x00\x0f\xc4\x00\x00\x00\x00\x00\x01\x00\x13\x89\xd1\
-\x00\x00\x11\x1a\x00\x00\x00\x00\x00\x01\x00\x13\xa4\x0e\
-\x00\x00\x0e\xae\x00\x00\x00\x00\x00\x01\x00\x13\x75\x1d\
-\x00\x00\x10\xa6\x00\x00\x00\x00\x00\x01\x00\x13\x9c\x0e\
-\x00\x00\x10\x50\x00\x00\x00\x00\x00\x01\x00\x13\x96\x63\
-\x00\x00\x0f\x02\x00\x00\x00\x00\x00\x01\x00\x13\x7c\x90\
-\x00\x00\x10\xf6\x00\x00\x00\x00\x00\x01\x00\x13\xa1\xc7\
-\x00\x00\x10\x24\x00\x00\x00\x00\x00\x01\x00\x13\x91\xb8\
-\x00\x00\x0f\x78\x00\x00\x00\x00\x00\x01\x00\x13\x83\x60\
-\x00\x00\x0f\x52\x00\x00\x00\x00\x00\x01\x00\x13\x81\x49\
+\x00\x00\x0f\x72\x00\x00\x00\x00\x00\x01\x00\x13\x83\x99\
+\x00\x00\x0f\xe2\x00\x00\x00\x00\x00\x01\x00\x13\x8a\xe4\
+\x00\x00\x0f\x22\x00\x00\x00\x00\x00\x01\x00\x13\x7e\x3d\
+\x00\x00\x10\xc0\x00\x00\x00\x00\x00\x01\x00\x13\x9d\x62\
+\x00\x00\x10\x42\x00\x00\x00\x00\x00\x01\x00\x13\x92\xfa\
+\x00\x00\x0e\xca\x00\x00\x00\x00\x00\x01\x00\x13\x77\x06\
+\x00\x00\x11\x12\x00\x00\x00\x00\x00\x01\x00\x13\xa3\x69\
+\x00\x00\x10\x0a\x00\x00\x00\x00\x00\x01\x00\x13\x8e\x58\
+\x00\x00\x11\x60\x00\x00\x00\x00\x00\x01\x00\x13\xa8\x95\
+\x00\x00\x0e\xf4\x00\x00\x00\x00\x00\x01\x00\x13\x79\xa4\
+\x00\x00\x10\xec\x00\x00\x00\x00\x00\x01\x00\x13\xa0\x95\
+\x00\x00\x10\x96\x00\x00\x00\x00\x00\x01\x00\x13\x9a\xea\
+\x00\x00\x0f\x48\x00\x00\x00\x00\x00\x01\x00\x13\x81\x17\
+\x00\x00\x11\x3c\x00\x00\x00\x00\x00\x01\x00\x13\xa6\x4e\
+\x00\x00\x10\x6a\x00\x00\x00\x00\x00\x01\x00\x13\x96\x3f\
+\x00\x00\x0f\xbe\x00\x00\x00\x00\x00\x01\x00\x13\x87\xe7\
+\x00\x00\x0f\x98\x00\x00\x00\x00\x00\x01\x00\x13\x85\xd0\
 \x00\x00\x03\x66\x00\x00\x00\x00\x00\x01\x00\x00\x21\x92\
-\x00\x00\x0b\x44\x00\x00\x00\x00\x00\x01\x00\x11\xef\x19\
-\x00\x00\x0b\xc4\x00\x00\x00\x00\x00\x01\x00\x11\xf5\xdf\
-\x00\x00\x0a\xc8\x00\x00\x00\x00\x00\x01\x00\x11\xe8\x15\
-\x00\x00\x0b\x6c\x00\x00\x00\x00\x00\x01\x00\x11\xf1\xb9\
-\x00\x00\x0b\xee\x00\x00\x00\x00\x00\x01\x00\x11\xf8\xaa\
-\x00\x00\x0b\x12\x00\x00\x00\x00\x00\x01\x00\x11\xed\x2f\
-\x00\x00\x0a\xec\x00\x00\x00\x00\x00\x01\x00\x11\xea\xbc\
-\x00\x00\x0b\xa2\x00\x00\x00\x00\x00\x01\x00\x11\xf3\x3b\
+\x00\x00\x0b\x8a\x00\x00\x00\x00\x00\x01\x00\x11\xf3\xa0\
+\x00\x00\x0c\x0a\x00\x00\x00\x00\x00\x01\x00\x11\xfa\x66\
+\x00\x00\x0b\x0e\x00\x00\x00\x00\x00\x01\x00\x11\xec\x9c\
+\x00\x00\x0b\xb2\x00\x00\x00\x00\x00\x01\x00\x11\xf6\x40\
+\x00\x00\x0c\x34\x00\x00\x00\x00\x00\x01\x00\x11\xfd\x31\
+\x00\x00\x0b\x58\x00\x00\x00\x00\x00\x01\x00\x11\xf1\xb6\
+\x00\x00\x0b\x32\x00\x00\x00\x00\x00\x01\x00\x11\xef\x43\
+\x00\x00\x0b\xe8\x00\x00\x00\x00\x00\x01\x00\x11\xf7\xc2\
 \x00\x00\x01\x5c\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
 \x00\x00\x01\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x05\xe6\
 \x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x02\xfe\
-\x00\x00\x0d\xd4\x00\x00\x00\x00\x00\x01\x00\x12\x13\xf8\
-\x00\x00\x0d\xfe\x00\x00\x00\x00\x00\x01\x00\x12\x1d\x84\
-\x00\x00\x0e\x2e\x00\x00\x00\x00\x00\x01\x00\x12\x8c\xc9\
-\x00\x00\x0e\x4e\x00\x00\x00\x00\x00\x01\x00\x12\x93\x7a\
-\x00\x00\x11\x9c\x00\x00\x00\x00\x00\x01\x00\x13\xab\x22\
-\x00\x00\x11\x42\x00\x00\x00\x00\x00\x01\x00\x13\xa6\x21\
-\x00\x00\x13\xba\x00\x00\x00\x00\x00\x01\x00\x13\xd0\x31\
-\x00\x00\x12\x0e\x00\x00\x00\x00\x00\x01\x00\x13\xb1\xaf\
-\x00\x00\x11\x68\x00\x00\x00\x00\x00\x01\x00\x13\xa9\x52\
-\x00\x00\x13\x0c\x00\x00\x00\x00\x00\x01\x00\x13\xc1\x0c\
-\x00\x00\x12\xaa\x00\x00\x00\x00\x00\x01\x00\x13\xb8\xdc\
-\x00\x00\x13\xe0\x00\x00\x00\x00\x00\x01\x00\x13\xd3\x13\
-\x00\x00\x13\x86\x00\x00\x00\x00\x00\x01\x00\x13\xcc\x54\
-\x00\x00\x12\xd6\x00\x00\x00\x00\x00\x01\x00\x13\xbd\xe8\
-\x00\x00\x14\x12\x00\x00\x00\x00\x00\x01\x00\x13\xd6\xd0\
-\x00\x00\x11\xde\x00\x00\x00\x00\x00\x01\x00\x13\xae\x75\
-\x00\x00\x13\x2e\x00\x00\x00\x00\x00\x01\x00\x13\xc5\x7b\
-\x00\x00\x12\x72\x00\x00\x00\x00\x00\x01\x00\x13\xb6\x66\
-\x00\x00\x13\x5c\x00\x00\x00\x00\x00\x01\x00\x13\xc9\xcc\
-\x00\x00\x12\x3c\x00\x00\x00\x00\x00\x01\x00\x13\xb3\xb6\
-\x00\x00\x0a\x10\x00\x00\x00\x00\x00\x01\x00\x0e\xec\xf7\
-\x00\x00\x0a\x30\x00\x00\x00\x00\x00\x01\x00\x0e\xf0\xd4\
-\x00\x00\x09\xea\x00\x00\x00\x00\x00\x01\x00\x0e\xea\x59\
-\x00\x00\x0c\xb2\x00\x00\x00\x00\x00\x01\x00\x12\x02\xc6\
-\x00\x00\x0d\x50\x00\x00\x00\x00\x00\x01\x00\x12\x0d\x3b\
-\x00\x00\x0d\xaa\x00\x00\x00\x00\x00\x01\x00\x12\x11\xf4\
-\x00\x00\x0c\x48\x00\x00\x00\x00\x00\x01\x00\x11\xfe\xd6\
-\x00\x00\x0d\x2c\x00\x00\x00\x00\x00\x01\x00\x12\x0a\x08\
-\x00\x00\x0c\x7c\x00\x00\x00\x00\x00\x01\x00\x12\x00\xcd\
-\x00\x00\x0c\xe6\x00\x00\x00\x00\x00\x01\x00\x12\x04\xc4\
-\x00\x00\x0d\x08\x00\x00\x00\x00\x00\x01\x00\x12\x06\xd7\
-\x00\x00\x0d\x86\x00\x00\x00\x00\x00\x01\x00\x12\x0f\x23\
-\x00\x00\x0c\x20\x00\x00\x00\x00\x00\x01\x00\x11\xfc\x1a\
+\x00\x00\x0e\x1a\x00\x00\x00\x00\x00\x01\x00\x12\x18\x7f\
+\x00\x00\x0e\x44\x00\x00\x00\x00\x00\x01\x00\x12\x22\x0b\
+\x00\x00\x0e\x74\x00\x00\x00\x00\x00\x01\x00\x12\x91\x50\
+\x00\x00\x0e\x94\x00\x00\x00\x00\x00\x01\x00\x12\x98\x01\
+\x00\x00\x11\xe2\x00\x00\x00\x00\x00\x01\x00\x13\xaf\xa9\
+\x00\x00\x11\x88\x00\x00\x00\x00\x00\x01\x00\x13\xaa\xa8\
+\x00\x00\x14\x00\x00\x00\x00\x00\x00\x01\x00\x13\xd4\xb8\
+\x00\x00\x12\x54\x00\x00\x00\x00\x00\x01\x00\x13\xb6\x36\
+\x00\x00\x11\xae\x00\x00\x00\x00\x00\x01\x00\x13\xad\xd9\
+\x00\x00\x13\x52\x00\x00\x00\x00\x00\x01\x00\x13\xc5\x93\
+\x00\x00\x12\xf0\x00\x00\x00\x00\x00\x01\x00\x13\xbd\x63\
+\x00\x00\x14\x26\x00\x00\x00\x00\x00\x01\x00\x13\xd7\x9a\
+\x00\x00\x13\xcc\x00\x00\x00\x00\x00\x01\x00\x13\xd0\xdb\
+\x00\x00\x13\x1c\x00\x00\x00\x00\x00\x01\x00\x13\xc2\x6f\
+\x00\x00\x14\x58\x00\x00\x00\x00\x00\x01\x00\x13\xdb\x57\
+\x00\x00\x12\x24\x00\x00\x00\x00\x00\x01\x00\x13\xb2\xfc\
+\x00\x00\x13\x74\x00\x00\x00\x00\x00\x01\x00\x13\xca\x02\
+\x00\x00\x12\xb8\x00\x00\x00\x00\x00\x01\x00\x13\xba\xed\
+\x00\x00\x13\xa2\x00\x00\x00\x00\x00\x01\x00\x13\xce\x53\
+\x00\x00\x12\x82\x00\x00\x00\x00\x00\x01\x00\x13\xb8\x3d\
+\x00\x00\x0a\x56\x00\x00\x00\x00\x00\x01\x00\x0e\xf1\x7e\
+\x00\x00\x0a\x76\x00\x00\x00\x00\x00\x01\x00\x0e\xf5\x5b\
+\x00\x00\x0a\x30\x00\x00\x00\x00\x00\x01\x00\x0e\xee\xe0\
+\x00\x00\x0c\xf8\x00\x00\x00\x00\x00\x01\x00\x12\x07\x4d\
+\x00\x00\x0d\x96\x00\x00\x00\x00\x00\x01\x00\x12\x11\xc2\
+\x00\x00\x0d\xf0\x00\x00\x00\x00\x00\x01\x00\x12\x16\x7b\
+\x00\x00\x0c\x8e\x00\x00\x00\x00\x00\x01\x00\x12\x03\x5d\
+\x00\x00\x0d\x72\x00\x00\x00\x00\x00\x01\x00\x12\x0e\x8f\
+\x00\x00\x0c\xc2\x00\x00\x00\x00\x00\x01\x00\x12\x05\x54\
+\x00\x00\x0d\x2c\x00\x00\x00\x00\x00\x01\x00\x12\x09\x4b\
+\x00\x00\x0d\x4e\x00\x00\x00\x00\x00\x01\x00\x12\x0b\x5e\
+\x00\x00\x0d\xcc\x00\x00\x00\x00\x00\x01\x00\x12\x13\xaa\
+\x00\x00\x0c\x66\x00\x00\x00\x00\x00\x01\x00\x12\x00\xa1\
 \x00\x00\x02\xee\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x20\
 \x00\x00\x02\x72\x00\x00\x00\x00\x00\x01\x00\x00\x11\xc5\
 \x00\x00\x02\x16\x00\x00\x00\x00\x00\x01\x00\x00\x0c\x03\
@@ -82697,37 +82781,39 @@
 \x00\x00\x04\xb8\x00\x00\x00\x00\x00\x01\x00\x0d\x50\x06\
 \x00\x00\x05\x52\x00\x00\x00\x00\x00\x01\x00\x0d\x56\x1f\
 \x00\x00\x05\x20\x00\x00\x00\x00\x00\x01\x00\x0d\x54\x57\
-\x00\x00\x14\x7a\x00\x00\x00\x00\x00\x01\x00\x13\xe0\x04\
-\x00\x00\x14\xae\x00\x00\x00\x00\x00\x01\x00\x13\xe2\xd4\
-\x00\x00\x14\x36\x00\x00\x00\x00\x00\x01\x00\x13\xda\x83\
-\x00\x00\x14\x5a\x00\x00\x00\x00\x00\x01\x00\x13\xdd\x81\
+\x00\x00\x14\xc0\x00\x00\x00\x00\x00\x01\x00\x13\xe4\x8b\
+\x00\x00\x14\xf4\x00\x00\x00\x00\x00\x01\x00\x13\xe7\x5b\
+\x00\x00\x14\x7c\x00\x00\x00\x00\x00\x01\x00\x13\xdf\x0a\
+\x00\x00\x14\xa0\x00\x00\x00\x00\x00\x01\x00\x13\xe2\x08\
 \x00\x00\x06\xde\x00\x00\x00\x00\x00\x01\x00\x0e\xaa\x8e\
 \x00\x00\x07\xc4\x00\x00\x00\x00\x00\x01\x00\x0e\xbb\x82\
-\x00\x00\x09\xca\x00\x00\x00\x00\x00\x01\x00\x0e\xe6\x66\
-\x00\x00\x09\x98\x00\x00\x00\x00\x00\x01\x00\x0e\xdf\x50\
-\x00\x00\x08\x7e\x00\x00\x00\x00\x00\x01\x00\x0e\xc4\x50\
-\x00\x00\x09\x1e\x00\x00\x00\x00\x00\x01\x00\x0e\xd7\x0f\
-\x00\x00\x09\x48\x00\x00\x00\x00\x00\x01\x00\x0e\xd9\x44\
+\x00\x00\x09\xf0\x00\x00\x00\x00\x00\x01\x00\x0e\xe8\x9a\
+\x00\x00\x09\xbe\x00\x00\x00\x00\x00\x01\x00\x0e\xe1\x84\
+\x00\x00\x0a\x10\x00\x00\x00\x00\x00\x01\x00\x0e\xec\x8d\
+\x00\x00\x08\xa4\x00\x00\x00\x00\x00\x01\x00\x0e\xc6\x84\
 \x00\x00\x08\x1e\x00\x00\x00\x00\x00\x01\x00\x0e\xc0\x33\
-\x00\x00\x08\x4c\x00\x00\x00\x00\x00\x01\x00\x0e\xc2\xb3\
+\x00\x00\x09\x44\x00\x00\x00\x00\x00\x01\x00\x0e\xd9\x43\
+\x00\x00\x09\x6e\x00\x00\x00\x00\x00\x01\x00\x0e\xdb\x78\
+\x00\x00\x08\x44\x00\x00\x00\x00\x00\x01\x00\x0e\xc2\x67\
+\x00\x00\x08\x72\x00\x00\x00\x00\x00\x01\x00\x0e\xc4\xe7\
 \x00\x00\x07\x52\x00\x00\x00\x00\x00\x01\x00\x0e\xb4\x35\
 \x00\x00\x07\xa4\x00\x00\x00\x00\x00\x01\x00\x0e\xb8\x76\
 \x00\x00\x07\xec\x00\x00\x00\x00\x00\x01\x00\x0e\xbe\xe0\
-\x00\x00\x08\xd0\x00\x00\x00\x00\x00\x01\x00\x0e\xca\xc5\
-\x00\x00\x08\xa4\x00\x00\x00\x00\x00\x01\x00\x0e\xc8\x62\
-\x00\x00\x09\x6a\x00\x00\x00\x00\x00\x01\x00\x0e\xdd\x48\
+\x00\x00\x08\xf6\x00\x00\x00\x00\x00\x01\x00\x0e\xcc\xf9\
+\x00\x00\x08\xca\x00\x00\x00\x00\x00\x01\x00\x0e\xca\x96\
+\x00\x00\x09\x90\x00\x00\x00\x00\x00\x01\x00\x0e\xdf\x7c\
 \x00\x00\x06\xb0\x00\x00\x00\x00\x00\x01\x00\x0e\xa3\xd0\
 \x00\x00\x07\x02\x00\x00\x00\x00\x00\x01\x00\x0e\xad\x7a\
 \x00\x00\x07\x2e\x00\x00\x00\x00\x00\x01\x00\x0e\xb0\xbc\
 \x00\x00\x07\x82\x00\x00\x00\x00\x00\x01\x00\x0e\xb5\x2e\
-\x00\x00\x08\xee\x00\x00\x00\x00\x00\x01\x00\x0e\xcd\x67\
-\x00\x00\x0a\x74\x00\x00\x00\x00\x00\x01\x00\x0e\xf7\xe1\
-\x00\x00\x0a\x52\x00\x00\x00\x00\x00\x01\x00\x0e\xf4\x0e\
-\x00\x00\x0a\xa6\x00\x00\x00\x00\x00\x01\x00\x11\xe5\x3f\
-\x00\x00\x14\xde\x00\x00\x00\x00\x00\x01\x00\x13\xe5\xcd\
-\x00\x00\x15\x40\x00\x00\x00\x00\x00\x01\x00\x13\xec\x43\
-\x00\x00\x15\x12\x00\x00\x00\x00\x00\x01\x00\x13\xe9\x2f\
-\x00\x00\x15\x68\x00\x00\x00\x00\x00\x01\x00\x13\xee\xe1\
+\x00\x00\x09\x14\x00\x00\x00\x00\x00\x01\x00\x0e\xcf\x9b\
+\x00\x00\x0a\xba\x00\x00\x00\x00\x00\x01\x00\x0e\xfc\x68\
+\x00\x00\x0a\x98\x00\x00\x00\x00\x00\x01\x00\x0e\xf8\x95\
+\x00\x00\x0a\xec\x00\x00\x00\x00\x00\x01\x00\x11\xe9\xc6\
+\x00\x00\x15\x24\x00\x00\x00\x00\x00\x01\x00\x13\xea\x54\
+\x00\x00\x15\x86\x00\x00\x00\x00\x00\x01\x00\x13\xf0\xca\
+\x00\x00\x15\x58\x00\x00\x00\x00\x00\x01\x00\x13\xed\xb6\
+\x00\x00\x15\xae\x00\x00\x00\x00\x00\x01\x00\x13\xf3\x68\
 \x00\x00\x06\x18\x00\x00\x00\x00\x00\x01\x00\x0d\x91\xaf\
 \x00\x00\x05\xb8\x00\x00\x00\x00\x00\x01\x00\x0d\x62\x6f\
 \x00\x00\x05\x88\x00\x00\x00\x00\x00\x01\x00\x0d\x57\xdb\

=== modified file 'openlp/core/ui/__init__.py'
--- openlp/core/ui/__init__.py	2011-12-27 10:33:55 +0000
+++ openlp/core/ui/__init__.py	2012-05-26 18:22:20 +0000
@@ -52,6 +52,7 @@
     Theme = 2
     Screen = 3
 
+
 class AlertLocation(object):
     """
     This is an enumeration class which controls where Alerts are placed on the
@@ -70,6 +71,29 @@
     Middle = 1
     Bottom = 2
 
+
+class SingleColumnTableWidget(QtGui.QTableWidget):
+    """
+    Class to for a single column table widget to use for song verses.
+    """
+    def __init__(self, parent):
+        """
+        Constructor
+        """
+        QtGui.QTableWidget.__init__(self, parent)
+        self.horizontalHeader().setVisible(False)
+        self.setColumnCount(1)
+
+    def resizeEvent(self, event):
+        """
+        Resize the first column together with the widget.
+        """
+        QtGui.QTableWidget.resizeEvent(self, event)
+        if self.columnCount():
+            self.setColumnWidth(0, event.size().width())
+            self.resizeRowsToContents()
+
+
 from firsttimeform import FirstTimeForm
 from firsttimelanguageform import FirstTimeLanguageForm
 from themelayoutform import ThemeLayoutForm

=== modified file 'openlp/plugins/songs/forms/__init__.py'
--- openlp/plugins/songs/forms/__init__.py	2011-12-27 10:33:55 +0000
+++ openlp/plugins/songs/forms/__init__.py	2012-05-26 18:22:20 +0000
@@ -61,4 +61,4 @@
 from songmaintenanceform import SongMaintenanceForm
 from songimportform import SongImportForm
 from songexportform import SongExportForm
-
+from songselectform import SongSelectForm

=== modified file 'openlp/plugins/songs/forms/authorsdialog.py'
--- openlp/plugins/songs/forms/authorsdialog.py	2012-04-01 22:44:09 +0000
+++ openlp/plugins/songs/forms/authorsdialog.py	2012-05-26 18:22:20 +0000
@@ -25,7 +25,7 @@
 # Temple Place, Suite 330, Boston, MA 02111-1307 USA                          #
 ###############################################################################
 
-from PyQt4 import QtCore, QtGui
+from PyQt4 import QtGui
 
 from openlp.core.lib import translate
 from openlp.core.lib.ui import create_button_box

=== modified file 'openlp/plugins/songs/forms/editsongdialog.py'
--- openlp/plugins/songs/forms/editsongdialog.py	2012-04-15 10:16:01 +0000
+++ openlp/plugins/songs/forms/editsongdialog.py	2012-05-26 18:22:20 +0000
@@ -29,6 +29,7 @@
 
 from openlp.core.lib import build_icon, translate
 from openlp.core.lib.ui import UiStrings, create_button_box, create_button
+from openlp.core.ui import SingleColumnTableWidget
 from openlp.plugins.songs.lib.ui import SongStrings
 
 class Ui_EditSongDialog(object):
@@ -370,24 +371,3 @@
     comboBox.setInsertPolicy(QtGui.QComboBox.NoInsert)
     comboBox.setObjectName(name)
     return comboBox
-
-class SingleColumnTableWidget(QtGui.QTableWidget):
-    """
-    Class to for a single column table widget to use for the verse table widget.
-    """
-    def __init__(self, parent):
-        """
-        Constructor
-        """
-        QtGui.QTableWidget.__init__(self, parent)
-        self.horizontalHeader().setVisible(False)
-        self.setColumnCount(1)
-
-    def resizeEvent(self, event):
-        """
-        Resize the first column together with the widget.
-        """
-        QtGui.QTableWidget.resizeEvent(self, event)
-        if self.columnCount():
-            self.setColumnWidth(0, event.size().width())
-            self.resizeRowsToContents()

=== added file 'openlp/plugins/songs/forms/songselectdialog.py'
--- openlp/plugins/songs/forms/songselectdialog.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/forms/songselectdialog.py	2012-05-26 18:22:20 +0000
@@ -0,0 +1,263 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2012 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan,      #
+# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias     #
+# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,    #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, 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 translate, build_icon
+from openlp.core.ui import SingleColumnTableWidget
+
+class Ui_SongSelectDialog(object):
+    """
+    The actual Qt components that make up the dialog.
+    """
+    def setupUi(self, songSelectDialog):
+        songSelectDialog.setObjectName(u'SongsPlugin.SongSelectForm')
+        songSelectDialog.resize(616, 378)
+        self.songSelectLayout = QtGui.QVBoxLayout(songSelectDialog)
+        self.songSelectLayout.setSpacing(0)
+        self.songSelectLayout.setMargin(0)
+        self.songSelectLayout.setObjectName(u'songSelectLayout')
+        self.stackedWidget = QtGui.QStackedWidget(songSelectDialog)
+        self.stackedWidget.setObjectName(u'stackedWidget')
+        self.loginPage = QtGui.QWidget()
+        self.loginPage.setObjectName(u'loginPage')
+        self.loginLayout = QtGui.QFormLayout(self.loginPage)
+        self.loginLayout.setContentsMargins(150, 100, 150, 100)
+        self.loginLayout.setSpacing(8)
+        self.loginLayout.setObjectName(u'loginLayout')
+        self.noticeLayout = QtGui.QHBoxLayout()
+        self.noticeLayout.setObjectName(u'noticeLayout')
+        self.noticeLabel = QtGui.QLabel(self.loginPage)
+        self.noticeLabel.setWordWrap(True)
+        self.noticeLabel.setObjectName(u'noticeLabel')
+        self.noticeLayout.addWidget(self.noticeLabel)
+        self.loginLayout.setLayout(0,
+            QtGui.QFormLayout.SpanningRole, self.noticeLayout)
+        self.usernameLabel = QtGui.QLabel(self.loginPage)
+        self.usernameLabel.setObjectName(u'usernameLabel')
+        self.loginLayout.setWidget(1,
+            QtGui.QFormLayout.LabelRole, self.usernameLabel)
+        self.usernameEdit = QtGui.QLineEdit(self.loginPage)
+        self.usernameEdit.setObjectName(u'usernameEdit')
+        self.loginLayout.setWidget(1,
+            QtGui.QFormLayout.FieldRole, self.usernameEdit)
+        self.passwordLabel = QtGui.QLabel(self.loginPage)
+        self.passwordLabel.setObjectName(u'passwordLabel')
+        self.loginLayout.setWidget(2,
+            QtGui.QFormLayout.LabelRole, self.passwordLabel)
+        self.passwordEdit = QtGui.QLineEdit(self.loginPage)
+        self.passwordEdit.setEchoMode(QtGui.QLineEdit.Password)
+        self.passwordEdit.setObjectName(u'passwordEdit')
+        self.loginLayout.setWidget(2,
+            QtGui.QFormLayout.FieldRole, self.passwordEdit)
+        self.loginButtonLayout = QtGui.QHBoxLayout()
+        self.loginButtonLayout.setSpacing(8)
+        self.loginButtonLayout.setContentsMargins(0, -1, -1, -1)
+        self.loginButtonLayout.setObjectName(u'loginButtonLayout')
+        self.loginSpacer = QtGui.QWidget(self.loginPage)
+        self.loginSpacer.setSizePolicy(
+            QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+        self.loginSpacer.setObjectName(u'loginSpacer')
+        self.loginButtonLayout.addWidget(self.loginSpacer)
+        self.loginProgressBar = QtGui.QProgressBar(self.loginPage)
+        self.loginProgressBar.setMinimum(0)
+        self.loginProgressBar.setMaximum(3)
+        self.loginProgressBar.setValue(0)
+        self.loginProgressBar.setMinimumWidth(200)
+        self.loginProgressBar.setVisible(False)
+        self.loginButtonLayout.addWidget(self.loginProgressBar)
+        self.loginButton = QtGui.QPushButton(self.loginPage)
+        self.loginButton.setIcon(build_icon(u':/songs/song_author_edit.png'))
+        self.loginButton.setObjectName(u'loginButton')
+        self.loginButtonLayout.addWidget(self.loginButton)
+        self.loginLayout.setLayout(3,
+            QtGui.QFormLayout.SpanningRole, self.loginButtonLayout)
+        self.stackedWidget.addWidget(self.loginPage)
+        self.searchPage = QtGui.QWidget()
+        self.searchPage.setObjectName(u'searchPage')
+        self.searchLayout = QtGui.QVBoxLayout(self.searchPage)
+        self.searchLayout.setSpacing(8)
+        self.searchLayout.setMargin(8)
+        self.searchLayout.setObjectName(u'searchLayout')
+        self.searchInputLayout = QtGui.QHBoxLayout()
+        self.searchInputLayout.setSpacing(8)
+        self.searchInputLayout.setObjectName(u'searchInputLayout')
+        self.searchLabel = QtGui.QLabel(self.searchPage)
+        self.searchLabel.setObjectName(u'searchLabel')
+        self.searchInputLayout.addWidget(self.searchLabel)
+        self.searchEdit = QtGui.QLineEdit(self.searchPage)
+        self.searchEdit.setObjectName(u'searchEdit')
+        self.searchInputLayout.addWidget(self.searchEdit)
+        self.searchButton = QtGui.QPushButton(self.searchPage)
+        self.searchButton.setIcon(build_icon(u':/songs/song_ss_find.png'))
+        self.searchButton.setObjectName(u'searchButton')
+        self.searchInputLayout.addWidget(self.searchButton)
+        self.searchLayout.addLayout(self.searchInputLayout)
+        self.searchProgressBar = QtGui.QProgressBar(self.searchPage)
+        self.searchProgressBar.setMinimum(0)
+        self.searchProgressBar.setMaximum(3)
+        self.searchProgressBar.setValue(0)
+        self.searchProgressBar.setVisible(False)
+        self.searchLayout.addWidget(self.searchProgressBar)
+        self.searchResultsWidget = QtGui.QListWidget(self.searchPage)
+        self.searchResultsWidget.setProperty("showDropIndicator", False)
+        self.searchResultsWidget.setAlternatingRowColors(True)
+        self.searchResultsWidget.setSelectionMode(
+            QtGui.QAbstractItemView.ExtendedSelection)
+        self.searchResultsWidget.setSelectionBehavior(
+            QtGui.QAbstractItemView.SelectRows)
+        self.searchResultsWidget.setObjectName(u'searchResultsWidget')
+        self.searchLayout.addWidget(self.searchResultsWidget)
+        self.viewLayout = QtGui.QHBoxLayout()
+        self.viewLayout.setSpacing(8)
+        self.viewLayout.setObjectName(u'viewLayout')
+        self.logoutButton = QtGui.QPushButton(self.searchPage)
+        self.logoutButton.setIcon(build_icon(u':/songs/song_author_edit.png'))
+        self.viewLayout.addWidget(self.logoutButton)
+        self.viewSpacer = QtGui.QSpacerItem(40, 20,
+            QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+        self.viewLayout.addItem(self.viewSpacer)
+        self.viewButton = QtGui.QPushButton(self.searchPage)
+        self.viewButton.setIcon(build_icon(u':/songs/song_search_all.png'))
+        self.viewButton.setObjectName(u'viewButton')
+        self.viewLayout.addWidget(self.viewButton)
+        self.searchLayout.addLayout(self.viewLayout)
+        self.stackedWidget.addWidget(self.searchPage)
+        self.songPage = QtGui.QWidget()
+        self.songPage.setObjectName(u'songPage')
+        self.songLayout = QtGui.QGridLayout(self.songPage)
+        self.songLayout.setMargin(8)
+        self.songLayout.setSpacing(8)
+        self.songLayout.setObjectName(u'songLayout')
+        self.titleLabel = QtGui.QLabel(self.songPage)
+        self.titleLabel.setObjectName(u'titleLabel')
+        self.songLayout.addWidget(self.titleLabel, 0, 0, 1, 1)
+        self.titleEdit = QtGui.QLineEdit(self.songPage)
+        self.titleEdit.setReadOnly(True)
+        self.titleEdit.setObjectName(u'titleEdit')
+        self.songLayout.addWidget(self.titleEdit, 0, 1, 1, 1)
+        self.authorsLabel = QtGui.QLabel(self.songPage)
+        self.authorsLabel.setObjectName(u'authorsLabel')
+        self.songLayout.addWidget(self.authorsLabel, 0, 2, 1, 1)
+        self.authorListWidget = QtGui.QListWidget(self.songPage)
+        self.authorListWidget.setObjectName(u'authorListWidget')
+        self.songLayout.addWidget(self.authorListWidget, 0, 3, 3, 1)
+        self.copyrightLabel = QtGui.QLabel(self.songPage)
+        self.copyrightLabel.setObjectName(u'copyrightLabel')
+        self.songLayout.addWidget(self.copyrightLabel, 1, 0, 1, 1)
+        self.copyrightEdit = QtGui.QLineEdit(self.songPage)
+        self.copyrightEdit.setReadOnly(True)
+        self.copyrightEdit.setObjectName(u'copyrightEdit')
+        self.songLayout.addWidget(self.copyrightEdit, 1, 1, 1, 1)
+        self.ccliLabel = QtGui.QLabel(self.songPage)
+        self.ccliLabel.setObjectName(u'ccliLabel')
+        self.songLayout.addWidget(self.ccliLabel, 2, 0, 1, 1)
+        self.ccliEdit = QtGui.QLineEdit(self.songPage)
+        self.ccliEdit.setReadOnly(True)
+        self.ccliEdit.setObjectName(u'ccliEdit')
+        self.songLayout.addWidget(self.ccliEdit, 2, 1, 1, 1)
+        self.lyricsLabel = QtGui.QLabel(self.songPage)
+        self.lyricsLabel.setAlignment(
+            QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
+        self.lyricsLabel.setObjectName(u'lyricsLabel')
+        self.songLayout.addWidget(self.lyricsLabel, 3, 0, 1, 1)
+        self.lyricsTableWidget = SingleColumnTableWidget(self.songPage)
+        self.lyricsTableWidget.setObjectName(u'lyricsTableWidget')
+        self.lyricsTableWidget.setRowCount(0)
+        self.songLayout.addWidget(self.lyricsTableWidget, 3, 1, 1, 3)
+        self.songProgressBar = QtGui.QProgressBar(self.songPage)
+        self.songProgressBar.setMinimum(0)
+        self.songProgressBar.setMaximum(3)
+        self.songProgressBar.setValue(0)
+        self.songProgressBar.setVisible(False)
+        self.songLayout.addWidget(self.songProgressBar, 4, 0, 1, 4)
+        self.importLayout = QtGui.QHBoxLayout()
+        self.importLayout.setObjectName(u'saveLayout')
+        self.backButton = QtGui.QPushButton(self.songPage)
+        self.backButton.setIcon(build_icon(u':/songs/song_back.png'))
+        self.backButton.setObjectName(u'backButton')
+        self.importLayout.addWidget(self.backButton)
+        self.importSpacer = QtGui.QSpacerItem(40, 20,
+            QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
+        self.importLayout.addItem(self.importSpacer)
+        self.importButton = QtGui.QPushButton(self.songPage)
+        self.importButton.setIcon(build_icon(u':/general/general_import.png'))
+        self.importButton.setObjectName(u'saveButton')
+        self.importLayout.addWidget(self.importButton)
+        self.songLayout.addLayout(self.importLayout, 5, 0, 1, 5)
+        self.stackedWidget.addWidget(self.songPage)
+        self.songSelectLayout.addWidget(self.stackedWidget)
+        self.usernameLabel.setBuddy(self.usernameEdit)
+        self.passwordLabel.setBuddy(self.passwordEdit)
+        self.titleLabel.setBuddy(self.titleEdit)
+        self.authorsLabel.setBuddy(self.authorListWidget)
+        self.copyrightLabel.setBuddy(self.copyrightEdit)
+        self.ccliLabel.setBuddy(self.ccliEdit)
+        self.lyricsLabel.setBuddy(self.lyricsTableWidget)
+
+        self.retranslateUi(songSelectDialog)
+        self.stackedWidget.setCurrentIndex(0)
+
+    def retranslateUi(self, songSelectDialog):
+        """
+        Translate the GUI.
+        """
+        songSelectDialog.setWindowTitle(
+            translate('SongsPlugin.SongSelectForm',
+                'CCLI SongSelect Importer'))
+        self.noticeLabel.setText(
+            translate('SongsPlugin.SongSelectForm', '<strong>Note:</strong> '
+                'An Internet connection is required in order to import songs '
+                'from CCLI SongSelect.'))
+        self.usernameLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Username:'))
+        self.passwordLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Password:'))
+        self.loginButton.setText(
+            translate('SongsPlugin.SongSelectForm', 'Login'))
+        self.searchLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Search Text:'))
+        self.searchButton.setText(
+            translate('SongsPlugin.SongSelectForm', 'Search'))
+        self.logoutButton.setText(
+            translate('SongsPlugin.SongSelectForm', 'Logout'))
+        self.viewButton.setText(
+            translate('SongsPlugin.SongSelectForm', 'View'))
+        self.titleLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Title:'))
+        self.authorsLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Author(s):'))
+        self.copyrightLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Copyright:'))
+        self.ccliLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'CCLI Number:'))
+        self.lyricsLabel.setText(
+            translate('SongsPlugin.SongSelectForm', 'Lyrics:'))
+        self.backButton.setText(
+            translate('SongsPlugin.SongSelectForm', 'Back'))
+        self.importButton.setText(
+            translate('SongsPlugin.SongSelectForm', 'Import'))

=== added file 'openlp/plugins/songs/forms/songselectform.py'
--- openlp/plugins/songs/forms/songselectform.py	1970-01-01 00:00:00 +0000
+++ openlp/plugins/songs/forms/songselectform.py	2012-05-26 18:22:20 +0000
@@ -0,0 +1,336 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection                                      #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2012 Raoul Snyman                                        #
+# Portions copyright (c) 2008-2012 Tim Bentley, Gerald Britton, Jonathan      #
+# Corwin, Michael Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan,      #
+# Armin Köhler, Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias     #
+# Põldaru, Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith,    #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, 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
+from cookielib import CookieJar
+from urllib import urlencode
+from urllib2 import HTTPCookieProcessor, HTTPError, build_opener
+from HTMLParser import HTMLParser
+
+from PyQt4 import QtCore, QtGui
+from BeautifulSoup import BeautifulSoup, NavigableString
+
+from openlp.core.lib import translate
+from openlp.core.lib.eventreceiver import Receiver
+from openlp.plugins.songs.lib import VerseType, clean_song
+from openlp.plugins.songs.forms.songselectdialog import Ui_SongSelectDialog
+from openlp.plugins.songs.lib.ui import SongStrings
+from openlp.plugins.songs.lib.db import Author, Song
+from openlp.plugins.songs.lib.xml import SongXML
+
+USER_AGENT = 'Mozilla/5.0 (Linux; U; Android 4.0.3; nl-nl; GT-I9000 ' \
+    'Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 ' \
+    'Mobile Safari/534.30'
+BASE_URL = 'https://mobile.songselect.com'
+LOGIN_URL = BASE_URL + '/account/login'
+LOGOUT_URL = BASE_URL + '/account/logout'
+SEARCH_URL = BASE_URL + '/search/results'
+
+log = logging.getLogger(__name__)
+
+class SongSelectForm(QtGui.QDialog, Ui_SongSelectDialog):
+    """
+    The :class:`SongSelectForm` class is the SongSelect dialog.
+    """
+
+    def __init__(self, parent=None, plugin=None, db_manager=None):
+        QtGui.QDialog.__init__(self, parent)
+        self.setupUi(self)
+        self.song = None
+        self.plugin = plugin
+        self.db_manager = db_manager
+        self.html_parser = HTMLParser()
+        self.opener = build_opener(HTTPCookieProcessor(CookieJar()))
+        self.opener.addheaders = [
+            ('User-Agent', USER_AGENT)
+        ]
+        QtCore.QObject.connect(
+            self.loginButton,
+            QtCore.SIGNAL(u'clicked(bool)'),
+            self.onLoginButtonClicked
+        )
+        QtCore.QObject.connect(
+            self.searchButton,
+            QtCore.SIGNAL(u'clicked(bool)'),
+            self.onSearchButtonClicked
+        )
+        QtCore.QObject.connect(
+            self.searchEdit,
+            QtCore.SIGNAL(u'returnPressed()'),
+            self.onSearchButtonClicked
+        )
+        QtCore.QObject.connect(
+            self.logoutButton,
+            QtCore.SIGNAL(u'clicked(bool)'),
+            self.done
+        )
+        QtCore.QObject.connect(
+            self.viewButton,
+            QtCore.SIGNAL(u'clicked(bool)'),
+            self.onViewButtonClicked
+        )
+        QtCore.QObject.connect(
+            self.backButton,
+            QtCore.SIGNAL(u'clicked(bool)'),
+            self.onBackButtonClicked
+        )
+        QtCore.QObject.connect(
+            self.importButton,
+            QtCore.SIGNAL(u'clicked(bool)'),
+            self.onImportButtonClicked
+        )
+
+    def exec_(self):
+        """
+        Execute the dialog. This method sets everything back to its initial
+        values..
+        """
+        self.stackedWidget.setCurrentIndex(0)
+        self.searchEdit.setText('')
+        self.searchResultsWidget.clear()
+        self.usernameEdit.setText(QtCore.QSettings().value(
+            self.plugin.settingsSection + u'/songselect username',
+            QtCore.QVariant('')).toString())
+        self.passwordEdit.setText(QtCore.QSettings().value(
+            self.plugin.settingsSection + u'/songselect password',
+            QtCore.QVariant('')).toString())
+        return QtGui.QDialog.exec_(self)
+
+    def onLoginButtonClicked(self):
+        """
+        Log the user in to SongSelect.
+        """
+        self.loginButton.setEnabled(False)
+        self.loginSpacer.setVisible(False)
+        self.loginProgressBar.setVisible(True)
+        self.loginProgressBar.setValue(1)
+        Receiver.send_message(u'openlp_process_events')
+        login_page = BeautifulSoup(self.opener.open(LOGIN_URL).read())
+        self.loginProgressBar.setValue(2)
+        Receiver.send_message(u'openlp_process_events')
+        token_input = login_page.find('input',
+            attrs={'name': '__RequestVerificationToken'})
+        data = urlencode({
+            '__RequestVerificationToken': token_input.attrMap['value'],
+            'UserName': self.usernameEdit.text(),
+            'Password': self.passwordEdit.text(),
+            'RememberMe': 'false'
+        })
+        posted_page = BeautifulSoup(self.opener.open(LOGIN_URL, data).read())
+        self.loginProgressBar.setValue(3)
+        Receiver.send_message(u'openlp_process_events')
+        if posted_page.find('input',
+            attrs={'name': '__RequestVerificationToken'}):
+            QtGui.QMessageBox.critical(
+                self,
+                translate('SongsPlugin.SongSelectForm', 'Error Logging In'),
+                translate('SongsPlugin.SongSelectForm',
+                    'There was a problem logging in, perhaps your username '
+                    'or password is incorrect?')
+            )
+        else:
+            self.stackedWidget.setCurrentIndex(1)
+        self.loginProgressBar.setVisible(False)
+        self.loginProgressBar.setValue(0)
+        self.loginSpacer.setVisible(True)
+        self.loginButton.setEnabled(True)
+        Receiver.send_message(u'openlp_process_events')
+
+    def onSearchButtonClicked(self):
+        """
+        Run a search on SongSelect.
+        """
+        self.searchButton.setEnabled(False)
+        self.searchProgressBar.setVisible(True)
+        self.searchProgressBar.setValue(1)
+        Receiver.send_message(u'openlp_process_events')
+        data = urlencode({
+            'SearchTerm': self.searchEdit.text(),
+            'allowredirect': 'false'
+        })
+        results_page = BeautifulSoup(
+            self.opener.open(SEARCH_URL + '?' + data).read())
+        self.searchProgressBar.setValue(2)
+        Receiver.send_message(u'openlp_process_events')
+        search_results = results_page.findAll('li', 'result pane')
+        self.searchResultsWidget.clear()
+        for result in search_results:
+            song = {
+                u'title': self.html_parser.unescape(
+                    unicode(result.find(u'h3').string)),
+                u'authors': [self.html_parser.unescape(unicode(author.string))
+                    for author in result.findAll(u'li')],
+                u'link': BASE_URL + result.find(u'a').attrs[0][1]
+            }
+            song_item = QtGui.QListWidgetItem(
+                song[u'title'] + u' (' + u', '.join(song[u'authors']) + u')',
+                self.searchResultsWidget
+            )
+            song_item.setData(QtCore.Qt.UserRole, song)
+        self.searchProgressBar.setValue(3)
+        Receiver.send_message(u'openlp_process_events')
+        self.searchProgressBar.setVisible(False)
+        self.searchProgressBar.setValue(0)
+        self.searchButton.setEnabled(True)
+        Receiver.send_message(u'openlp_process_events')
+
+    def onViewButtonClicked(self):
+        """
+        View a song from SongSelect.
+        """
+        self.songProgressBar.setVisible(True)
+        current_item = self.searchResultsWidget.currentItem()
+        if not current_item:
+            return
+        else:
+            current_item = current_item.data(QtCore.Qt.UserRole).toPyObject()
+        self.titleEdit.setText(u'')
+        self.copyrightEdit.setText(u'')
+        self.ccliEdit.setText(u'')
+        self.authorListWidget.clear()
+        self.lyricsTableWidget.clear()
+        self.stackedWidget.setCurrentIndex(2)
+        song = {}
+        for key, value in current_item.iteritems():
+            song[unicode(key)] = unicode(value) \
+                if isinstance(value, QtCore.QString) else value
+        self.songProgressBar.setValue(1)
+        Receiver.send_message(u'openlp_process_events')
+        song_page = BeautifulSoup(self.opener.open(song[u'link']).read())
+        self.songProgressBar.setValue(2)
+        Receiver.send_message(u'openlp_process_events')
+        try:
+            lyrics_page = BeautifulSoup(
+                self.opener.open(song[u'link'] + u'/lyrics').read())
+        except HTTPError:
+            lyrics_page = None
+        self.songProgressBar.setValue(3)
+        Receiver.send_message(u'openlp_process_events')
+        song[u'copyright'] = u'/'.join([unicode(li.string)
+            for li in song_page.find(u'ul', u'copyright')\
+                .findChildren(u'li')])
+        song[u'copyright'] = self.html_parser.unescape(song['copyright'])
+        song[u'ccli_number'] = song_page.find(u'ul', u'info')\
+            .findChild(u'li').string.split(u':')[1].strip()
+        song[u'verses'] = []
+        if lyrics_page:
+            verses = lyrics_page.find(u'section', u'lyrics')\
+                .findChildren(u'p')
+            verse_labels = lyrics_page.find(u'section', u'lyrics')\
+                .findChildren(u'h3')
+            for counter in range(len(verses)):
+                verse = {
+                    u'label': verse_labels[counter].string,
+                    u'lyrics': u''
+                }
+                for v in verses[counter].contents:
+                    if isinstance(v, NavigableString):
+                        verse[u'lyrics'] = verse[u'lyrics'] + v.string
+                    else:
+                        verse[u'lyrics'] = verse[u'lyrics'] + u'\n'
+                verse[u'lyrics'] = verse[u'lyrics'].strip(u' \n\r\t')
+                song[u'verses'].append(self.html_parser.unescape(verse))
+        self.titleEdit.setText(song[u'title'])
+        self.copyrightEdit.setText(song[u'copyright'])
+        self.ccliEdit.setText(song[u'ccli_number'])
+        for author in song[u'authors']:
+            QtGui.QListWidgetItem(self.html_parser.unescape(author),
+                self.authorListWidget)
+        self.lyricsTableWidget.setRowCount(0)
+        for counter, verse in enumerate(song[u'verses']):
+            log.debug(u'Verse type: %s', verse[u'label'])
+            self.lyricsTableWidget.setRowCount(
+                self.lyricsTableWidget.rowCount() + 1)
+            item = QtGui.QTableWidgetItem(verse[u'lyrics'])
+            item.setData(QtCore.Qt.UserRole, QtCore.QVariant(verse[u'label']))
+            item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
+            self.lyricsTableWidget.setItem(counter, 0, item)
+        self.lyricsTableWidget.setVerticalHeaderLabels(
+            [verse[u'label'] for verse in song[u'verses']])
+        self.lyricsTableWidget.resizeRowsToContents()
+        self.lyricsTableWidget.repaint()
+        self.songProgressBar.setVisible(False)
+        self.songProgressBar.setValue(0)
+        self.song = song
+        Receiver.send_message(u'openlp_process_events')
+
+    def onBackButtonClicked(self):
+        """
+        Go back to the search page.
+        """
+        self.stackedWidget.setCurrentIndex(1)
+
+    def onImportButtonClicked(self):
+        """
+        Import a song from SongSelect.
+        """
+        song = Song.populate(
+            title=self.song[u'title'],
+            copyright=self.song[u'copyright'],
+            ccli_number=self.song[u'ccli_number']
+        )
+        song_xml = SongXML()
+        verse_order = []
+        for verse in self.song[u'verses']:
+            verse_type, verse_number = VerseType.parse_verse(verse[u'label'])
+            song_xml.add_verse_to_lyrics(
+                VerseType.Tags[verse_type],
+                verse_number,
+                verse[u'lyrics']
+            )
+            verse_order.append('%s%s' % \
+                (VerseType.Tags[verse_type], verse_number))
+        song.verse_order = u' '.join(verse_order)
+        song.lyrics = unicode(song_xml.extract_xml(), u'utf-8')
+        clean_song(self.db_manager, song)
+        self.db_manager.save_object(song)
+        song.authors = []
+        for author_name in self.song[u'authors']:
+            author_name = unicode(author_name)
+            author = self.db_manager.get_object_filtered(Author,
+                Author.display_name == author_name)
+            if not author:
+                author = Author.populate(
+                    first_name=author_name.rsplit(u' ', 1)[0],
+                    last_name=author_name.rsplit(u' ', 1)[1],
+                    display_name=author_name
+                )
+            song.authors.append(author)
+        self.db_manager.save_object(song)
+        QtGui.QMessageBox.information(self,
+            translate('SongsPlugin.SongSelectForm', 'Song Imported'),
+            translate('SongsPlugin.SongSelectForm',
+                'Your song has been imported.')
+        )
+
+    def done(self, r):
+        """
+        Log out of SongSelect.
+        """
+        log.debug(u'Closing SongSelectForm')
+        self.opener.open(LOGOUT_URL)
+        return QtGui.QDialog.done(self, r)

=== modified file 'openlp/plugins/songs/lib/__init__.py'
--- openlp/plugins/songs/lib/__init__.py	2012-04-29 15:31:56 +0000
+++ openlp/plugins/songs/lib/__init__.py	2012-05-26 18:22:20 +0000
@@ -169,6 +169,7 @@
         for num, translation in enumerate(VerseType.TranslatedNames):
             if verse_name == translation.lower():
                 return num
+        return None
 
     @staticmethod
     def from_loose_input(verse_name, default=Other):
@@ -190,9 +191,25 @@
             if verse_index is None:
                 verse_index = VerseType.from_tag(verse_name, default)
         else:
-            return default
+            verse_index = default
         return verse_index
 
+    @staticmethod
+    def parse_verse(verse_text, default=Other):
+        match = re.match(r'([-a-zA-Z]*)[ ]?([\d][a-zA-Z0-9]*)?', verse_text)
+        if match:
+            verse_name = match.group(1)
+            verse_number = match.group(2)
+            if verse_number is not None:
+                verse_number = int(verse_number)
+            else:
+                verse_number = 1
+            verse_type = VerseType.from_loose_input(verse_name, default)
+            return verse_type, verse_number
+        else:
+            raise TypeError(u'Verse text does not match known values.')
+
+
 def retrieve_windows_encoding(recommendation=None):
     """
     Determines which encoding to use on an information source. The process uses
@@ -294,7 +311,7 @@
     song.search_title = clean_string(song.title) + u'@' + \
         clean_string(song.alternate_title)
     # Only do this, if we the song is a 1.9.4 song (or older).
-    if song.lyrics.find(u'<lyrics language="en">') != -1:
+    if u'<lyrics language="en">' in song.lyrics:
         # Remove the old "language" attribute from lyrics tag (prior to 1.9.5).
         # This is not very important, but this keeps the database clean. This
         # can be removed when everybody has cleaned his songs.

=== modified file 'openlp/plugins/songs/lib/songstab.py'
--- openlp/plugins/songs/lib/songstab.py	2012-04-02 19:52:47 +0000
+++ openlp/plugins/songs/lib/songstab.py	2012-05-26 18:22:20 +0000
@@ -59,6 +59,26 @@
         self.modeLayout.addWidget(self.addFromServiceCheckBox)
         self.leftLayout.addWidget(self.modeGroupBox)
         self.leftLayout.addStretch()
+        self.songSelectGroupBox = QtGui.QGroupBox(self.rightColumn)
+        self.songSelectGroupBox.setObjectName(u'songSelectGroupBox')
+        self.songSelectLayout = QtGui.QFormLayout(self.songSelectGroupBox)
+        self.songSelectLayout.setObjectName(u'songSelectLayout')
+        self.usernameLabel = QtGui.QLabel(self.songSelectGroupBox)
+        self.usernameLabel.setObjectName(u'usernameLabel')
+        self.usernameEdit = QtGui.QLineEdit(self.songSelectGroupBox)
+        self.usernameEdit.setObjectName(u'usernameEdit')
+        self.songSelectLayout.addRow(self.usernameLabel, self.usernameEdit)
+        self.passwordLabel = QtGui.QLabel(self.songSelectGroupBox)
+        self.passwordLabel.setObjectName(u'passwordLabel')
+        self.passwordEdit = QtGui.QLineEdit(self.songSelectGroupBox)
+        self.passwordEdit.setEchoMode(QtGui.QLineEdit.Password)
+        self.passwordEdit.setObjectName(u'passwordEdit')
+        self.songSelectLayout.addRow(self.passwordLabel, self.passwordEdit)
+        self.warningLabel = QtGui.QLabel(self.songSelectGroupBox)
+        self.warningLabel.setWordWrap(True)
+        self.warningLabel.setObjectName(u'warningLabel')
+        self.songSelectLayout.addWidget(self.warningLabel)
+        self.rightLayout.addWidget(self.songSelectGroupBox)
         self.rightLayout.addStretch()
         QtCore.QObject.connect(self.searchAsTypeCheckBox,
             QtCore.SIGNAL(u'stateChanged(int)'),
@@ -84,30 +104,28 @@
             translate('SongsPlugin.SongsTab', 'Update service from song edit'))
         self.addFromServiceCheckBox.setText(translate('SongsPlugin.SongsTab',
             'Import missing songs from service files'))
+        self.songSelectGroupBox.setTitle(translate(
+            'SongsPlugin.SongsTab', 'SongSelect Details'))
+        self.usernameLabel.setText(translate(
+            'SongsPlugin.SongsTab', 'Username:'))
+        self.passwordLabel.setText(translate(
+            'SongsPlugin.SongsTab', 'Password:'))
+        self.warningLabel.setText(translate(
+            'SongsPlugin.SongsTab', 'WARNING: This stores your password in '
+                'plain text on your computer. If you are unhappy with this, '
+                'DO NOT STORE YOUR PASSWORD.'))
 
     def onSearchAsTypeCheckBoxChanged(self, check_state):
-        self.song_search = False
-        # we have a set value convert to True/False
-        if check_state == QtCore.Qt.Checked:
-            self.song_search = True
+        self.song_search = check_state == QtCore.Qt.Checked
 
     def onToolBarActiveCheckBoxChanged(self, check_state):
-        self.tool_bar = False
-        # we have a set value convert to True/False
-        if check_state == QtCore.Qt.Checked:
-            self.tool_bar = True
+        self.tool_bar = check_state == QtCore.Qt.Checked
 
     def onUpdateOnEditCheckBoxChanged(self, check_state):
-        self.update_edit = False
-        # we have a set value convert to True/False
-        if check_state == QtCore.Qt.Checked:
-            self.update_edit = True
+        self.update_edit = check_state == QtCore.Qt.Checked
 
     def onAddFromServiceCheckBoxChanged(self, check_state):
-        self.update_load = False
-        # we have a set value convert to True/False
-        if check_state == QtCore.Qt.Checked:
-            self.update_load = True
+        self.update_load = check_state == QtCore.Qt.Checked
 
     def load(self):
         settings = QtCore.QSettings()
@@ -124,6 +142,10 @@
         self.toolBarActiveCheckBox.setChecked(self.tool_bar)
         self.updateOnEditCheckBox.setChecked(self.update_edit)
         self.addFromServiceCheckBox.setChecked(self.update_load)
+        self.usernameEdit.setText(settings.value(u'songselect username',
+            QtCore.QVariant('')).toString())
+        self.passwordEdit.setText(settings.value(u'songselect password',
+            QtCore.QVariant('')).toString())
         settings.endGroup()
 
     def save(self):
@@ -135,4 +157,8 @@
             QtCore.QVariant(self.update_edit))
         settings.setValue(u'add song from service',
             QtCore.QVariant(self.update_load))
+        settings.setValue(u'songselect username',
+            QtCore.QVariant(self.usernameEdit.text()))
+        settings.setValue(u'songselect password',
+            QtCore.QVariant(self.passwordEdit.text()))
         settings.endGroup()

=== modified file 'openlp/plugins/songs/songsplugin.py'
--- openlp/plugins/songs/songsplugin.py	2012-04-29 15:31:56 +0000
+++ openlp/plugins/songs/songsplugin.py	2012-05-26 18:22:20 +0000
@@ -41,6 +41,7 @@
 from openlp.plugins.songs.lib.db import init_schema, Song
 from openlp.plugins.songs.lib.importer import SongFormat
 from openlp.plugins.songs.lib.olpimport import OpenLPSongImport
+from openlp.plugins.songs.forms import SongSelectForm
 
 log = logging.getLogger(__name__)
 
@@ -63,26 +64,36 @@
         self.weight = -10
         self.iconPath = u':/plugins/plugin_songs.png'
         self.icon = build_icon(self.iconPath)
+        self.songSelectForm = SongSelectForm(plugin_helpers['formparent'],
+            self, self.manager)
 
     def checkPreConditions(self):
+        """
+        Run a pre-initialisation check.
+        """
         return self.manager.session is not None
 
     def initialise(self):
+        """
+        Initialise the songs plugin.
+        """
         log.info(u'Songs Initialising')
         Plugin.initialise(self)
         self.songImportItem.setVisible(True)
         self.songExportItem.setVisible(True)
         self.toolsReindexItem.setVisible(True)
+        self.toolsSongSelectItem.setVisible(True)
         action_list = ActionList.get_instance()
         action_list.add_action(self.songImportItem, unicode(UiStrings().Import))
         action_list.add_action(self.songExportItem, unicode(UiStrings().Export))
         action_list.add_action(self.toolsReindexItem,
             unicode(UiStrings().Tools))
+        action_list.add_action(self.toolsSongSelectItem,
+            unicode(UiStrings().Tools))
         QtCore.QObject.connect(Receiver.get_receiver(),
             QtCore.SIGNAL(u'servicemanager_new_service'),
         self.clearTemporarySongs)
 
-
     def addImportMenuItem(self, import_menu):
         """
         Give the Songs plugin the opportunity to add items to the
@@ -134,6 +145,14 @@
             'Re-index the songs database to improve searching and ordering.'),
             visible=False, triggers=self.onToolsReindexItemTriggered)
         tools_menu.addAction(self.toolsReindexItem)
+        self.toolsSongSelectItem = create_action(tools_menu,
+            u'toolsSongSelectItem',
+            text=translate('SongsPlugin', 'CCLI &SongSelect'),
+            icon=u':/general/general_import.png',
+            statustip=translate('SongsPlugin',
+                'Import songs from CCLI\'s SongSelect service.'),
+            visible=False, triggers=self.onToolsSongSelectItemTriggered)
+        tools_menu.addAction(self.toolsSongSelectItem)
 
     def onToolsReindexItemTriggered(self):
         """
@@ -153,15 +172,31 @@
         self.manager.save_objects(songs)
         self.mediaItem.onSearchTextButtonClicked()
 
+    def onToolsSongSelectItemTriggered(self):
+        """
+        Run the SongSelect importer
+        """
+        self.songSelectForm.exec_()
+        self.mediaItem.onSearchTextButtonClicked()
+
     def onSongImportItemClicked(self):
+        """
+        Open the song import wizard.
+        """
         if self.mediaItem:
             self.mediaItem.onImportClick()
 
     def onSongExportItemClicked(self):
+        """
+        Open the song export wizard.
+        """
         if self.mediaItem:
             self.mediaItem.onExportClick()
 
     def about(self):
+        """
+        Show the about message in the plugins list.
+        """
         return translate('SongsPlugin', '<strong>Songs Plugin</strong>'
             '<br />The songs plugin provides the ability to display and '
             'manage songs.')
@@ -194,6 +229,9 @@
             self.manager.save_object(song)
 
     def importSongs(self, format, **kwargs):
+        """
+        Get and initialise the importer for a particular source.
+        """
         class_ = SongFormat.get_class(format)
         importer = class_(self.manager, **kwargs)
         importer.register(self.mediaItem.importWizard)
@@ -277,7 +315,9 @@
         Plugin.finalise(self)
 
     def clearTemporarySongs(self):
-        # Remove temporary songs
+        """
+        Remove temporary songs
+        """
         songs = self.manager.get_all_objects(Song, Song.temporary == True)
         for song in songs:
             self.manager.delete_object(Song, song.id)

=== modified file 'resources/images/openlp-2.qrc'
--- resources/images/openlp-2.qrc	2012-02-25 00:01:24 +0000
+++ resources/images/openlp-2.qrc	2012-05-26 18:22:20 +0000
@@ -1,6 +1,8 @@
 <RCC>
   <qresource prefix="songs">
     <file>song_search_all.png</file>
+    <file>song_back.png</file>
+    <file>song_ss_find.png</file>
     <file>song_search_author.png</file>
     <file>song_search_lyrics.png</file>
     <file>song_search_title.png</file>

=== added file 'resources/images/song_back.png'
Binary files resources/images/song_back.png	1970-01-01 00:00:00 +0000 and resources/images/song_back.png	2012-05-26 18:22:20 +0000 differ
=== added file 'resources/images/song_ss_find.png'
Binary files resources/images/song_ss_find.png	1970-01-01 00:00:00 +0000 and resources/images/song_ss_find.png	2012-05-26 18:22:20 +0000 differ

Follow ups