diff --git a/OpenLP.spec b/OpenLP.spec deleted file mode 100644 index 9569af6c1..000000000 --- a/OpenLP.spec +++ /dev/null @@ -1,19 +0,0 @@ -# -*- mode: python -*- -a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), 'openlp.pyw'], - pathex=[os.path.abspath('.')]) -pyz = PYZ(a.pure) -exe = EXE(pyz, - a.scripts, - exclude_binaries=1, - name=os.path.join('build\\pyi.win32\\OpenLP', 'OpenLP.exe'), - debug=False, - strip=False, - upx=True, - console=False , icon='resources\\images\\OpenLP.ico') -coll = COLLECT( exe, - a.binaries, - a.zipfiles, - a.datas, - strip=False, - upx=True, - name=os.path.join('dist', 'OpenLP')) diff --git a/documentation/source/conf.py b/documentation/source/conf.py index 86ad3b7de..248c83e56 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -17,7 +17,7 @@ import sys # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath(os.path.join('..', '..'))) +sys.path.insert(0, os.path.abspath(os.path.join('..', '..'))) # -- General configuration ----------------------------------------------------- diff --git a/documentation/source/core/lib.rst b/documentation/source/core/lib.rst index 43ca90b3b..5fc66200d 100644 --- a/documentation/source/core/lib.rst +++ b/documentation/source/core/lib.rst @@ -60,12 +60,6 @@ .. autoclass:: openlp.core.lib.settingstab.SettingsTab :members: -:mod:`ThemeXML` ---------------- - -.. autoclass:: openlp.core.lib.themexmlhandler.ThemeXML - :members: - :mod:`OpenLPToolbar` -------------------- diff --git a/documentation/source/manual/index.rst b/documentation/source/manual/index.rst new file mode 100644 index 000000000..2ed7824fe --- /dev/null +++ b/documentation/source/manual/index.rst @@ -0,0 +1,22 @@ +.. OpenLP documentation master file, created by + sphinx-quickstart on Thu Sep 30 21:24:54 2010. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to OpenLP's documentation +================================== + +Contents: + +.. toctree:: + :maxdepth: 2 + + introduction + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/documentation/source/manual/introduction.rst b/documentation/source/manual/introduction.rst new file mode 100644 index 000000000..02ecf7dbd --- /dev/null +++ b/documentation/source/manual/introduction.rst @@ -0,0 +1,46 @@ +============= +Introduction +============= + +About +----- + +OpenLP is an open source lyrics projection application developed specifically +for churches. It is licensed under the GNU Generic Public License, which means +that it is free to use and distribute, and it stays free. + +Lyrics Projection +----------------- + +OpenLP's purpose is to project the lyrics of songs and Bible verses using a +computer and a data projector. OpenLP also has the ability to project videos, +images, and also play audio. OpenLP also is highly customizable providing users +with the ability to set up a wide variety of themes, including themes with +video backgrounds. + +Open Source +----------- + +OpenLP is open source software. This means that the source code (the +programming instructions the developers write) is open to anyone who wants to +look at it. This gives you, the end user, a few freedoms. + +From a developer's perspective, it gives you the freedom to inspect the code +and make sure that it is not malicious. Also, it gives you the freedom to +change the code and the freedom to "fork" the project and make it your own. + +For end users open source software gives you the freedom to use software as +you wish. You are not required to pay for the software and you are free to +make copies and distribute it to anyone you want. + +GNU General Public License +-------------------------- + +The GNU General Public License was specifically chosen because it ensures the +above mentioned freedoms. It specifically states that you are not allowed +to charge for the software, and that you have to distribute the source code as +well. + +You can find a copy of the GNU General Public License from the Help menu +selecting about OpenLP or on-line +at: http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt diff --git a/documentation/source/plugins/songs.rst b/documentation/source/plugins/songs.rst index fab10f02d..2ce744ddd 100644 --- a/documentation/source/plugins/songs.rst +++ b/documentation/source/plugins/songs.rst @@ -6,8 +6,8 @@ .. automodule:: openlp.plugins.songs :members: -:mod:`SongsPlugin` Class ------------------------- +:class:`SongsPlugin` Class +-------------------------- .. autoclass:: openlp.plugins.songs.songsplugin.SongsPlugin :members: @@ -18,8 +18,8 @@ .. automodule:: openlp.plugins.songs.forms :members: -:mod:`AuthorsForm` -^^^^^^^^^^^^^^^^^^ +:class:`AuthorsForm` +^^^^^^^^^^^^^^^^^^^^ .. autoclass:: openlp.plugins.songs.forms.authorsdialog.Ui_AuthorsDialog :members: @@ -27,8 +27,8 @@ .. autoclass:: openlp.plugins.songs.forms.authorsform.AuthorsForm :members: -:mod:`EditSongForm` -^^^^^^^^^^^^^^^^^^^ +:class:`EditSongForm` +^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: openlp.plugins.songs.forms.editsongdialog.Ui_EditSongDialog :members: @@ -36,11 +36,158 @@ .. autoclass:: openlp.plugins.songs.forms.editsongform.EditSongForm :members: -:mod:`EditVerseForm` -^^^^^^^^^^^^^^^^^^^^ +:class:`EditVerseForm` +^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: openlp.plugins.songs.forms.editversedialog.Ui_EditVerseDialog :members: .. autoclass:: openlp.plugins.songs.forms.editverseform.EditVerseForm :members: + +:class:`SongBookForm` +^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: openlp.plugins.songs.forms.songbookdialog.Ui_SongBookDialog + :members: + +.. autoclass:: openlp.plugins.songs.forms.songbookform.SongBookForm + :members: + +:class:`SongImportForm` +^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: openlp.plugins.songs.forms.songimportwizard.Ui_SongImportWizard + :members: + +.. autoclass:: openlp.plugins.songs.forms.songimportform.ImportWizardForm + :members: + +:class:`SongMaintenanceForm` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: openlp.plugins.songs.forms.songmaintenancedialog.Ui_SongMaintenanceDialog + :members: + +.. autoclass:: openlp.plugins.songs.forms.songmaintenanceform.SongMaintenanceForm + :members: + +:class:`TopicsForm` +^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: openlp.plugins.songs.forms.topicsdialog.Ui_TopicsDialog + :members: + +.. autoclass:: openlp.plugins.songs.forms.topicsform.TopicsForm + :members: + +:mod:`lib` Submodule +-------------------- + +.. automodule:: openlp.plugins.songs.lib + :members: + +:mod:`cclifileimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.cclifileimport + :members: + +.. autoclass:: openlp.plugins.songs.lib.cclifileimport.CCLIFileImportError + :members: + +:mod:`db` Submodule +^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.db + :members: + +:mod:`ewimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.ewimport + :members: + +.. autoclass:: openlp.plugins.songs.lib.ewimport.FieldDescEntry + :members: + +:mod:`importer` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.importer + :members: + +:mod:`mediaitem` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.mediaitem + :members: + +.. autoclass:: openlp.plugins.songs.lib.mediaitem.SongListView + :members: + +:mod:`olp1import` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.olp1import + :members: + +:mod:`olpimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.olpimport + :members: + +:mod:`oooimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.oooimport + :members: + +:mod:`opensongimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.opensongimport + :members: + +:mod:`sofimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.sofimport + :members: + +:mod:`songbeamerimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.songbeamerimport + :members: + +:mod:`songimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.songimport + :members: + +:mod:`songstab` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.songstab + :members: + +:mod:`wowimport` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.wowimport + :members: + +:mod:`songxml` Submodule +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.songxml + :members: + +:mod:`xml` Submodule +^^^^^^^^^^^^^^^^^^^^ + +.. automodule:: openlp.plugins.songs.lib.xml + :members: diff --git a/openlp.pyw b/openlp.pyw index 80b49321e..17743903f 100755 --- a/openlp.pyw +++ b/openlp.pyw @@ -30,6 +30,7 @@ import sys import logging from optparse import OptionParser from traceback import format_exception +from subprocess import Popen, PIPE from PyQt4 import QtCore, QtGui @@ -71,6 +72,84 @@ class OpenLP(QtGui.QApplication): """ log.info(u'OpenLP Application Loaded') + def _get_version(self): + """ + Load and store current Application Version + """ + if u'--dev-version' in sys.argv: + # If we're running the dev version, let's use bzr to get the version + try: + # If bzrlib is availble, use it + from bzrlib.branch import Branch + b = Branch.open_containing('.')[0] + b.lock_read() + try: + # Get the branch's latest revision number. + revno = b.revno() + # Convert said revision number into a bzr revision id. + revision_id = b.dotted_revno_to_revision_id((revno,)) + # Get a dict of tags, with the revision id as the key. + tags = b.tags.get_reverse_tag_dict() + # Check if the latest + if revision_id in tags: + full_version = u'%s' % tags[revision_id][0] + else: + full_version = '%s-bzr%s' % \ + (sorted(b.tags.get_tag_dict().keys())[-1], revno) + finally: + b.unlock() + except: + # Otherwise run the command line bzr client + bzr = Popen((u'bzr', u'tags', u'--sort', u'time'), stdout=PIPE) + output, error = bzr.communicate() + code = bzr.wait() + if code != 0: + raise Exception(u'Error running bzr tags') + lines = output.splitlines() + if len(lines) == 0: + tag = u'0.0.0' + revision = u'0' + else: + tag, revision = lines[-1].split() + bzr = Popen((u'bzr', u'log', u'--line', u'-r', u'-1'), + stdout=PIPE) + output, error = bzr.communicate() + code = bzr.wait() + if code != 0: + raise Exception(u'Error running bzr log') + latest = output.split(u':')[0] + full_version = latest == revision and tag or \ + u'%s-bzr%s' % (tag, latest) + else: + # We're not running the development version, let's use the file + filepath = AppLocation.get_directory(AppLocation.VersionDir) + filepath = os.path.join(filepath, u'.version') + fversion = None + try: + fversion = open(filepath, u'r') + full_version = unicode(fversion.read()).rstrip() + except IOError: + log.exception('Error in version file.') + full_version = u'0.0.0-bzr000' + finally: + if fversion: + fversion.close() + bits = full_version.split(u'-') + app_version = { + u'full': full_version, + u'version': bits[0], + u'build': bits[1] if len(bits) > 1 else None + } + if app_version[u'build']: + log.info( + u'Openlp version %s build %s', + app_version[u'version'], + app_version[u'build'] + ) + else: + log.info(u'Openlp version %s' % app_version[u'version']) + return app_version + def notify(self, obj, evt): #TODO needed for presentation exceptions return QtGui.QApplication.notify(self, obj, evt) @@ -79,39 +158,7 @@ class OpenLP(QtGui.QApplication): """ Run the OpenLP application. """ - #Load and store current Application Version - filepath = AppLocation.get_directory(AppLocation.VersionDir) - filepath = os.path.join(filepath, u'.version') - fversion = None - try: - fversion = open(filepath, u'r') - for line in fversion: - full_version = unicode(line).rstrip() #\ - #.replace(u'\r', u'').replace(u'\n', u'') - bits = full_version.split(u'-') - app_version = { - u'full': full_version, - u'version': bits[0], - u'build': bits[1] if len(bits) > 1 else None - } - if app_version[u'build']: - log.info( - u'Openlp version %s build %s', - app_version[u'version'], - app_version[u'build'] - ) - else: - log.info(u'Openlp version %s' % app_version[u'version']) - except IOError: - log.exception('Error in version file.') - app_version = { - u'full': u'1.9.0-bzr000', - u'version': u'1.9.0', - u'build': u'bzr000' - } - finally: - if fversion: - fversion.close() + app_version = self._get_version() #provide a listener for widgets to reqest a screen update. QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'openlp_process_events'), self.processEvents) @@ -172,6 +219,9 @@ def main(): parser.add_option('-p', '--portable', dest='portable', action='store_true', help='Specify if this should be run as a ' 'portable app, off a USB flash drive (not implemented).') + parser.add_option('-d', '--dev-version', dest='dev_version', + action='store_true', help='Ignore the version file and pull the ' + 'version directly from Bazaar') parser.add_option('-s', '--style', dest='style', help='Set the Qt4 style (passed directly to Qt4).') # Set up logging diff --git a/openlp/plugins/bibles/forms/bibleimportwizard.py b/openlp/plugins/bibles/forms/bibleimportwizard.py index d64fce261..304e9fb0f 100644 --- a/openlp/plugins/bibles/forms/bibleimportwizard.py +++ b/openlp/plugins/bibles/forms/bibleimportwizard.py @@ -275,14 +275,14 @@ class Ui_BibleImportWizard(object): self.CopyrightEdit.setObjectName(u'CopyrightEdit') self.LicenseDetailsLayout.setWidget(1, QtGui.QFormLayout.FieldRole, self.CopyrightEdit) - self.PermissionLabel = QtGui.QLabel(self.LicenseDetailsPage) - self.PermissionLabel.setObjectName(u'PermissionLabel') + self.PermissionsLabel = QtGui.QLabel(self.LicenseDetailsPage) + self.PermissionsLabel.setObjectName(u'PermissionsLabel') self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.LabelRole, - self.PermissionLabel) - self.PermissionEdit = QtGui.QLineEdit(self.LicenseDetailsPage) - self.PermissionEdit.setObjectName(u'PermissionEdit') + self.PermissionsLabel) + self.PermissionsEdit = QtGui.QLineEdit(self.LicenseDetailsPage) + self.PermissionsEdit.setObjectName(u'PermissionsEdit') self.LicenseDetailsLayout.setWidget(2, QtGui.QFormLayout.FieldRole, - self.PermissionEdit) + self.PermissionsEdit) BibleImportWizard.addPage(self.LicenseDetailsPage) self.ImportPage = QtGui.QWizardPage() self.ImportPage.setObjectName(u'ImportPage') @@ -372,8 +372,8 @@ class Ui_BibleImportWizard(object): translate('BiblesPlugin.ImportWizardForm', 'Version name:')) self.CopyrightLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Copyright:')) - self.PermissionLabel.setText( - translate('BiblesPlugin.ImportWizardForm', 'Permission:')) + self.PermissionsLabel.setText( + translate('BiblesPlugin.ImportWizardForm', 'Permissions:')) self.ImportPage.setTitle( translate('BiblesPlugin.ImportWizardForm', 'Importing')) self.ImportPage.setSubTitle( diff --git a/openlp/plugins/bibles/forms/importwizardform.py b/openlp/plugins/bibles/forms/importwizardform.py index 3b2611e8f..3a20130eb 100644 --- a/openlp/plugins/bibles/forms/importwizardform.py +++ b/openlp/plugins/bibles/forms/importwizardform.py @@ -282,7 +282,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): self.LicenseDetailsPage.registerField( u'license_copyright', self.CopyrightEdit) self.LicenseDetailsPage.registerField( - u'license_permission', self.PermissionEdit) + u'license_permissions', self.PermissionsEdit) def setDefaults(self): settings = QtCore.QSettings() @@ -308,8 +308,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): QtCore.QVariant(self.VersionNameEdit.text())) self.setField(u'license_copyright', QtCore.QVariant(self.CopyrightEdit.text())) - self.setField(u'license_permission', - QtCore.QVariant(self.PermissionEdit.text())) + self.setField(u'license_permissions', + QtCore.QVariant(self.PermissionsEdit.text())) self.onLocationComboBoxChanged(WebDownload.Crosswalk) settings.endGroup() @@ -391,8 +391,8 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): bible_type = self.field(u'source_format').toInt()[0] license_version = unicode(self.field(u'license_version').toString()) license_copyright = unicode(self.field(u'license_copyright').toString()) - license_permission = \ - unicode(self.field(u'license_permission').toString()) + license_permissions = \ + unicode(self.field(u'license_permissions').toString()) importer = None if bible_type == BibleFormat.OSIS: # Import an OSIS bible @@ -436,7 +436,7 @@ class ImportWizardForm(QtGui.QWizard, Ui_BibleImportWizard): ) if importer.do_import(): self.manager.save_meta_data(license_version, license_version, - license_copyright, license_permission) + license_copyright, license_permissions) self.manager.reload_bibles() self.ImportProgressLabel.setText( translate('BiblesPlugin.ImportWizardForm', 'Finished import.')) diff --git a/openlp/plugins/bibles/lib/db.py b/openlp/plugins/bibles/lib/db.py index 49bc82102..8f5c7dc79 100644 --- a/openlp/plugins/bibles/lib/db.py +++ b/openlp/plugins/bibles/lib/db.py @@ -64,10 +64,10 @@ class Verse(BaseModel): def init_schema(url): """ - Setup a bible database connection and initialise the database schema + Setup a bible database connection and initialise the database schema. ``url`` - The database to setup + The database to setup. """ session, metadata = init_db(url) @@ -240,7 +240,7 @@ class BibleDB(QtCore.QObject, Manager): and the value is the verse text. """ log.debug(u'create_chapter %s,%s', book_id, chapter) - #text list has book and chapter as first two elements of the array + # text list has book and chapter as first two elements of the array for verse_number, verse_text in textlist.iteritems(): verse = Verse.populate( book_id = book_id, @@ -281,23 +281,23 @@ class BibleDB(QtCore.QObject, Manager): def create_meta(self, key, value): """ - Utility method to save BibleMeta objects in a Bible database + Utility method to save BibleMeta objects in a Bible database. ``key`` - The key for this instance + The key for this instance. ``value`` - The value for this instance + The value for this instance. """ log.debug(u'save_meta %s/%s', key, value) self.save_object(BibleMeta.populate(key=key, value=value)) def get_book(self, book): """ - Return a book object from the database + Return a book object from the database. ``book`` - The name of the book to return + The name of the book to return. """ log.debug(u'BibleDb.get_book("%s")', book) db_book = self.get_object_filtered(Book, Book.name.like(book + u'%')) @@ -353,9 +353,9 @@ class BibleDB(QtCore.QObject, Manager): QtGui.QMessageBox.information(self.bible_plugin.mediaItem, translate('BiblesPlugin.BibleDB', 'Book not found'), translate('BiblesPlugin.BibleDB', 'The book you requested ' - 'could not be found in this bible. Please check your ' - 'spelling and that this is a complete bible not just ' - 'one testament.')) + 'could not be found in this Bible. Please check your ' + 'spelling and that this is a complete Bible not just ' + 'one testament.')) return verse_list def verse_search(self, text): @@ -387,10 +387,10 @@ class BibleDB(QtCore.QObject, Manager): def get_chapter_count(self, book): """ - Return the number of chapters in a book + Return the number of chapters in a book. ``book`` - The book to get the chapter count for + The book to get the chapter count for. """ log.debug(u'BibleDB.get_chapter_count("%s")', book) count = self.session.query(Verse.chapter).join(Book)\ @@ -403,13 +403,13 @@ class BibleDB(QtCore.QObject, Manager): def get_verse_count(self, book, chapter): """ - Return the number of verses in a chapter + Return the number of verses in a chapter. ``book`` - The book containing the chapter + The book containing the chapter. ``chapter`` - The chapter to get the verse count for + The chapter to get the verse count for. """ log.debug(u'BibleDB.get_verse_count("%s", %s)', book, chapter) count = self.session.query(Verse).join(Book)\ @@ -423,7 +423,7 @@ class BibleDB(QtCore.QObject, Manager): def dump_bible(self): """ - Utility debugging method to dump the contents of a bible + Utility debugging method to dump the contents of a bible. """ log.debug(u'.........Dumping Bible Database') log.debug('...............................Books ') diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 415a0cde5..18cdb7223 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -187,16 +187,16 @@ class BGExtract(object): def get_bible_chapter(self, version, bookname, chapter): """ - Access and decode bibles via the BibleGateway website + Access and decode bibles via the BibleGateway website. ``version`` - The version of the bible like 31 for New International version + The version of the bible like 31 for New International version. ``bookname`` - Name of the Book + Name of the Book. ``chapter`` - Chapter number + Chapter number. """ log.debug(u'get_bible_chapter %s, %s, %s', version, bookname, chapter) url_params = urllib.urlencode( @@ -298,13 +298,13 @@ class CWExtract(object): versetext = versetext + part elif part and part.attrMap and \ (part.attrMap[u'class'] == u'WordsOfChrist' or \ - part.attrMap[u'class'] == u'strongs'): + part.attrMap[u'class'] == u'strongs'): for subpart in part.contents: Receiver.send_message(u'openlp_process_events') if isinstance(subpart, NavigableString): versetext = versetext + subpart elif subpart and subpart.attrMap and \ - subpart.attrMap[u'class'] == u'strongs': + subpart.attrMap[u'class'] == u'strongs': for subsub in subpart.contents: Receiver.send_message(u'openlp_process_events') if isinstance(subsub, NavigableString): @@ -428,7 +428,7 @@ class HTTPBible(BibleDB): def get_chapter(self, book, chapter): """ - Receive the request and call the relevant handler methods + Receive the request and call the relevant handler methods. """ log.debug(u'get_chapter %s, %s', book, chapter) log.debug(u'source = %s', self.download_source) diff --git a/openlp/plugins/bibles/lib/manager.py b/openlp/plugins/bibles/lib/manager.py index fd2c2adff..877331341 100644 --- a/openlp/plugins/bibles/lib/manager.py +++ b/openlp/plugins/bibles/lib/manager.py @@ -137,7 +137,7 @@ class BibleManager(object): name = bible.get_name() log.debug(u'Bible Name: "%s"', name) self.db_cache[name] = bible - # look to see if lazy load bible exists and get create getter. + # Look to see if lazy load bible exists and get create getter. source = self.db_cache[name].get_object(BibleMeta, u'download source') if source: @@ -181,10 +181,10 @@ class BibleManager(object): def get_bibles(self): """ - Returns a list of the names of available Bibles. + Returns a dict with all available Bibles. """ log.debug(u'get_bibles') - return self.db_cache.keys() + return self.db_cache def get_books(self, bible): """ @@ -204,7 +204,7 @@ class BibleManager(object): def get_chapter_count(self, bible, book): """ - Returns the number of Chapters for a given book + Returns the number of Chapters for a given book. """ log.debug(u'get_book_chapter_count %s', book) return self.db_cache[bible].get_chapter_count(book) @@ -212,7 +212,7 @@ class BibleManager(object): def get_verse_count(self, bible, book, chapter): """ Returns all the number of verses for a given - book and chapterMaxBibleBookVerses + book and chapterMaxBibleBookVerses. """ log.debug(u'BibleManager.get_verse_count("%s", "%s", %s)', bible, book, chapter) @@ -254,12 +254,35 @@ class BibleManager(object): 'Book Chapter:Verse-Verse\n' 'Book Chapter:Verse-Verse,Verse-Verse\n' 'Book Chapter:Verse-Verse,Chapter:Verse-Verse\n' - 'Book Chapter:Verse-Chapter:Verse\n')) + 'Book Chapter:Verse-Chapter:Verse')) + return None + + def verse_search(self, bible, text): + """ + Does a verse search for the given bible and text. + + ``bible`` + The bible to seach in (unicode). + + ``text`` + The text to search for (unicode). + """ + log.debug(u'BibleManager.verse_search("%s", "%s")', bible, text) + if text: + return self.db_cache[bible].verse_search(text) + else: + QtGui.QMessageBox.information(self.parent.mediaItem, + translate('BiblesPlugin.BibleManager', + 'Scripture Reference Error'), + translate('BiblesPlugin.BibleManager', 'You did not enter a ' + 'search keyword.\nYou can separate different keywords by a ' + 'space to search for all of your keywords and you can seperate ' + 'them by a comma to search for one of them.')) return None def save_meta_data(self, bible, version, copyright, permissions): """ - Saves the bibles meta data + Saves the bibles meta data. """ log.debug(u'save_meta data %s,%s, %s,%s', bible, version, copyright, permissions) @@ -269,14 +292,14 @@ class BibleManager(object): def get_meta_data(self, bible, key): """ - Returns the meta data for a given key + Returns the meta data for a given key. """ log.debug(u'get_meta %s,%s', bible, key) return self.db_cache[bible].get_object(BibleMeta, key) def exists(self, name): """ - Check cache to see if new bible + Check cache to see if new bible. """ if not isinstance(name, unicode): name = unicode(name) diff --git a/openlp/plugins/bibles/lib/mediaitem.py b/openlp/plugins/bibles/lib/mediaitem.py index 92eb200ee..f985c7471 100644 --- a/openlp/plugins/bibles/lib/mediaitem.py +++ b/openlp/plugins/bibles/lib/mediaitem.py @@ -32,6 +32,7 @@ from PyQt4 import QtCore, QtGui from openlp.core.lib import MediaManagerItem, Receiver, BaseListWithDnD, \ ItemCapabilities, translate from openlp.plugins.bibles.forms import ImportWizardForm +from openlp.plugins.bibles.lib.db import BibleDB log = logging.getLogger(__name__) @@ -374,7 +375,7 @@ class BibleMediaItem(MediaManagerItem): self.AdvancedSecondBibleComboBox.clear() self.QuickSecondBibleComboBox.addItem(u'') self.AdvancedSecondBibleComboBox.addItem(u'') - bibles = self.parent.manager.get_bibles() + bibles = self.parent.manager.get_bibles().keys() # load bibles into the combo boxes first = True for bible in bibles: @@ -497,6 +498,7 @@ class BibleMediaItem(MediaManagerItem): def onAdvancedSearchButton(self): log.debug(u'Advanced Search Button pressed') + self.AdvancedSearchButton.setEnabled(False) bible = unicode(self.AdvancedVersionComboBox.currentText()) dual_bible = unicode(self.AdvancedSecondBibleComboBox.currentText()) book = unicode(self.AdvancedBookComboBox.currentText()) @@ -529,16 +531,30 @@ class BibleMediaItem(MediaManagerItem): self.displayResults(bible, dual_bible) else: self.displayResults(bible, dual_bible) + self.AdvancedSearchButton.setEnabled(True) def onQuickSearchButton(self): log.debug(u'Quick Search Button pressed') + self.QuickSearchButton.setEnabled(False) bible = unicode(self.QuickVersionComboBox.currentText()) dual_bible = unicode(self.QuickSecondBibleComboBox.currentText()) text = unicode(self.QuickSearchEdit.text()) - self.search_results = self.parent.manager.get_verses(bible, text) - if dual_bible: - self.dual_search_results = self.parent.manager.get_verses( - dual_bible, text) + if self.QuickSearchComboBox.currentIndex() == 0: + # We are doing a 'Verse Search'. + self.search_results = self.parent.manager.get_verses(bible, text) + if dual_bible and self.search_results: + self.dual_search_results = self.parent.manager.get_verses( + dual_bible, text) + else: + # We are doing a ' Text Search'. + bibles = self.parent.manager.get_bibles() + self.search_results = self.parent.manager.verse_search(bible, text) + if dual_bible and self.search_results: + text = [] + for verse in self.search_results: + text.append((verse.book.name, verse.chapter, verse.verse, + verse.verse)) + self.dual_search_results = bibles[dual_bible].get_verses(text) if self.ClearQuickSearchComboBox.currentIndex() == 0: self.listView.clear() if self.listView.count() != 0 and self.search_results: @@ -558,6 +574,7 @@ class BibleMediaItem(MediaManagerItem): self.displayResults(bible, dual_bible) elif self.search_results: self.displayResults(bible, dual_bible) + self.QuickSearchButton.setEnabled(True) def displayResults(self, bible, dual_bible=u''): """ @@ -566,16 +583,16 @@ class BibleMediaItem(MediaManagerItem): """ version = self.parent.manager.get_meta_data(bible, u'Version') copyright = self.parent.manager.get_meta_data(bible, u'Copyright') - permission = self.parent.manager.get_meta_data(bible, u'Permissions') + permissions = self.parent.manager.get_meta_data(bible, u'Permissions') if dual_bible: dual_version = self.parent.manager.get_meta_data(dual_bible, u'Version') dual_copyright = self.parent.manager.get_meta_data(dual_bible, u'Copyright') - dual_permission = self.parent.manager.get_meta_data(dual_bible, + dual_permissions = self.parent.manager.get_meta_data(dual_bible, u'Permissions') - if not dual_permission: - dual_permission = u'' + if not dual_permissions: + dual_permissions = u'' # We count the number of rows which are maybe already present. start_count = self.listView.count() for count, verse in enumerate(self.search_results): @@ -587,12 +604,12 @@ class BibleMediaItem(MediaManagerItem): 'bible': QtCore.QVariant(bible), 'version': QtCore.QVariant(version.value), 'copyright': QtCore.QVariant(copyright.value), - 'permission': QtCore.QVariant(permission.value), + 'permissions': QtCore.QVariant(permissions.value), 'text': QtCore.QVariant(verse.text), 'dual_bible': QtCore.QVariant(dual_bible), 'dual_version': QtCore.QVariant(dual_version.value), 'dual_copyright': QtCore.QVariant(dual_copyright.value), - 'dual_permission': QtCore.QVariant(dual_permission.value), + 'dual_permissions': QtCore.QVariant(dual_permissions.value), 'dual_text': QtCore.QVariant( self.dual_search_results[count].text) } @@ -607,12 +624,12 @@ class BibleMediaItem(MediaManagerItem): 'bible': QtCore.QVariant(bible), 'version': QtCore.QVariant(version.value), 'copyright': QtCore.QVariant(copyright.value), - 'permission': QtCore.QVariant(permission.value), + 'permissions': QtCore.QVariant(permissions.value), 'text': QtCore.QVariant(verse.text), 'dual_bible': QtCore.QVariant(u''), 'dual_version': QtCore.QVariant(u''), 'dual_copyright': QtCore.QVariant(u''), - 'dual_permission': QtCore.QVariant(u''), + 'dual_permissions': QtCore.QVariant(u''), 'dual_text': QtCore.QVariant(u'') } bible_text = u' %s %d:%d (%s)' % (verse.book.name, @@ -658,20 +675,20 @@ class BibleMediaItem(MediaManagerItem): bible = self._decodeQtObject(bitem, 'bible') version = self._decodeQtObject(bitem, 'version') copyright = self._decodeQtObject(bitem, 'copyright') - permission = self._decodeQtObject(bitem, 'permission') + permissions = self._decodeQtObject(bitem, 'permissions') text = self._decodeQtObject(bitem, 'text') dual_bible = self._decodeQtObject(bitem, 'dual_bible') dual_version = self._decodeQtObject(bitem, 'dual_version') dual_copyright = self._decodeQtObject(bitem, 'dual_copyright') - dual_permission = self._decodeQtObject(bitem, 'dual_permission') + dual_permissions = self._decodeQtObject(bitem, 'dual_permissions') dual_text = self._decodeQtObject(bitem, 'dual_text') verse_text = self.formatVerse(old_chapter, chapter, verse) - footer = u'%s (%s %s %s)' % (book, version, copyright, permission) + footer = u'%s (%s %s %s)' % (book, version, copyright, permissions) if footer not in raw_footer: raw_footer.append(footer) if dual_bible: footer = u'%s (%s %s %s)' % (book, dual_version, dual_copyright, - dual_permission) + dual_permissions) if footer not in raw_footer: raw_footer.append(footer) bible_text = u'%s %s\n\n%s %s' % (verse_text, text, verse_text, diff --git a/openlp/plugins/custom/forms/__init__.py b/openlp/plugins/custom/forms/__init__.py index 008caff8d..f31745e14 100644 --- a/openlp/plugins/custom/forms/__init__.py +++ b/openlp/plugins/custom/forms/__init__.py @@ -25,3 +25,4 @@ ############################################################################### from editcustomform import EditCustomForm +from editcustomslideform import EditCustomSlideForm diff --git a/openlp/plugins/custom/forms/editcustomdialog.py b/openlp/plugins/custom/forms/editcustomdialog.py index 84a310cb9..89cd0b6df 100644 --- a/openlp/plugins/custom/forms/editcustomdialog.py +++ b/openlp/plugins/custom/forms/editcustomdialog.py @@ -26,7 +26,7 @@ from PyQt4 import QtCore, QtGui -from openlp.core.lib import build_icon, translate, SpellTextEdit +from openlp.core.lib import build_icon, translate class Ui_CustomEditDialog(object): def setupUi(self, customEditDialog): @@ -36,6 +36,70 @@ class Ui_CustomEditDialog(object): build_icon(u':/icon/openlp.org-icon-32.bmp')) self.gridLayout = QtGui.QGridLayout(customEditDialog) self.gridLayout.setObjectName(u'gridLayout') + self.horizontalLayout3 = QtGui.QHBoxLayout() + self.horizontalLayout3.setObjectName(u'horizontalLayout3') + self.themeLabel = QtGui.QLabel(customEditDialog) + self.themeLabel.setObjectName(u'themeLabel') + self.horizontalLayout3.addWidget(self.themeLabel) + self.themeComboBox = QtGui.QComboBox(customEditDialog) + self.themeLabel.setBuddy(self.themeComboBox) + self.themeComboBox.setObjectName(u'themeComboBox') + self.horizontalLayout3.addWidget(self.themeComboBox) + self.gridLayout.addLayout(self.horizontalLayout3, 2, 0, 1, 1) + self.horizontalLayout2 = QtGui.QHBoxLayout() + self.horizontalLayout2.setObjectName(u'horizontalLayout2') + self.creditLabel = QtGui.QLabel(customEditDialog) + self.creditLabel.setObjectName(u'creditLabel') + self.horizontalLayout2.addWidget(self.creditLabel) + self.creditEdit = QtGui.QLineEdit(customEditDialog) + self.creditLabel.setBuddy(self.creditEdit) + self.creditEdit.setObjectName(u'creditEdit') + self.horizontalLayout2.addWidget(self.creditEdit) + self.gridLayout.addLayout(self.horizontalLayout2, 3, 0, 1, 1) + self.buttonBox = QtGui.QDialogButtonBox(customEditDialog) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | + QtGui.QDialogButtonBox.Save) + self.buttonBox.setObjectName(u'buttonBox') + self.gridLayout.addWidget(self.buttonBox, 4, 0, 1, 1) + self.horizontalLayout4 = QtGui.QHBoxLayout() + self.horizontalLayout4.setObjectName(u'horizontalLayout4') + self.slideListView = QtGui.QListWidget(customEditDialog) + self.slideListView.setAlternatingRowColors(True) + self.slideListView.setObjectName(u'slideListView') + self.horizontalLayout4.addWidget(self.slideListView) + self.verticalLayout = QtGui.QVBoxLayout() + self.verticalLayout.setObjectName(u'verticalLayout') + self.addButton = QtGui.QPushButton(customEditDialog) + self.addButton.setObjectName(u'addButton') + self.verticalLayout.addWidget(self.addButton) + self.editButton = QtGui.QPushButton(customEditDialog) + self.editButton.setObjectName(u'editButton') + self.verticalLayout.addWidget(self.editButton) + self.editAllButton = QtGui.QPushButton(customEditDialog) + self.editAllButton.setObjectName(u'editAllButton') + self.verticalLayout.addWidget(self.editAllButton) + self.deleteButton = QtGui.QPushButton(customEditDialog) + self.deleteButton.setObjectName(u'deleteButton') + self.verticalLayout.addWidget(self.deleteButton) + spacerItem = QtGui.QSpacerItem(20, 128, QtGui.QSizePolicy.Minimum, + QtGui.QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem) + self.upButton = QtGui.QPushButton(customEditDialog) + icon1 = QtGui.QIcon() + icon1.addPixmap(QtGui.QPixmap(u':/services/service_up.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.upButton.setIcon(icon1) + self.upButton.setObjectName(u'upButton') + self.verticalLayout.addWidget(self.upButton) + self.downButton = QtGui.QPushButton(customEditDialog) + icon2 = QtGui.QIcon() + icon2.addPixmap(QtGui.QPixmap(u':/services/service_down.png'), + QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.downButton.setIcon(icon2) + self.downButton.setObjectName(u'downButton') + self.verticalLayout.addWidget(self.downButton) + self.horizontalLayout4.addLayout(self.verticalLayout) + self.gridLayout.addLayout(self.horizontalLayout4, 1, 0, 1, 1) self.horizontalLayout = QtGui.QHBoxLayout() self.horizontalLayout.setObjectName(u'horizontalLayout') self.titleLabel = QtGui.QLabel(customEditDialog) @@ -46,91 +110,6 @@ class Ui_CustomEditDialog(object): self.titleEdit.setObjectName(u'titleEdit') self.horizontalLayout.addWidget(self.titleEdit) self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) - self.horizontalLayout4 = QtGui.QHBoxLayout() - self.horizontalLayout4.setObjectName(u'horizontalLayout4') - self.verseListView = QtGui.QListWidget(customEditDialog) - self.verseListView.setAlternatingRowColors(True) - self.verseListView.setObjectName(u'verseListView') - self.horizontalLayout4.addWidget(self.verseListView) - self.verticalLayout = QtGui.QVBoxLayout() - self.verticalLayout.setObjectName(u'verticalLayout') - self.upButton = QtGui.QPushButton(customEditDialog) - self.upButton.setIcon(build_icon(u':/services/service_up.png')) - self.upButton.setObjectName(u'upButton') - self.verticalLayout.addWidget(self.upButton) - spacerItem = QtGui.QSpacerItem(20, 128, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem) - self.downButton = QtGui.QPushButton(customEditDialog) - self.downButton.setIcon(build_icon(u':/services/service_down.png')) - self.downButton.setObjectName(u'downButton') - self.verticalLayout.addWidget(self.downButton) - self.horizontalLayout4.addLayout(self.verticalLayout) - self.gridLayout.addLayout(self.horizontalLayout4, 1, 0, 1, 1) - self.editWidget = QtGui.QWidget(customEditDialog) - self.editWidget.setObjectName(u'editWidget') - self.editLayout3 = QtGui.QHBoxLayout(self.editWidget) - self.editLayout3.setSpacing(8) - self.editLayout3.setMargin(0) - self.editLayout3.setObjectName(u'editLayout3') - self.verseTextEdit = SpellTextEdit(self) - self.verseTextEdit.setObjectName(u'verseTextEdit') - self.editLayout3.addWidget(self.verseTextEdit) - self.buttonWidget = QtGui.QWidget(self.editWidget) - self.buttonWidget.setObjectName(u'buttonWidget') - self.verticalLayout2 = QtGui.QVBoxLayout(self.buttonWidget) - self.verticalLayout2.setObjectName(u'verticalLayout2') - self.addButton = QtGui.QPushButton(self.buttonWidget) - self.addButton.setObjectName(u'addButton') - self.verticalLayout2.addWidget(self.addButton) - self.editButton = QtGui.QPushButton(self.buttonWidget) - self.editButton.setObjectName(u'editButton') - self.verticalLayout2.addWidget(self.editButton) - self.editAllButton = QtGui.QPushButton(self.buttonWidget) - self.editAllButton.setObjectName(u'editAllButton') - self.verticalLayout2.addWidget(self.editAllButton) - self.saveButton = QtGui.QPushButton(self.buttonWidget) - self.saveButton.setObjectName(u'saveButton') - self.verticalLayout2.addWidget(self.saveButton) - self.deleteButton = QtGui.QPushButton(self.buttonWidget) - self.deleteButton.setObjectName(u'deleteButton') - self.verticalLayout2.addWidget(self.deleteButton) - self.clearButton = QtGui.QPushButton(self.buttonWidget) - self.clearButton.setObjectName(u'clearButton') - self.verticalLayout2.addWidget(self.clearButton) - self.splitButton = QtGui.QPushButton(self.buttonWidget) - self.splitButton.setObjectName(u'splitButton') - self.verticalLayout2.addWidget(self.splitButton) - spacerItem1 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, - QtGui.QSizePolicy.Expanding) - self.verticalLayout2.addItem(spacerItem1) - self.editLayout3.addWidget(self.buttonWidget) - self.gridLayout.addWidget(self.editWidget, 2, 0, 1, 1) - self.horizontalLayout3 = QtGui.QHBoxLayout() - self.horizontalLayout3.setObjectName(u'horizontalLayout3') - self.themeLabel = QtGui.QLabel(customEditDialog) - self.themeLabel.setObjectName(u'themeLabel') - self.horizontalLayout3.addWidget(self.themeLabel) - self.themeComboBox = QtGui.QComboBox(customEditDialog) - self.themeLabel.setBuddy(self.themeComboBox) - self.themeComboBox.setObjectName(u'themeComboBox') - self.horizontalLayout3.addWidget(self.themeComboBox) - self.gridLayout.addLayout(self.horizontalLayout3, 3, 0, 1, 1) - self.horizontalLayout2 = QtGui.QHBoxLayout() - self.horizontalLayout2.setObjectName(u'horizontalLayout2') - self.creditLabel = QtGui.QLabel(customEditDialog) - self.creditLabel.setObjectName(u'creditLabel') - self.horizontalLayout2.addWidget(self.creditLabel) - self.creditEdit = QtGui.QLineEdit(customEditDialog) - self.creditLabel.setBuddy(self.creditEdit) - self.creditEdit.setObjectName(u'creditEdit') - self.horizontalLayout2.addWidget(self.creditEdit) - self.gridLayout.addLayout(self.horizontalLayout2, 4, 0, 1, 1) - self.buttonBox = QtGui.QDialogButtonBox(customEditDialog) - self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | - QtGui.QDialogButtonBox.Save) - self.buttonBox.setObjectName(u'buttonBox') - self.gridLayout.addWidget(self.buttonBox, 5, 0, 1, 1) self.retranslateUi(customEditDialog) QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), customEditDialog.accept) @@ -143,46 +122,32 @@ class Ui_CustomEditDialog(object): translate('CustomPlugin.EditCustomForm', 'Edit Custom Slides')) self.upButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Move slide up one ' - 'position.')) + 'position.')) self.downButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Move slide down one ' - 'position.')) + 'position.')) self.titleLabel.setText( translate('CustomPlugin.EditCustomForm', '&Title:')) self.addButton.setText( - translate('CustomPlugin.EditCustomForm', 'Add New')) + translate('CustomPlugin.EditCustomForm', '&Add')) self.addButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Add a new slide at ' - 'bottom.')) + 'bottom.')) self.editButton.setText( - translate('CustomPlugin.EditCustomForm', 'Edit')) + translate('CustomPlugin.EditCustomForm', '&Edit')) self.editButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Edit the selected ' - 'slide.')) + 'slide.')) self.editAllButton.setText( - translate('CustomPlugin.EditCustomForm', 'Edit All')) + translate('CustomPlugin.EditCustomForm', 'Ed&it All')) self.editAllButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Edit all the slides at ' - 'once.')) - self.saveButton.setText( - translate('CustomPlugin.EditCustomForm', 'Save')) - self.saveButton.setToolTip( - translate('CustomPlugin.EditCustomForm', 'Save the slide currently ' - 'being edited.')) + 'once.')) self.deleteButton.setText( - translate('CustomPlugin.EditCustomForm', 'Delete')) + translate('CustomPlugin.EditCustomForm', '&Delete')) self.deleteButton.setToolTip( translate('CustomPlugin.EditCustomForm', 'Delete the selected ' - 'slide.')) - self.clearButton.setText( - translate('CustomPlugin.EditCustomForm', 'Clear')) - self.clearButton.setToolTip( - translate('CustomPlugin.EditCustomForm', 'Clear edit area')) - self.splitButton.setText( - translate('CustomPlugin.EditCustomForm', 'Split Slide')) - self.splitButton.setToolTip( - translate('CustomPlugin.EditCustomForm', 'Split a slide into two ' - 'by inserting a slide splitter.')) + 'slide.')) self.themeLabel.setText( translate('CustomPlugin.EditCustomForm', 'The&me:')) self.creditLabel.setText( diff --git a/openlp/plugins/custom/forms/editcustomform.py b/openlp/plugins/custom/forms/editcustomform.py index 910fe65e7..8ee4d2673 100644 --- a/openlp/plugins/custom/forms/editcustomform.py +++ b/openlp/plugins/custom/forms/editcustomform.py @@ -32,6 +32,7 @@ from openlp.core.lib import Receiver, translate from openlp.plugins.custom.lib import CustomXMLBuilder, CustomXMLParser from openlp.plugins.custom.lib.db import CustomSlide from editcustomdialog import Ui_CustomEditDialog +from editcustomslideform import EditCustomSlideForm log = logging.getLogger(__name__) @@ -40,7 +41,7 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): Class documentation goes here. """ log.info(u'Custom Editor loaded') - def __init__(self, custommanager, parent = None): + def __init__(self, custommanager, parent=None): """ Constructor """ @@ -61,28 +62,20 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): QtCore.SIGNAL(u'pressed()'), self.onEditButtonPressed) QtCore.QObject.connect(self.editAllButton, QtCore.SIGNAL(u'pressed()'), self.onEditAllButtonPressed) - QtCore.QObject.connect(self.saveButton, - QtCore.SIGNAL(u'pressed()'), self.onSaveButtonPressed) QtCore.QObject.connect(self.deleteButton, QtCore.SIGNAL(u'pressed()'), self.onDeleteButtonPressed) - QtCore.QObject.connect(self.clearButton, - QtCore.SIGNAL(u'pressed()'), self.onClearButtonPressed) QtCore.QObject.connect(self.upButton, QtCore.SIGNAL(u'pressed()'), self.onUpButtonPressed) QtCore.QObject.connect(self.downButton, QtCore.SIGNAL(u'pressed()'), self.onDownButtonPressed) - QtCore.QObject.connect(self.splitButton, - QtCore.SIGNAL(u'pressed()'), self.onSplitButtonPressed) - QtCore.QObject.connect(self.verseListView, - QtCore.SIGNAL(u'itemDoubleClicked(QListWidgetItem*)'), - self.onVerseListViewSelected) - QtCore.QObject.connect(self.verseListView, + QtCore.QObject.connect(self.slideListView, QtCore.SIGNAL(u'itemClicked(QListWidgetItem*)'), - self.onVerseListViewPressed) + self.onSlideListViewPressed) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'theme_update_list'), self.loadThemes) - # Create other objects and forms + # Create other objects and forms. self.custommanager = custommanager + self.editSlideForm = EditCustomSlideForm(self) self.initialise() def onPreview(self, button): @@ -92,21 +85,15 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): Receiver.send_message(u'custom_preview') def initialise(self): - self.editAll = False self.addButton.setEnabled(True) self.deleteButton.setEnabled(False) self.editButton.setEnabled(False) self.editAllButton.setEnabled(True) - self.saveButton.setEnabled(False) - self.clearButton.setEnabled(False) - self.splitButton.setEnabled(False) self.titleEdit.setText(u'') self.creditEdit.setText(u'') - self.verseTextEdit.clear() - self.verseListView.clear() - #make sure we have a new item + self.slideListView.clear() + # Make sure we have a new item. self.customSlide = CustomSlide() - self.themeComboBox.addItem(u'') def loadThemes(self, themelist): self.themeComboBox.clear() @@ -115,6 +102,16 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.themeComboBox.addItem(themename) def loadCustom(self, id, preview=False): + """ + Called when editing or creating a new custom. + + ``id`` + The cutom's id. If zero, then a new custom is created. + + ``preview`` + States whether the custom is edited while being previewed in the + preview panel. + """ self.customSlide = CustomSlide() self.initialise() if id != 0: @@ -122,9 +119,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.titleEdit.setText(self.customSlide.title) self.creditEdit.setText(self.customSlide.credits) customXML = CustomXMLParser(self.customSlide.text) - verseList = customXML.get_verses() - for verse in verseList: - self.verseListView.addItem(verse[1]) + slideList = customXML.get_verses() + for slide in slideList: + self.slideListView.addItem(slide[1]) theme = self.customSlide.theme_name id = self.themeComboBox.findText(theme, QtCore.Qt.MatchExactly) if id == -1: @@ -132,7 +129,8 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.themeComboBox.setCurrentIndex(id) else: self.themeComboBox.setCurrentIndex(0) - #if not preview hide the preview button + self.editAllButton.setEnabled(False) + # If not preview hide the preview button. self.previewButton.setVisible(False) if preview: self.previewButton.setVisible(True) @@ -148,6 +146,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): self.close() def saveCustom(self): + """ + Saves the custom. + """ valid, message = self._validate() if not valid: QtGui.QMessageBox.critical(self, @@ -157,9 +158,9 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): sxml.new_document() sxml.add_lyrics_to_song() count = 1 - for i in range(0, self.verseListView.count()): + for i in range(0, self.slideListView.count()): sxml.add_verse_to_lyrics(u'custom', unicode(count), - unicode(self.verseListView.item(i).text())) + unicode(self.slideListView.item(i).text())) count += 1 self.customSlide.title = unicode(self.titleEdit.displayText(), u'utf-8') self.customSlide.text = unicode(sxml.extract_xml(), u'utf-8') @@ -170,114 +171,103 @@ class EditCustomForm(QtGui.QDialog, Ui_CustomEditDialog): return self.custommanager.save_object(self.customSlide) def onUpButtonPressed(self): - selectedRow = self.verseListView.currentRow() + selectedRow = self.slideListView.currentRow() if selectedRow != 0: - qw = self.verseListView.takeItem(selectedRow) - self.verseListView.insertItem(selectedRow - 1, qw) - self.verseListView.setCurrentRow(selectedRow - 1) + qw = self.slideListView.takeItem(selectedRow) + self.slideListView.insertItem(selectedRow - 1, qw) + self.slideListView.setCurrentRow(selectedRow - 1) def onDownButtonPressed(self): - selectedRow = self.verseListView.currentRow() + selectedRow = self.slideListView.currentRow() # zero base arrays - if selectedRow != self.verseListView.count() - 1: - qw = self.verseListView.takeItem(selectedRow) - self.verseListView.insertItem(selectedRow + 1, qw) - self.verseListView.setCurrentRow(selectedRow + 1) + if selectedRow != self.slideListView.count() - 1: + qw = self.slideListView.takeItem(selectedRow) + self.slideListView.insertItem(selectedRow + 1, qw) + self.slideListView.setCurrentRow(selectedRow + 1) - def onClearButtonPressed(self): - self.verseTextEdit.clear() - self.editAll = False - self.addButton.setEnabled(True) - self.editAllButton.setEnabled(True) - self.saveButton.setEnabled(False) - - def onVerseListViewPressed(self, item): + def onSlideListViewPressed(self, item): self.deleteButton.setEnabled(True) self.editButton.setEnabled(True) - def onVerseListViewSelected(self, item): - self.editText(item.text()) - def onAddButtonPressed(self): - self.verseListView.addItem(self.verseTextEdit.toPlainText()) - self.deleteButton.setEnabled(False) - self.verseTextEdit.clear() + self.editSlideForm.setText(u'') + if self.editSlideForm.exec_(): + for slide in self.editSlideForm.getText(): + self.slideListView.addItem(slide) + self.editAllButton.setEnabled(True) def onEditButtonPressed(self): - self.editText(self.verseListView.currentItem().text()) + self.editSlideForm.setText(self.slideListView.currentItem().text()) + if self.editSlideForm.exec_(): + self.updateSlideList(self.editSlideForm.getText()) def onEditAllButtonPressed(self): - self.editAll = True - self.addButton.setEnabled(False) - self.splitButton.setEnabled(True) - if self.verseListView.count() > 0: - verse_list = u'' - for row in range(0, self.verseListView.count()): - item = self.verseListView.item(row) - verse_list += item.text() - if row != self.verseListView.count() - 1: - verse_list += u'\n[---]\n' - self.editText(verse_list) + """ + Edits all slides. + """ + if self.slideListView.count() > 0: + slide_list = u'' + for row in range(0, self.slideListView.count()): + item = self.slideListView.item(row) + slide_list += item.text() + if row != self.slideListView.count() - 1: + slide_list += u'\n[---]\n' + self.editSlideForm.setText(slide_list) + if self.editSlideForm.exec_(): + self.updateSlideList(self.editSlideForm.getText(), True) - def editText(self, text): - self.beforeText = text - self.verseTextEdit.setPlainText(text) - self.deleteButton.setEnabled(False) - self.editButton.setEnabled(False) - self.editAllButton.setEnabled(False) - self.saveButton.setEnabled(True) - self.clearButton.setEnabled(True) + def updateSlideList(self, slides, edit_all=False): + """ + Updates the slide list after editing slides. - def onSaveButtonPressed(self): - if self.editAll: - self.verseListView.clear() - for row in unicode(self.verseTextEdit.toPlainText()).split( - u'\n[---]\n'): - self.verseListView.addItem(row) + ``slides`` + A list of all slides which have been edited. + + ``edit_all`` + Indicates if all slides or only one slide has been edited. + """ + if len(slides) == 1: + self.slideListView.currentItem().setText(slides[0]) else: - self.verseListView.currentItem().setText( - self.verseTextEdit.toPlainText()) - #number of lines has change - if len(self.beforeText.split(u'\n')) != \ - len(self.verseTextEdit.toPlainText().split(u'\n')): - tempList = {} - for row in range(0, self.verseListView.count()): - tempList[row] = self.verseListView.item(row).text() - self.verseListView.clear() - for row in range (0, len(tempList)): - self.verseListView.addItem(tempList[row]) - self.verseListView.repaint() - self.addButton.setEnabled(True) - self.saveButton.setEnabled(False) - self.editButton.setEnabled(False) - self.editAllButton.setEnabled(True) - self.splitButton.setEnabled(False) - self.verseTextEdit.clear() - - def onSplitButtonPressed(self): - if self.verseTextEdit.textCursor().columnNumber() != 0: - self.verseTextEdit.insertPlainText(u'\n') - self.verseTextEdit.insertPlainText(u'[---]\n' ) - self.verseTextEdit.setFocus() + if edit_all: + self.slideListView.clear() + for slide in slides: + self.slideListView.addItem(slide) + else: + old_slides = [] + old_row = self.slideListView.currentRow() + # Create a list with all (old/unedited) slides. + old_slides = [self.slideListView.item(row).text() for row in \ + range(0, self.slideListView.count())] + self.slideListView.clear() + old_slides.pop(old_row) + # Insert all slides to make the old_slides list complete. + for slide in slides: + old_slides.insert(old_row, slide) + for slide in old_slides: + self.slideListView.addItem(slide) + self.slideListView.repaint() def onDeleteButtonPressed(self): - self.verseListView.takeItem(self.verseListView.currentRow()) - self.editButton.setEnabled(False) + self.slideListView.takeItem(self.slideListView.currentRow()) + self.editButton.setEnabled(True) self.editAllButton.setEnabled(True) + if self.slideListView.count() == 0: + self.deleteButton.setEnabled(False) + self.editButton.setEnabled(False) + self.editAllButton.setEnabled(False) def _validate(self): + """ + Checks whether a custom is valid or not. + """ + # We must have a title. if len(self.titleEdit.displayText()) == 0: self.titleEdit.setFocus() return False, translate('CustomPlugin.EditCustomForm', 'You need to type in a title.') - # must have 1 slide - if self.verseListView.count() == 0: - self.verseTextEdit.setFocus() + # We must have one slide. + if self.slideListView.count() == 0: return False, translate('CustomPlugin.EditCustomForm', 'You need to add at least one slide') - if self.verseTextEdit.toPlainText(): - self.verseTextEdit.setFocus() - return False, translate('CustomPlugin.EditCustomForm', - 'You have one or more unsaved slides, please either save your ' - 'slide(s) or clear your changes.') return True, u'' diff --git a/openlp/plugins/custom/forms/editcustomslidedialog.py b/openlp/plugins/custom/forms/editcustomslidedialog.py new file mode 100644 index 000000000..ce4cf6e29 --- /dev/null +++ b/openlp/plugins/custom/forms/editcustomslidedialog.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 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 translate, SpellTextEdit + +class Ui_CustomSlideEditDialog(object): + def setupUi(self, customSlideEditDialog): + customSlideEditDialog.setObjectName(u'customSlideEditDialog') + customSlideEditDialog.resize(474, 442) + self.buttonBox = QtGui.QDialogButtonBox(customSlideEditDialog) + self.buttonBox.setGeometry(QtCore.QRect(8, 407, 458, 32)) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel | + QtGui.QDialogButtonBox.Save) + self.buttonBox.setObjectName(u'buttonBox') + self.slideTextEdit = SpellTextEdit(self) + self.slideTextEdit.setGeometry(QtCore.QRect(8, 8, 458, 349)) + self.slideTextEdit.setObjectName(u'slideTextEdit') + self.splitButton = QtGui.QPushButton(customSlideEditDialog) + self.splitButton.setGeometry(QtCore.QRect(380, 370, 85, 27)) + self.splitButton.setObjectName(u'splitButton') + self.retranslateUi(customSlideEditDialog) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'accepted()'), + customSlideEditDialog.accept) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL(u'rejected()'), + customSlideEditDialog.reject) + QtCore.QMetaObject.connectSlotsByName(customSlideEditDialog) + + def retranslateUi(self, customSlideEditDialog): + self.splitButton.setText( + translate('CustomPlugin.EditCustomForm', 'Split Slide')) + self.splitButton.setToolTip( + translate('CustomPlugin.EditCustomForm', 'Split a slide into two ' + 'by inserting a slide splitter.')) diff --git a/openlp/plugins/custom/forms/editcustomslideform.py b/openlp/plugins/custom/forms/editcustomslideform.py new file mode 100644 index 000000000..ff396658f --- /dev/null +++ b/openlp/plugins/custom/forms/editcustomslideform.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4 + +############################################################################### +# OpenLP - Open Source Lyrics Projection # +# --------------------------------------------------------------------------- # +# Copyright (c) 2008-2010 Raoul Snyman # +# Portions copyright (c) 2008-2010 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 + +from PyQt4 import QtCore, QtGui + +from openlp.core.lib import Receiver, translate +from editcustomslidedialog import Ui_CustomSlideEditDialog + +log = logging.getLogger(__name__) + +class EditCustomSlideForm(QtGui.QDialog, Ui_CustomSlideEditDialog): + """ + Class documentation goes here. + """ + log.info(u'Custom Verse Editor loaded') + def __init__(self, parent=None): + """ + Constructor + """ + QtGui.QDialog.__init__(self, parent) + self.setupUi(self) + # Connecting signals and slots + QtCore.QObject.connect(self.splitButton, + QtCore.SIGNAL(u'pressed()'), self.onSplitButtonPressed) + + def setText(self, text): + """ + Set the text for slideTextEdit. + + ``text`` + The text (unicode). + """ + self.slideTextEdit.clear() + if text: + self.slideTextEdit.setPlainText(text) + self.slideTextEdit.setFocus() + + def getText(self): + """ + Returns a list with all slides. + """ + return self.slideTextEdit.toPlainText().split(u'\n[---]\n') + + def onSplitButtonPressed(self): + """ + Splits a slide in two slides. + """ + if self.slideTextEdit.textCursor().columnNumber() != 0: + self.slideTextEdit.insertPlainText(u'\n') + self.slideTextEdit.insertPlainText(u'[---]\n' ) + self.slideTextEdit.setFocus() diff --git a/openlp/plugins/songs/forms/editsongform.py b/openlp/plugins/songs/forms/editsongform.py index 41eef0545..67ff6f32f 100644 --- a/openlp/plugins/songs/forms/editsongform.py +++ b/openlp/plugins/songs/forms/editsongform.py @@ -483,6 +483,8 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog): self.VerseListWidget.resizeRowsToContents() self.VerseListWidget.repaint() self.tagRows() + self.VerseEditButton.setEnabled(False) + self.VerseDeleteButton.setEnabled(False) def onVerseDeleteButtonClicked(self): self.VerseListWidget.removeRow(self.VerseListWidget.currentRow()) diff --git a/openlp/plugins/songs/lib/cclifileimport.py b/openlp/plugins/songs/lib/cclifileimport.py index 9d0da5cfa..669201325 100755 --- a/openlp/plugins/songs/lib/cclifileimport.py +++ b/openlp/plugins/songs/lib/cclifileimport.py @@ -38,9 +38,9 @@ class CCLIFileImportError(Exception): class CCLIFileImport(SongImport): """ - The :class:`CCLIFileImport` class provides OpenLP with the - ability to import CCLI SongSelect song files in both .txt and - .usr formats. See http://www.ccli.com + The :class:`CCLIFileImport` class provides OpenLP with the ability to + import CCLI SongSelect song files in both .txt and .usr formats. + See http://www.ccli.com/ for more details. """ def __init__(self, manager, **kwargs): @@ -49,6 +49,7 @@ class CCLIFileImport(SongImport): ``manager`` The song manager for the running OpenLP installation. + ``filenames`` The files to be imported. """ @@ -97,7 +98,7 @@ class CCLIFileImport(SongImport): def do_import_usr_file(self, textList): """ - The :method:`do_import_usr_file` method provides OpenLP + The :func:`do_import_usr_file` method provides OpenLP with the ability to import CCLI SongSelect songs in *USR* file format @@ -105,6 +106,7 @@ class CCLIFileImport(SongImport): An array of strings containing the usr file content. **SongSelect .usr file format** + ``[File]`` USR file format first line ``Type=`` @@ -140,6 +142,7 @@ class CCLIFileImport(SongImport): Contains the songs various lyrics in order as shown by the *Fields* description e.g. *Words=Above all powers....* [/n = CR, /n/t = CRLF] + """ log.debug(u'USR file text: %s', textList) lyrics = [] @@ -191,48 +194,32 @@ class CCLIFileImport(SongImport): def do_import_txt_file(self, textList): """ - The :method:`do_import_txt_file` method provides OpenLP + The :func:`do_import_txt_file` method provides OpenLP with the ability to import CCLI SongSelect songs in *TXT* file format ``textList`` An array of strings containing the txt file content. - **SongSelect .txt file format** + SongSelect .txt file format:: - ``Song Title`` - Contains the song title - - - - ``Title of following verse/chorus and number`` - e.g. Verse 1, Chorus 1 - - ``Verse/Chorus lyrics`` - - - - - - ``Title of next verse/chorus (repeats)`` - - ``Verse/Chorus lyrics`` - - - - - - ``Song CCLI Number`` - e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885) - ``Song Copyright`` - e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing - ``Song Authors`` - e.g. Lenny LeBlanc | Paul Baloche - ``Licencing info`` - e.g. For use solely with the SongSelect Terms of Use. + Song Title # Contains the song title + + Verse type and number # e.g. Verse 1, Chorus 1 + Verse lyrics + + + Verse type and number (repeats) + Verse lyrics + + + Song CCLI number # e.g. CCLI Number (e.g.CCLI-Liednummer: 2672885) + Song copyright # e.g. © 1999 Integrity's Hosanna! Music | LenSongs Publishing + Song authors # e.g. Lenny LeBlanc | Paul Baloche + Licencing info # e.g. For use solely with the SongSelect Terms of Use. All rights Reserved. www.ccli.com - ``CCLI Licence number of user`` - e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14 + CCLI Licence number of user # e.g. CCL-Liedlizenznummer: 14 / CCLI License No. 14 + """ log.debug(u'TXT file text: %s', textList) self.set_defaults() diff --git a/openlp/plugins/songs/lib/songxml.py b/openlp/plugins/songs/lib/songxml.py index 4068c396f..6818218c5 100644 --- a/openlp/plugins/songs/lib/songxml.py +++ b/openlp/plugins/songs/lib/songxml.py @@ -282,11 +282,9 @@ class Song(object): def get_author_list(self, asOneString = True): """Return the list of authors as a string - asOneString - True -- string: - 'John Newton, A Parker' - False -- list of strings - ['John Newton', u'A Parker'] + ``asOneString`` + If ``True``, returns 'John Newton, A Parker'. If ``False``, returns + [u'John Newton', u'A Parker'] """ if asOneString: res = self._assure_string(self.author_list) @@ -297,7 +295,8 @@ class Song(object): def set_author_list(self, author_list): """Set the author_list - author_list -- a string or list of strings + ``author_list`` + a string or list of strings """ if author_list is None: self.author_list = None @@ -307,11 +306,9 @@ class Song(object): def get_category_array(self, asOneString = True): """Return the list of categories as a string - asOneString - True -- string: - 'Hymn, Gospel' - False -- list of strings - ['Hymn', u'Gospel'] + ``asOneString`` + If ``True``, returns 'Hymn, Gospel'. If ``False``, returns + [u'Hymn', u'Gospel'] """ if asOneString: res = self._assure_string(self.category_array) @@ -381,6 +378,7 @@ class Song(object): properties slideNumber -- 1 .. numberOfSlides + Returns a list as: [theme_name (string), title (string), diff --git a/openlp/plugins/songs/lib/wowimport.py b/openlp/plugins/songs/lib/wowimport.py index 879d56704..2f20cf20d 100644 --- a/openlp/plugins/songs/lib/wowimport.py +++ b/openlp/plugins/songs/lib/wowimport.py @@ -24,7 +24,7 @@ # Temple Place, Suite 330, Boston, MA 02111-1307 USA # ############################################################################### """ -The :mod:`wowimport` module provides the functionality for importing Words of +The :mod:`wowimport` module provides the functionality for importing Words of Worship songs into the OpenLP database. """ import os @@ -38,19 +38,18 @@ log = logging.getLogger(__name__) class WowImport(SongImport): """ - The :class:`WowImport` class provides the ability to import song files from + The :class:`WowImport` class provides the ability to import song files from Words of Worship. - Words Of Worship Song File Format - ````````````````````````````````` - + **Words Of Worship Song File Format:** + The Words Of Worship song file format is as follows: * The song title is the file name minus the extension. - * The song has a header, a number of blocks, followed by footer containing - the author and the copyright. + * The song has a header, a number of blocks, followed by footer containing + the author and the copyright. * A block can be a verse, chorus or bridge. - + File Header: Bytes are counted from one, i.e. the first byte is byte 1. These bytes, up to the 56 byte, can change but no real meaning has been found. The @@ -65,29 +64,29 @@ class WowImport(SongImport): Each block ends with 4 bytes, the first of which defines what type of block it is, and the rest which are null bytes: - * ``NUL`` (\x00) - Verse - * ``SOH`` (\x01) - Chorus - * ``STX`` (\x02) - Bridge + * ``NUL`` (0x00) - Verse + * ``SOH`` (0x01) - Chorus + * ``STX`` (0x02) - Bridge - Blocks are seperated by two bytes. The first byte is ``SOH`` (\x01), - and the second byte is ``€`` (\x80). + Blocks are seperated by two bytes. The first byte is 0x01, and the + second byte is 0x80. Lines: Each line starts with a byte which specifies how long that line is, the line text, and ends with a null byte. - + Footer: - The footer follows on after the last block, the first byte specifies - the length of the author text, followed by the author text, if - this byte is null, then there is no author text. The byte after the - author text specifies the length of the copyright text, followed - by the copyright text. - + The footer follows on after the last block, the first byte specifies + the length of the author text, followed by the author text, if + this byte is null, then there is no author text. The byte after the + author text specifies the length of the copyright text, followed + by the copyright text. + The file is ended with four null bytes. - + Valid extensions for a Words of Worship song file are: - + * .wsg * .wow-song """ @@ -111,7 +110,7 @@ class WowImport(SongImport): """ Recieve a single file, or a list of files to import. """ - + if isinstance(self.import_source, list): self.import_wizard.importProgressBar.setMaximum( len(self.import_source)) @@ -127,14 +126,14 @@ class WowImport(SongImport): if self.songData.read(19) != u'WoW File\nSong Words': continue # Seek to byte which stores number of blocks in the song - self.songData.seek(56) + self.songData.seek(56) self.no_of_blocks = ord(self.songData.read(1)) # Seek to the beging of the first block - self.songData.seek(82) + self.songData.seek(82) for block in range(self.no_of_blocks): self.lines_to_read = ord(self.songData.read(1)) # Skip 3 nulls to the beginnig of the 1st line - self.songData.seek(3, os.SEEK_CUR) + self.songData.seek(3, os.SEEK_CUR) self.block_text = u'' while self.lines_to_read: self.length_of_line = ord(self.songData.read(1)) @@ -148,7 +147,7 @@ class WowImport(SongImport): self.block_type = BLOCK_TYPES[ord(self.songData.read(1))] # Skip 3 nulls at the end of the block self.songData.seek(3, os.SEEK_CUR) - # Blocks are seperated by 2 bytes, skip them, but not if + # Blocks are seperated by 2 bytes, skip them, but not if # this is the last block! if (block + 1) < self.no_of_blocks: self.songData.seek(2, os.SEEK_CUR) @@ -170,4 +169,4 @@ class WowImport(SongImport): self.import_wizard.incrementProgressBar( "Importing %s" % (self.file_name)) return True - + diff --git a/resources/forms/editcustomdialog.ui b/resources/forms/editcustomdialog.ui index 44ce46ca7..7c714baab 100644 --- a/resources/forms/editcustomdialog.ui +++ b/resources/forms/editcustomdialog.ui @@ -18,20 +18,48 @@ :/icon/openlp.org-icon-32.bmp:/icon/openlp.org-icon-32.bmp - - + + - + - Title: + Theme: - + + + + + + + + + + + Credits: + + + + + + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + @@ -44,16 +72,42 @@ - + - + - + Add New - - - :/services/service_up.png:/services/service_up.png + + + + + + + + + Edit + + + + + + + + + + Edit All + + + + + + + + + + Delete @@ -70,6 +124,20 @@ + + + + + + + + + + + :/services/service_up.png:/services/service_up.png + + + @@ -88,166 +156,26 @@ - - - - - 8 - - - 0 - - - - - - - - - - - - - - Add New - - - - - - - - - - Edit - - - - - - - - - - Edit All - - - - - - - - - - Save - - - - - - - - - - Delete - - - - - - - - - - Clear - - - - - - - - - - Split Slide - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - + + - + - Theme: + Title: - - - - - + - - - - - - Credits: - - - - - - - - - - - - - - - QDialogButtonBox::Cancel|QDialogButtonBox::Save - - - TitleEdit - VerseTextEdit - AddButton VerseListView - EditButton - EditAllButton - SaveButton - DeleteButton CreditEdit - UpButton - DownButton ThemeComboBox diff --git a/resources/forms/editcustomslidedialog.ui b/resources/forms/editcustomslidedialog.ui new file mode 100644 index 000000000..f537f854e --- /dev/null +++ b/resources/forms/editcustomslidedialog.ui @@ -0,0 +1,96 @@ + + + customSlideEditDialog + + + + 0 + 0 + 474 + 442 + + + + Dialog + + + + + 8 + 407 + 458 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Save + + + + + + 8 + 8 + 458 + 349 + + + + + + + 380 + 370 + 85 + 27 + + + + + + + Split Slide + + + + + + + + + buttonBox + accepted() + customSlideEditDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + customSlideEditDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/resources/innosetup/LICENSE.txt b/resources/windows/LICENSE.txt similarity index 100% rename from resources/innosetup/LICENSE.txt rename to resources/windows/LICENSE.txt diff --git a/resources/innosetup/OpenLP-2.0.iss b/resources/windows/OpenLP-2.0.iss similarity index 97% rename from resources/innosetup/OpenLP-2.0.iss rename to resources/windows/OpenLP-2.0.iss index e75f1076f..94ee4fc22 100644 --- a/resources/innosetup/OpenLP-2.0.iss +++ b/resources/windows/OpenLP-2.0.iss @@ -27,6 +27,7 @@ DefaultDirName={pf}\{#AppName} DefaultGroupName={#AppVerName} AllowNoIcons=true LicenseFile=LICENSE.txt +OutputDir=..\..\dist OutputBaseFilename=OpenLP-{#RealVersion}-setup Compression=lzma SolidCompression=true diff --git a/resources/innosetup/OpenLP.ico b/resources/windows/OpenLP.ico similarity index 100% rename from resources/innosetup/OpenLP.ico rename to resources/windows/OpenLP.ico diff --git a/resources/innosetup/OpenLP.reg b/resources/windows/OpenLP.reg similarity index 100% rename from resources/innosetup/OpenLP.reg rename to resources/windows/OpenLP.reg diff --git a/resources/windows/OpenLP.spec b/resources/windows/OpenLP.spec new file mode 100644 index 000000000..47a1952f3 --- /dev/null +++ b/resources/windows/OpenLP.spec @@ -0,0 +1,14 @@ +# -*- mode: python -*- +a = Analysis([ + os.path.join(HOMEPATH, 'support\\_mountzlib.py'), + os.path.join(HOMEPATH, 'support\\useUnicode.py'), + os.path.abspath('openlp.pyw')], + pathex=[os.path.abspath('.')]) +pyz = PYZ(a.pure) +exe = EXE(pyz, a.scripts, exclude_binaries=1, + name=os.path.abspath(os.path.join('build', 'pyi.win32', 'OpenLP', + 'OpenLP.exe')), + debug=False, strip=False, upx=True, console=False, + icon=os.path.abspath(os.path.join('resources', 'images', 'OpenLP.ico'))) +coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, + name=os.path.abspath(os.path.join('dist', 'OpenLP'))) diff --git a/resources/innosetup/openlp.conf b/resources/windows/openlp.conf similarity index 100% rename from resources/innosetup/openlp.conf rename to resources/windows/openlp.conf diff --git a/resources/windows/warnOpenLP.txt b/resources/windows/warnOpenLP.txt new file mode 100644 index 000000000..19c579942 --- /dev/null +++ b/resources/windows/warnOpenLP.txt @@ -0,0 +1,611 @@ +W: no module named openlp.core.lib.build_html (top-level import by openlp.core.ui.maindisplay) +W: no module named mx (top-level import by sqlite.main) +W: no module named ctypes.create_string_buffer (delayed import by urllib) +W: no module named openlp.core.ui.ServiceNoteForm (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.ui.mainwindow) +W: no module named email.Iterators (delayed import by email.message) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named sqlalchemy.sql.join (top-level import by sqlalchemy) +W: no module named java (conditional import by xml.sax._exceptions) +W: no module named openlp.plugins.images.lib.ImageMediaItem (top-level import by openlp.plugins.images.imageplugin) +W: no module named sqlalchemy.SMALLINT (top-level import by sqlalchemy.databases.sybase) +W: no module named sqlalchemy.engine.create_engine (top-level import by sqlalchemy) +W: no module named sqlalchemy.sql.asc (top-level import by sqlalchemy) +W: no module named openlp.plugins.bibles.lib.BiblesTab (top-level import by openlp.plugins.bibles.bibleplugin) +W: no module named PyQt4._qt (top-level import by PyQt4.QtCore) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.lib.alertstab) +W: no module named sqlalchemy.Column (top-level import by openlp.plugins.custom.lib.db) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songusage.songusageplugin) +W: no module named openlp.plugins.alerts.lib.AlertsManager (top-level import by openlp.plugins.alerts.alertsplugin) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.generaltab) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.forms.alertdialog) +W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named sqlalchemy.orm.MapperExtension (top-level import by sqlalchemy.orm.scoping) +W: no module named pyodbc (delayed import by sqlalchemy.databases.access) +W: no module named openlp.core.lib.expand_tags (top-level import by openlp.core.lib.renderer) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.servicemanager) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.dynamic) +W: no module named ctypes._SimpleCData (top-level import by ctypes.wintypes) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.core.ui.generaltab) +W: no module named simplejson (conditional import by openlp.plugins.remotes.lib.httpserver) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.alerts.forms.alertdialog) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.collections) +W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.lib.serviceitem) +W: no module named openlp.plugins.songs.lib.SongXMLParser (top-level import by openlp.plugins.songs.forms.editsongform) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.bibleplugin) +W: no module named xml.dom.XMLNS_NAMESPACE (top-level import by xml.dom.minidom) +W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.lib.songimport) +W: no module named openlp.plugins.songs.lib.SongXMLBuilder (top-level import by openlp.plugins.songs.forms.editsongform) +W: no module named openlp.core.ui.GeneralTab (top-level import by openlp.core.ui.settingsform) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named informixdb (delayed import by sqlalchemy.databases.informix) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.custom.customplugin) +W: no module named cjkcodecs (top-level import by BeautifulSoup) +W: no module named readline (delayed, conditional import by cmd) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.lib.songimport) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.media.mediaplugin) +W: no module named openlp.core.lib.ThemeXML (top-level import by openlp.core.ui.amendthemeform) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.manager) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.ui.maindisplay) +W: no module named openlp.plugins.songs.forms.EditVerseForm (top-level import by openlp.plugins.songs.forms.editsongform) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.ewimport) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.songs.lib.songstab) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.ui.HideMode (top-level import by openlp.core.ui.maindisplay) +W: no module named sqlalchemy.Column (top-level import by sqlalchemy.databases.sybase) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.slidecontroller) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.forms.songimportform) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.aboutdialog) +W: no module named sqlalchemy.sql.insert (top-level import by sqlalchemy) +W: no module named openlp.core.lib.str_to_bool (top-level import by openlp.core.ui.thememanager) +W: no module named sqlalchemy.MetaData (top-level import by sqlalchemy.databases.sybase) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.biblestab) +W: no module named openlp.plugins.bibles.lib.BibleManager (top-level import by openlp.plugins.bibles.bibleplugin) +W: no module named openlp.core.ui.SlideController (top-level import by openlp.core.ui.mainwindow) +W: no module named MacOS (delayed import by platform) +W: no module named openlp.core.lib.ThemeXML (top-level import by openlp.core.ui.thememanager) +W: no module named cx_Oracle (delayed import by sqlalchemy.databases.oracle) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.slidecontroller) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.servicenotedialog) +W: no module named sqlalchemy.sql.except_ (top-level import by sqlalchemy) +W: no module named openlp.core.ui.AboutForm (top-level import by openlp.core.ui.mainwindow) +W: no module named EasyDialogs (conditional import by getpass) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.lib.mediamanageritem) +W: no module named sqlalchemy.orm.SessionExtension (top-level import by sqlalchemy.orm.session) +W: no module named sqlalchemy.orm.relation (top-level import by openlp.plugins.bibles.lib.db) +W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.forms.editsongform) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.lib.http) +W: no module named sqlalchemy.sql.func (top-level import by sqlalchemy) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.utils.languagemanager) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.mainwindow) +W: no module named uno (conditional import by openlp.plugins.songs.lib.oooimport) +W: no module named kinterbasdb (delayed import by sqlalchemy.databases.firebird) +W: no module named multiprocessing.RLock (top-level import by multiprocessing.sharedctypes) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.filerenameform) +W: no module named sqlalchemy.ForeignKey (top-level import by sqlalchemy.databases.mssql) +W: no module named openlp.core.lib.Renderer (top-level import by openlp.core.lib.rendermanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songmaintenancedialog) +W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.lib.mediamanageritem) +W: no module named openlp.core.ui.FileRenameForm (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.songsplugin) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.bibles.bibleplugin) +W: no module named vms_lib (delayed, conditional import by platform) +W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.ui.slidecontroller) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.alerts.lib.alertsmanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedetaildialog) +W: no module named openlp.plugins.remotes.lib.RemoteTab (top-level import by openlp.plugins.remotes.remoteplugin) +W: no module named openlp.core.ui.ServiceManager (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.songusage.forms.songusagedetailform) +W: no module named openlp.core.ui.SettingsForm (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.plugins.alerts.lib.AlertsTab (top-level import by openlp.plugins.alerts.alertsplugin) +W: no module named xdg (delayed, conditional import by openlp.core.utils) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.custom.customplugin) +W: no module named openlp.core.ui.AmendThemeForm (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named posix (delayed, conditional import by iu) +W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.forms.editversedialog) +W: no module named multiprocessing.dummy.Process (delayed import by __main__) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named sqlalchemy.String (top-level import by sqlalchemy.databases.mssql) +W: no module named xml.dom.EMPTY_PREFIX (top-level import by xml.dom.expatbuilder) +W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.lib.mediamanageritem) +W: no module named openlp.core.lib.PluginManager (top-level import by openlp.core.ui.mainwindow) +W: no module named multiprocessing.current_process (top-level import by multiprocessing.reduction) +W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songbookform) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named xmltok (top-level import by pyexpat) +W: no module named openlp.plugins.bibles.lib.SearchResults (top-level import by openlp.plugins.bibles.lib.http) +W: no module named sqlalchemy.sql.delete (top-level import by sqlalchemy) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.lib.oooimport) +W: no module named _emx_link (conditional import by os) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.aboutdialog) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.bibles.forms.bibleimportwizard) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.core.lib.pluginmanager) +W: no module named openlp.plugins.songs.lib.SongsTab (top-level import by openlp.plugins.songs.songsplugin) +W: no module named sqlalchemy.CHAR (top-level import by sqlalchemy.databases.sybase) +W: no module named sqlalchemy.sql.collate (top-level import by sqlalchemy) +W: no module named sqlalchemy.sql.outparam (top-level import by sqlalchemy) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.lib.db) +W: no module named openlp.core.ui.PluginForm (top-level import by openlp.core.ui.mainwindow) +W: no module named gobject (top-level import by enchant.checker.GtkSpellCheckerDialog) +W: no module named openlp.core.utils.VersionThread (top-level import by __main__) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.topicsform) +W: no module named sqlalchemy.Integer (top-level import by sqlalchemy.databases.mssql) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.exceptiondialog) +W: no module named pwd (delayed, conditional import by distutils.util) +W: no module named uno (conditional import by openlp.plugins.presentations.lib.impresscontroller) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.utils) +W: no module named sqlalchemy.orm.class_mapper (top-level import by openlp.plugins.songs.lib.olpimport) +W: no module named sqlalchemy.orm.relation (top-level import by openlp.plugins.songs.lib.olpimport) +W: no module named readline (delayed import by pdb) +W: no module named openlp.core.ui.MainDisplay (top-level import by openlp.core.lib.rendermanager) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named sqlalchemy.Table (top-level import by openlp.plugins.songusage.lib.db) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.alertsplugin) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.forms.importwizardform) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.remotes.remoteplugin) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.images.imageplugin) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.alerts.lib.alertstab) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.editversedialog) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songusage.songusageplugin) +W: no module named openlp.core.ui.HideMode (top-level import by openlp.core.ui.slidecontroller) +W: no module named sqlalchemy.sql.between (top-level import by sqlalchemy) +W: no module named xml.dom.EMPTY_PREFIX (top-level import by xml.dom.minidom) +W: no module named pysqlite2 (delayed import by sqlalchemy.databases.sqlite) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.lib.customtab) +W: no module named gtk (top-level import by enchant.checker.GtkSpellCheckerDialog) +W: no module named xml.dom.EMPTY_NAMESPACE (top-level import by xml.dom.expatbuilder) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.remotes.lib.httpserver) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedeleteform) +W: no module named sqlalchemy.orm.scoped_session (top-level import by openlp.core.lib.db) +W: no module named openlp.core.lib.clean_tags (top-level import by openlp.core.lib.serviceitem) +W: no module named openlp.core.utils.get_filesystem_encoding (top-level import by openlp.core.ui.thememanager) +W: no module named xml.dom.EMPTY_NAMESPACE (top-level import by xml.dom.minidom) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.lib.toolbar) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.remotes.remoteplugin) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.attributes) +W: no module named sqlalchemy.ForeignKey (top-level import by sqlalchemy.databases.sybase) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.servicemanager) +W: no module named sqlalchemy.Column (top-level import by openlp.plugins.alerts.lib.db) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.core.ui.advancedtab) +W: no module named AES (delayed, conditional import by archive) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.forms.songmaintenanceform) +W: no module named openlp.core.lib.context_menu_separator (top-level import by openlp.core.lib.mediamanageritem) +W: no module named fcntl (top-level import by tempfile) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.thememanager) +W: no module named mx (top-level import by sqlalchemy.databases.mxODBC) +W: no module named sqlalchemy.sql.union (top-level import by sqlalchemy) +W: no module named openlp.plugins.songs.forms.TopicsForm (top-level import by openlp.plugins.songs.forms.songmaintenanceform) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named MacOS (delayed import by distutils.sysconfig) +W: no module named openlp.core.lib.SpellTextEdit (top-level import by openlp.plugins.custom.forms.editcustomdialog) +W: no module named ic (top-level import by webbrowser) +W: no module named com (conditional import by openlp.plugins.presentations.lib.impresscontroller) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.media.mediaplugin) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.forms.editcustomform) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.lib.spelltextedit) +W: no module named openlp.core.lib.html_expands (top-level import by openlp.core.lib.spelltextedit) +W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named sqlalchemy.Column (top-level import by openlp.plugins.songs.lib.db) +W: no module named py2exe (delayed import by enchant.tests) +W: no module named openlp.plugins.songs.forms.AuthorsForm (top-level import by openlp.plugins.songs.forms.songmaintenanceform) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.authorsform) +W: no module named openlp.plugins.remotes.lib.HttpServer (top-level import by openlp.plugins.remotes.remoteplugin) +W: no module named sqlalchemy.Table (top-level import by openlp.plugins.bibles.lib.db) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.remotes.remoteplugin) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.filerenamedialog) +W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named sapdb (delayed import by sqlalchemy.databases.maxdb) +W: no module named ctypes.cdll (delayed import by ctypes.util) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.presentations.lib.presentationtab) +W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named sqlalchemy.sql.text (top-level import by sqlalchemy) +W: no module named openlp.core.lib.image_to_byte (top-level import by openlp.core.lib.renderer) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.forms.importwizardform) +W: no module named openlp.core.lib.image_to_byte (top-level import by openlp.core.ui.maindisplay) +W: no module named iconv_codec (top-level import by BeautifulSoup) +W: no module named openlp.plugins.songs.forms.SongBookForm (top-level import by openlp.plugins.songs.forms.songmaintenanceform) +W: no module named sqlalchemy.sql.not_ (top-level import by sqlalchemy) +W: no module named multiprocessing.Pipe (top-level import by multiprocessing.queues) +W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedetailform) +W: no module named sqlalchemy.sql.subquery (top-level import by sqlalchemy) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.songsplugin) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.editsongdialog) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.bibles.bibleplugin) +W: no module named openlp.plugins.songs.forms.SongMaintenanceForm (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named xmlparse (top-level import by pyexpat) +W: no module named sqlalchemy.sql.exists (top-level import by sqlalchemy) +W: no module named sqlalchemy.sql.and_ (top-level import by openlp.plugins.songs.forms.songmaintenanceform) +W: no module named multiprocessing.Process (top-level import by multiprocessing.pool) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.settingsdialog) +W: no module named sqlalchemy.exceptions (top-level import by openlp.core.lib.db) +W: no module named sqlalchemy.sql.outerjoin (top-level import by sqlalchemy) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.editsongdialog) +W: no module named openlp.plugins.custom.lib.CustomXMLParser (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.custom.forms.editcustomdialog) +W: no module named sqlalchemy.Integer (top-level import by sqlalchemy.databases.sybase) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.properties) +W: no module named multiprocessing.current_process (top-level import by multiprocessing.managers) +W: no module named openlp.core.ui.SplashScreen (top-level import by __main__) +W: no module named multiprocessing.TimeoutError (top-level import by multiprocessing.dummy) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.songs.forms.songimportform) +W: no module named xml.dom.XMLNS_NAMESPACE (top-level import by xml.dom.expatbuilder) +W: no module named ctypes.c_int32 (delayed import by urllib) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.amendthemedialog) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.lib.serviceitem) +W: no module named openlp.core.utils.LanguageManager (top-level import by __main__) +W: no module named sqlalchemy.orm.object_mapper (top-level import by sqlalchemy.orm.properties) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.utils.languagemanager) +W: no module named sqlalchemy.sql.literal_column (top-level import by sqlalchemy) +W: no module named openlp.plugins.songs.lib.SongXMLParser (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named ctypes.c_char_p (delayed import by urllib) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.images.imageplugin) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.remotes.lib.remotetab) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.opensong) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songimportform) +W: no module named sqlalchemy.sql.select (top-level import by sqlalchemy) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songbookdialog) +W: no module named openlp.plugins.bibles.lib.BibleMediaItem (top-level import by openlp.plugins.bibles.bibleplugin) +W: no module named PyQt4._qt (top-level import by PyQt4.QtNetwork) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.songs.songsplugin) +W: no module named sqlalchemy.sql.case (top-level import by sqlalchemy) +W: no module named wx (top-level import by enchant.checker.wxSpellCheckerDialog) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.alerts.alertsplugin) +W: no module named com (conditional import by openlp.plugins.songs.lib.sofimport) +W: no module named PyQt4._qt (top-level import by PyQt4) +W: no module named SOCKS (top-level import by ftplib) +W: no module named openlp.plugins.songusage.forms.SongUsageDetailForm (top-level import by openlp.plugins.songusage.songusageplugin) +W: no module named sqlalchemy.sql.null (top-level import by sqlalchemy) +W: no module named sqlalchemy.MetaData (top-level import by openlp.core.lib.db) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.plugins.custom.forms.EditCustomForm (top-level import by openlp.plugins.custom.customplugin) +W: no module named org (delayed import by xml.sax) +W: no module named openlp.core.lib.SpellTextEdit (top-level import by openlp.plugins.songs.forms.editversedialog) +W: no module named sqlalchemy.orm.EXT_CONTINUE (top-level import by sqlalchemy.orm.scoping) +W: no module named openlp.core.lib.build_lyrics_outline_css (top-level import by openlp.core.lib.renderer) +W: no module named openlp.plugins.songs.lib.VerseType (top-level import by openlp.plugins.songs.forms.editverseform) +W: no module named com (conditional import by openlp.plugins.songs.lib.oooimport) +W: no module named openlp.core.lib.str_to_bool (top-level import by openlp.core.lib.theme) +W: no module named sqlalchemy.sql.literal (top-level import by sqlalchemy) +W: no module named termios (top-level import by getpass) +W: no module named openlp.core.lib.build_lyrics_format_css (top-level import by openlp.core.lib.renderer) +W: no module named ctypes.byref (delayed import by urllib) +W: no module named openlp.plugins.custom.lib.CustomTab (top-level import by openlp.plugins.custom.customplugin) +W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named openlp.plugins.bibles.lib.parse_reference (top-level import by openlp.plugins.bibles.lib.manager) +W: no module named java (delayed import by platform) +W: no module named openlp.core.ui.ServiceItemEditForm (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.customplugin) +W: no module named openlp.core.lib.ThemeLevel (top-level import by openlp.core.lib.rendermanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.db) +W: no module named _xmlrpclib (top-level import by xmlrpclib) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named openlp.plugins.media.lib.MediaMediaItem (top-level import by openlp.plugins.media.mediaplugin) +W: no module named openlp.plugins.custom.lib.CustomXMLBuilder (top-level import by openlp.plugins.custom.forms.editcustomform) +W: no module named rourl2path (conditional import by urllib) +W: no module named pwd (delayed import by webbrowser) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.themestab) +W: no module named PyQt4._qt (top-level import by PyQt4.QtWebKit) +W: no module named sqlalchemy.orm.class_mapper (delayed, conditional import by sqlalchemy.orm.interfaces) +W: no module named PyQt4._qt (top-level import by PyQt4.phonon) +W: no module named openlp.core.ui.HideMode (top-level import by openlp.plugins.presentations.lib.messagelistener) +W: no module named openlp.plugins.songusage.forms.SongUsageDeleteForm (top-level import by openlp.plugins.songusage.songusageplugin) +W: no module named openlp.core.lib.context_menu_separator (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.plugindialog) +W: no module named fcntl (conditional import by subprocess) +W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.bibles.lib.mediaitem) +W: no module named openlp.core.lib.PluginStatus (top-level import by openlp.core.lib.pluginmanager) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.forms.editsongform) +W: no module named openlp.core.ui.ScreenList (top-level import by __main__) +W: no module named sqlalchemy.or_ (top-level import by openlp.plugins.bibles.lib.db) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.editsongform) +W: no module named openlp.plugins.songs.forms.ImportWizardForm (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.ui.ThemeManager (top-level import by openlp.core.ui.mainwindow) +W: no module named pyodbc (delayed, conditional import by sqlalchemy.databases.mssql) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.lib.mediamanageritem) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.biblestab) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.songusageplugin) +W: no module named multiprocessing.active_children (top-level import by multiprocessing.managers) +W: no module named openlp.plugins.songs.forms.EditSongForm (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named email.Generator (delayed import by email.message) +W: no module named mx (delayed import by sqlalchemy.databases.mxODBC) +W: no module named sqlalchemy.sql.or_ (top-level import by sqlalchemy) +W: no module named sqlalchemy.Table (top-level import by openlp.plugins.custom.lib.db) +W: no module named sqlalchemy.Table (top-level import by sqlalchemy.databases.sybase) +W: no module named openlp.core.lib.get_text_file_string (top-level import by openlp.core.ui.thememanager) +W: no module named sqlalchemy.orm.object_session (top-level import by sqlalchemy.orm.scoping) +W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.bibles.lib.mediaitem) +W: no module named sqlalchemy.Table (top-level import by sqlalchemy.databases.mssql) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.forms.bibleimportwizard) +W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.lib.renderer) +W: no module named pymssql (delayed import by sqlalchemy.databases.mssql) +W: no module named sqlalchemy.orm.sessionmaker (top-level import by openlp.plugins.songs.lib.olpimport) +W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.expand_tags (top-level import by openlp.core.lib.serviceitem) +W: no module named gestalt (delayed import by platform) +W: no module named enchant.checker.SpellChecker (top-level import by enchant.checker.CmdLineChecker) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.themestab) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.olp1import) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.messagelistener) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.interfaces) +W: no module named sqlalchemy.orm.object_mapper (top-level import by sqlalchemy.orm.query) +W: no module named sqlalchemy.sql.distinct (top-level import by sqlalchemy) +W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named sqlalchemy.sql.extract (top-level import by sqlalchemy) +W: no module named sqlalchemy.Column (top-level import by openlp.plugins.bibles.lib.db) +W: no module named psycopg2 (delayed import by sqlalchemy.databases.postgres) +W: no module named enchant.checker.SpellChecker (delayed import by enchant.checker.GtkSpellCheckerDialog) +W: no module named clr (conditional import by adodbapi.adodbapi) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named openlp.plugins.custom.lib.CustomXMLParser (top-level import by openlp.plugins.custom.forms.editcustomform) +W: no module named openlp.core.theme.Theme (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.custom.forms.editcustomform) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.core.lib.settingsmanager) +W: no module named openlp.core.lib.Receiver (top-level import by __main__) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.bibles.lib.manager) +W: no module named org (top-level import by pickle) +W: no module named enchant.DictNotFoundError (top-level import by openlp.core.lib.spelltextedit) +W: no module named sqlalchemy.sql.except_all (top-level import by sqlalchemy) +W: no module named openlp.plugins.presentations.lib.PresentationTab (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named sqlalchemy.sql.cast (top-level import by sqlalchemy) +W: no module named sqlalchemy.orm.relation (top-level import by openlp.plugins.songs.lib.db) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.settingsdialog) +W: no module named openlp.core.utils.LanguageManager (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named sqlalchemy.sql.intersect (top-level import by sqlalchemy) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.songimport) +W: no module named sqlalchemy.orm.class_mapper (top-level import by sqlalchemy.orm.scoping) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.util) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.opensongimport) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.bibles.lib.biblestab) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.aboutform) +W: no module named openlp.plugins.custom.lib.CustomMediaItem (top-level import by openlp.plugins.custom.customplugin) +W: no module named sqlalchemy.orm.scoped_session (top-level import by openlp.plugins.songs.lib.olpimport) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.amendthemeform) +W: no module named sqlalchemy.engine.engine_from_config (top-level import by sqlalchemy) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.core.ui.themestab) +W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.maindisplay) +W: no module named openlp.core.lib.PluginStatus (top-level import by openlp.core.ui.pluginform) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.http) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.remotes.lib.httpserver) +W: no module named sqlalchemy.Table (top-level import by openlp.plugins.songs.lib.db) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.utils) +W: no module named openlp.core.lib.RenderManager (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.alerts.alertsplugin) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.lib.plugin) +W: no module named sqlalchemy.ForeignKey (top-level import by openlp.plugins.bibles.lib.db) +W: no module named openlp.plugins.songs.lib.SongMediaItem (top-level import by openlp.plugins.songs.songsplugin) +W: no module named sqlalchemy.Index (top-level import by openlp.plugins.songs.lib.db) +W: no module named multiprocessing.TimeoutError (top-level import by multiprocessing.pool) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songusage.forms.songusagedetaildialog) +W: no module named enchant.DictWithPWL (delayed import by enchant.checker.tests) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.songstab) +W: no module named openlp.core.ui.AdvancedTab (top-level import by openlp.core.ui.settingsform) +W: no module named MySQLdb (delayed import by sqlalchemy.databases.mysql) +W: no module named openlp.plugins.presentations.lib.PresentationMediaItem (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named openlp.plugins.alerts.forms.AlertForm (top-level import by openlp.plugins.alerts.alertsplugin) +W: no module named ctypes.c_int (delayed import by urllib) +W: no module named xml.dom.XML_NAMESPACE (delayed import by xml.dom.pulldom) +W: no module named ctypes.c_void_p (delayed import by urllib) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.lib.osis) +W: no module named sqlalchemy.create_engine (top-level import by openlp.core.lib.db) +W: no module named win32com.client._get_good_object_ (top-level import by win32com.client.util) +W: no module named openlp.core.ui.MainDisplay (top-level import by openlp.core.ui.slidecontroller) +W: no module named openlp.core.lib.resize_image (top-level import by openlp.plugins.presentations.lib.presentationcontroller) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.remotes.lib.remotetab) +W: no module named openlp.core.ui.MediaDockManager (top-level import by openlp.core.ui.mainwindow) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.session) +W: no module named sqlalchemy.Column (top-level import by sqlalchemy.databases.mssql) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.editversedialog) +W: no module named multiprocessing.Process (top-level import by multiprocessing.managers) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.presentationcontroller) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.custom.forms.editcustomdialog) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.lib.alertsmanager) +W: no module named sgmlop (top-level import by xmlrpclib) +W: no module named MacOS (conditional import by py_compile) +W: no module named multiprocessing.cpu_count (top-level import by multiprocessing.dummy) +W: no module named _dummy_threading (top-level import by dummy_threading) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songmaintenanceform) +W: no module named openlp.plugins.presentations.lib.PresentationController (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.lib.mediamanageritem) +W: no module named sqlalchemy.sql.union_all (top-level import by sqlalchemy) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.opensong) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.plugins.bibles.lib.mediaitem) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.osis) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.settingsform) +W: no module named enchant.tokenize.get_tokenizer (top-level import by enchant.checker) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.bibles.lib.manager) +W: no module named org (top-level import by copy) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.core.ui.servicemanager) +W: no module named sqlalchemy.MetaData (top-level import by openlp.plugins.songs.lib.olpimport) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.songmaintenancedialog) +W: no module named sqlalchemy.sql.select (top-level import by sqlalchemy.databases.mssql) +W: no module named openlp.core.lib.SettingsManager (top-level import by openlp.plugins.bibles.forms.importwizardform) +W: no module named multiprocessing.current_process (top-level import by multiprocessing.connection) +W: no module named sqlalchemy.orm.sessionmaker (top-level import by openlp.core.lib.db) +W: no module named sqlalchemy.sql.desc (top-level import by sqlalchemy) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songusage.forms.songusagedeletedialog) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.mediaitem) +W: no module named ctypes.cdll (delayed import by urllib) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.lib) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.media.mediaplugin) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.presentations.lib.presentationtab) +W: no module named MySQLdb (delayed, conditional import by sqlalchemy.databases.mysql) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named openlp.core.lib.MediaManagerItem (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named sqlalchemy.orm.object_session (top-level import by sqlalchemy.orm.dynamic) +W: no module named sqlalchemy.sql.modifier (top-level import by sqlalchemy) +W: no module named _xmlplus (top-level import by xml) +W: no module named sqlalchemy.Column (top-level import by openlp.plugins.songusage.lib.db) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.advancedtab) +W: no module named sqlalchemy.sql.and_ (top-level import by sqlalchemy) +W: no module named sqlalchemy.MetaData (top-level import by sqlalchemy.databases.mssql) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.dependency) +W: no module named openlp.core.lib.ThemeLevel (top-level import by openlp.core.ui.themestab) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.presentations.lib.presentationtab) +W: no module named openlp.core.utils.get_images_filter (top-level import by openlp.core.ui.amendthemeform) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.presentations.presentationplugin) +W: no module named openlp.plugins.presentations.lib.MessageListener (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named openlp.plugins.bibles.forms.ImportWizardForm (top-level import by openlp.plugins.bibles.lib.mediaitem) +W: no module named openlp.core.utils.AppLocation (top-level import by __main__) +W: no module named sqlalchemy.ForeignKey (top-level import by openlp.plugins.songs.lib.db) +W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.ui.thememanager) +W: no module named ctypes.cdll (conditional import by openlp.plugins.presentations.lib.pptviewcontroller) +W: no module named pwd (delayed import by getpass) +W: no module named sqlalchemy.sql.and_ (top-level import by openlp.plugins.songusage.forms.songusagedetailform) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.amendthemedialog) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.plugins.songs.forms.songimportwizard) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.serviceitemeditdialog) +W: no module named openlp.core.lib.resize_image (top-level import by openlp.core.ui.maindisplay) +W: no module named openlp.core.lib.BaseListWithDnD (top-level import by openlp.plugins.custom.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.topicsdialog) +W: no module named PyQt4._qt (top-level import by PyQt4.QtGui) +W: no module named sqlalchemy.sql.update (top-level import by sqlalchemy) +W: no module named multiprocessing.current_process (delayed, conditional import by logging) +W: no module named multiprocessing.Pool (top-level import by multiprocessing.managers) +W: no module named sqlalchemy.create_engine (delayed, conditional import by sqlalchemy.schema) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.forms.importwizardform) +W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.lib.mediamanageritem) +W: no module named posix (conditional import by os) +W: no module named sqlalchemy.sql.bindparam (top-level import by sqlalchemy) +W: no module named xml.dom.DOMImplementation (top-level import by xml.dom.domreg) +W: no module named openlp.core.utils.add_actions (top-level import by openlp.core.ui.mainwindow) +W: no module named sqlalchemy.create_engine (top-level import by openlp.plugins.songs.lib.olpimport) +W: no module named multiprocessing.cpu_count (top-level import by multiprocessing.pool) +W: no module named multiprocessing.AuthenticationError (top-level import by multiprocessing.connection) +W: no module named openlp.core.ui.ThemesTab (top-level import by openlp.core.ui.settingsform) +W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.media.lib.mediaitem) +W: no module named sqlalchemy.orm.class_mapper (top-level import by openlp.plugins.bibles.lib.db) +W: no module named sqlalchemy.String (top-level import by sqlalchemy.databases.sybase) +W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named pwd (delayed, conditional import by posixpath) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.strategies) +W: no module named mx (top-level import by adodbapi.adodbapi) +W: no module named sqlalchemy.sql.alias (top-level import by sqlalchemy) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.authorsdialog) +W: no module named sqlalchemy.Table (top-level import by openlp.plugins.alerts.lib.db) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.bibles.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.images.imageplugin) +W: no module named sqlalchemy.orm.mapperlib (delayed import by sqlalchemy.orm.util) +W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.lib.rendermanager) +W: no module named openlp.core.lib.OpenLPDockWidget (top-level import by openlp.core.ui.mainwindow) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.songs.forms.songimportwizard) +W: no module named openlp.core.lib.Plugin (top-level import by openlp.plugins.songusage.songusageplugin) +W: no module named openlp.core.utils.AppLocation (top-level import by openlp.plugins.presentations.lib.presentationcontroller) +W: no module named openlp.core.lib.context_menu_action (top-level import by openlp.core.lib.spelltextedit) +W: no module named openlp.core.lib.build_icon (top-level import by openlp.core.ui.thememanager) +W: no module named openlp.core.lib.check_item_selected (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.pluginform) +W: no module named enchant.checker.SpellChecker (delayed import by enchant.checker.wxSpellCheckerDialog) +W: no module named sqlalchemy.DefaultClause (top-level import by sqlalchemy.databases.sqlite) +W: no module named openlp.core.lib.ServiceItem (top-level import by openlp.core.ui.servicemanager) +W: no module named openlp.core.lib.ItemCapabilities (top-level import by openlp.core.ui.slidecontroller) +W: no module named openlp.core.utils.get_images_filter (top-level import by openlp.plugins.images.lib.mediaitem) +W: no module named pyodbc (delayed import by sqlalchemy.databases.mssql) +W: no module named openlp.core.lib.OpenLPToolbar (top-level import by openlp.core.ui.slidecontroller) +W: no module named System (conditional import by adodbapi.adodbapi) +W: no module named openlp.core.lib.SettingsTab (top-level import by openlp.plugins.custom.lib.customtab) +W: no module named openlp.core.lib.Receiver (top-level import by openlp.plugins.bibles.lib.csvbible) +W: no module named openlp.core.lib.translate (top-level import by openlp.core.ui.generaltab) +W: no module named openlp.core.lib.ThemeLevel (top-level import by openlp.core.ui.servicemanager) +W: no module named sqlalchemy.exceptions (top-level import by sqlalchemy.orm.scoping) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.alerts.forms.alertform) +W: no module named mypyodbc (delayed import by sqlalchemy.databases.sybase) +W: no module named sqlalchemy.sql.intersect_all (top-level import by sqlalchemy) +W: no module named openlp.core.lib.translate (top-level import by openlp.plugins.presentations.lib.mediaitem) +W: __all__ is built strangely at line 0 - dummy_threading (C:\Python26\lib\dummy_threading.pyc) +W: delayed exec statement detected at line 0 - bdb (C:\Python26\lib\bdb.pyc) +W: delayed eval hack detected at line 0 - bdb (C:\Python26\lib\bdb.pyc) +W: delayed eval hack detected at line 0 - bdb (C:\Python26\lib\bdb.pyc) +W: delayed __import__ hack detected at line 0 - optparse (C:\Python26\lib\optparse.pyc) +W: delayed conditional __import__ hack detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc) +W: delayed conditional exec statement detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc) +W: delayed conditional __import__ hack detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc) +W: delayed __import__ hack detected at line 0 - pkg_resources (build/bdist.linux-i686/egg/pkg_resources.pyc) +W: delayed conditional __import__ hack detected at line 0 - doctest (C:\Python26\lib\doctest.pyc) +W: delayed exec statement detected at line 0 - doctest (C:\Python26\lib\doctest.pyc) +W: delayed conditional __import__ hack detected at line 0 - doctest (C:\Python26\lib\doctest.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.orm.interfaces (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\interfaces.pyc) +W: __all__ is built strangely at line 0 - tokenize (C:\Python26\lib\tokenize.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.engine (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\engine\__init__.pyc) +W: delayed __import__ hack detected at line 0 - pickle (C:\Python26\lib\pickle.pyc) +W: delayed __import__ hack detected at line 0 - pickle (C:\Python26\lib\pickle.pyc) +W: top-level conditional exec statement detected at line 0 - sqlalchemy.sql.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\sql\util.pyc) +W: top-level conditional exec statement detected at line 0 - sqlalchemy.sql.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\sql\util.pyc) +W: delayed conditional __import__ hack detected at line 0 - openlp.core.lib.pluginmanager (c:\Documents and Settings\raoul\My Documents\My Projects\openlp\movements\openlp\core\lib\pluginmanager.pyc) +W: delayed conditional exec statement detected at line 0 - multiprocessing.sharedctypes (C:\Python26\lib\multiprocessing\sharedctypes.pyc) +W: delayed __import__ hack detected at line 0 - encodings (C:\Python26\lib\encodings\__init__.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.databases.mysql (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\databases\mysql.pyc) +W: delayed exec statement detected at line 0 - sqlalchemy.orm.attributes (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\attributes.pyc) +W: delayed conditional __import__ hack detected at line 0 - openlp.plugins.presentations.presentationplugin (c:\Documents and Settings\raoul\My Documents\My Projects\openlp\movements\openlp\plugins\presentations\presentationplugin.pyc) +W: delayed __import__ hack detected at line 0 - enchant.tokenize (C:\Python26\lib\site-packages\enchant\tokenize\__init__.pyc) +W: __all__ is built strangely at line 0 - multiprocessing (C:\Python26\lib\multiprocessing\__init__.pyc) +W: __all__ is built strangely at line 0 - dis (C:\Python26\lib\dis.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.databases (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\databases\__init__.pyc) +W: delayed __import__ hack detected at line 0 - win32com.server.policy (C:\Python26\lib\site-packages\win32com\server\policy.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.orm.mapper (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\mapper.pyc) +W: top-level exec statement detected at line 0 - hashlib (C:\Python26\lib\hashlib.pyc) +W: top-level conditional exec statement detected at line 0 - hashlib (C:\Python26\lib\hashlib.pyc) +W: delayed conditional eval hack detected at line 0 - warnings (C:\Python26\lib\warnings.pyc) +W: delayed conditional __import__ hack detected at line 0 - warnings (C:\Python26\lib\warnings.pyc) +W: delayed exec statement detected at line 0 - cgi (C:\Python26\lib\cgi.pyc) +W: delayed __import__ hack detected at line 0 - email (C:\Python26\lib\email\__init__.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.orm (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\__init__.pyc) +W: delayed __import__ hack detected at line 0 - ctypes (C:\Python26\lib\ctypes\__init__.pyc) +W: delayed __import__ hack detected at line 0 - ctypes (C:\Python26\lib\ctypes\__init__.pyc) +W: delayed conditional __import__ hack detected at line 0 - xml.dom.domreg (C:\Python26\lib\xml\dom\domreg.pyc) +W: delayed exec statement detected at line 0 - pdb (C:\Python26\lib\pdb.pyc) +W: delayed conditional eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc) +W: delayed eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc) +W: delayed conditional eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc) +W: delayed eval hack detected at line 0 - pdb (C:\Python26\lib\pdb.pyc) +W: delayed conditional __import__ hack detected at line 0 - unittest (C:\Python26\lib\unittest.pyc) +W: delayed conditional __import__ hack detected at line 0 - unittest (C:\Python26\lib\unittest.pyc) +W: delayed conditional __import__ hack detected at line 0 - pkgutil (C:\Python26\lib\pkgutil.pyc) +W: delayed conditional __import__ hack detected at line 0 - pkgutil (C:\Python26\lib\pkgutil.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.orm.properties (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\orm\properties.pyc) +W: delayed conditional exec statement detected at line 0 - iu (c:\Documents and Settings\raoul\My Documents\My Projects\pyinstaller\iu.pyc) +W: delayed conditional exec statement detected at line 0 - iu (c:\Documents and Settings\raoul\My Documents\My Projects\pyinstaller\iu.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy.sql (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\sql\__init__.pyc) +W: __all__ is built strangely at line 0 - collections (C:\Python26\lib\collections.pyc) +W: delayed exec statement detected at line 0 - collections (C:\Python26\lib\collections.pyc) +W: delayed __import__ hack detected at line 0 - sqlalchemy.engine.url (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\engine\url.pyc) +W: delayed exec statement detected at line 0 - multiprocessing.managers (C:\Python26\lib\multiprocessing\managers.pyc) +W: delayed exec statement detected at line 0 - socket (C:\Python26\lib\socket.pyc) +W: delayed conditional __import__ hack detected at line 0 - win32com.client.gencache (C:\Python26\lib\site-packages\win32com\client\gencache.pyc) +W: delayed __import__ hack detected at line 0 - win32com.client.gencache (C:\Python26\lib\site-packages\win32com\client\gencache.pyc) +W: delayed eval hack detected at line 0 - os (C:\Python26\lib\os.pyc) +W: __all__ is built strangely at line 0 - __future__ (C:\Python26\lib\__future__.pyc) +W: delayed __import__ hack detected at line 0 - win32com.client.makepy (C:\Python26\lib\site-packages\win32com\client\makepy.pyc) +W: delayed exec statement detected at line 0 - win32com.client.dynamic (C:\Python26\lib\site-packages\win32com\client\dynamic.pyc) +W: __all__ is built strangely at line 0 - sqlalchemy (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\__init__.pyc) +W: delayed __import__ hack detected at line 0 - xml.sax (C:\Python26\lib\xml\sax\__init__.pyc) +W: delayed eval hack detected at line 0 - gettext (C:\Python26\lib\gettext.pyc) +W: delayed eval hack detected at line 0 - sqlalchemy.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\util.pyc) +W: delayed exec statement detected at line 0 - sqlalchemy.util (C:\Python26\lib\site-packages\sqlalchemy-0.5.8-py2.6.egg\sqlalchemy\util.pyc) diff --git a/scripts/translation_utils.py b/scripts/translation_utils.py index 424e977bd..495732085 100755 --- a/scripts/translation_utils.py +++ b/scripts/translation_utils.py @@ -63,6 +63,7 @@ IGNORED_PATHS = [u'scripts'] IGNORED_FILES = [u'setup.py'] verbose_mode = False +quiet_mode = False class Command(object): """ @@ -128,6 +129,20 @@ class CommandStack(object): results.append(str((item[u'command'], ))) return u'[%s]' % u', '.join(results) +def print_quiet(text, linefeed=True): + """ + This method checks to see if we are in quiet mode, and if not prints + ``text`` out. + + ``text`` + The text to print. + """ + global quiet_mode + if not quiet_mode: + if linefeed: + print text + else: + print text, def print_verbose(text): """ @@ -137,8 +152,8 @@ def print_verbose(text): ``text`` The text to print. """ - global verbose_mode - if verbose_mode: + global verbose_mode, quiet_mode + if not quiet_mode and verbose_mode: print u' %s' % text def run(command): @@ -155,7 +170,6 @@ def run(command): print_verbose(u'ReadyRead: %s' % QtCore.QString(process.readAll())) print_verbose(u'Error(s):\n%s' % process.readAllStandardError()) print_verbose(u'Output:\n%s' % process.readAllStandardOutput()) - print u' Done.' def update_export_at_pootle(source_filename): """ @@ -170,7 +184,7 @@ def update_export_at_pootle(source_filename): print_verbose(u'Accessing: %s' % (REVIEW_URL)) page = urllib.urlopen(REVIEW_URL) page.close() - + def download_file(source_filename, dest_filename): """ @@ -194,7 +208,7 @@ def download_translations(): """ This method downloads the translation files from the Pootle server. """ - print 'Download translation files from Pootle' + print_quiet(u'Download translation files from Pootle') page = urllib.urlopen(SERVER_URL) soup = BeautifulSoup(page) languages = soup.findAll(text=re.compile(r'.*\.ts')) @@ -205,14 +219,14 @@ def download_translations(): language_file) print_verbose(u'Get Translation File: %s' % filename) download_file(language_file, filename) - print u' Done.' + print_quiet(u' Done.') def prepare_project(): """ This method creates the project file needed to update the translation files and compile them into .qm files. """ - print u'Generating the openlp.pro file' + print_quiet(u'Generating the openlp.pro file') lines = [] start_dir = os.path.abspath(u'..') start_dir = start_dir + os.sep @@ -251,10 +265,10 @@ def prepare_project(): file = open(os.path.join(start_dir, u'openlp.pro'), u'w') file.write(u'\n'.join(lines).encode('utf8')) file.close() - print u' Done.' + print_quiet(u' Done.') def update_translations(): - print u'Update the translation files' + print_quiet(u'Update the translation files') if not os.path.exists(os.path.join(os.path.abspath(u'..'), u'openlp.pro')): print u'You have no generated a project file yet, please run this ' + \ u'script with the -p option.' @@ -265,7 +279,7 @@ def update_translations(): os.chdir(os.path.abspath(u'scripts')) def generate_binaries(): - print u'Generate the related *.qm files' + print_quiet(u'Generate the related *.qm files') if not os.path.exists(os.path.join(os.path.abspath(u'..'), u'openlp.pro')): print u'You have not generated a project file yet, please run this ' + \ u'script with the -p option. It is also recommended that you ' + \ @@ -283,8 +297,9 @@ def generate_binaries(): src_list = os.listdir(src_path) for file in src_list: if re.search('.qm$', file): - copy(os.path.join(src_path, u'%s' % file), + copy(os.path.join(src_path, u'%s' % file), os.path.join(dest_path, u'%s' % file)) + print_quiet(u' Done.') def create_translation(language): @@ -294,17 +309,17 @@ def create_translation(language): ``language`` The language file to create. """ - print "Create new Translation File" + print_quiet(u'Create new Translation File') if not language.endswith(u'.ts'): language += u'.ts' filename = os.path.join(os.path.abspath(u'..'), u'resources', u'i18n', language) download_file(u'en.ts', filename) - print u' ** Please Note **' - print u' In order to get this file into OpenLP and onto the Pootle ' + \ - u'translation server you will need to subscribe to the OpenLP' + \ - u'Translators mailing list, and request that your language file ' + \ - u'be added to the project.' - print u' Done' + print_quiet(u' ** Please Note **') + print_quiet(u' In order to get this file into OpenLP and onto the ' + u'Pootle translation server you will need to subscribe to the ' + u'OpenLP Translators mailing list, and request that your language ' + u'file be added to the project.') + print_quiet(u' Done.') def process_stack(command_stack): """ @@ -315,9 +330,9 @@ def process_stack(command_stack): The command stack to process. """ if command_stack: - print u'Processing %d commands...' % len(command_stack) + print_quiet(u'Processing %d commands...' % len(command_stack)) for command in command_stack: - print u'%d.' % (command_stack.current_index), + print_quiet(u'%d.' % (command_stack.current_index), False) if command == Command.Download: download_translations() elif command == Command.Prepare: @@ -329,12 +344,12 @@ def process_stack(command_stack): elif command == Command.Create: arguments = command_stack.arguments() create_translation(*arguments) - print u'Finished processing commands.' + print_quiet(u'Finished processing commands.') else: - print u'No commands to process.' + print_quiet(u'No commands to process.') def main(): - global verbose_mode + global verbose_mode, quiet_mode # Set up command line options. usage = u'%prog [options]\nOptions are parsed in the order they are ' + \ u'listed below. If no options are given, "-dpug" will be used.\n\n' + \ @@ -352,6 +367,8 @@ def main(): help='compile .ts files into .qm files') parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='show extra information while processing translations') + parser.add_option('-q', '--quiet', dest='quiet', action='store_true', + help='suppress all output other than errors') (options, args) = parser.parse_args() # Create and populate the command stack command_stack = CommandStack() @@ -366,6 +383,7 @@ def main(): if options.generate: command_stack.append(Command.Generate) verbose_mode = options.verbose + quiet_mode = options.quiet if not command_stack: command_stack.append(Command.Download) command_stack.append(Command.Prepare) diff --git a/scripts/windows-builder.py b/scripts/windows-builder.py index d34b77249..1900fab99 100644 --- a/scripts/windows-builder.py +++ b/scripts/windows-builder.py @@ -87,20 +87,33 @@ windows-builder.py """ import os +import sys from shutil import copy from subprocess import Popen, PIPE +python_exe = sys.executable +innosetup_exe = os.path.join(os.getenv(u'PROGRAMFILES'), 'Inno Setup 5', + u'ISCC.exe') + +# Base paths script_path = os.path.split(os.path.abspath(__file__))[0] branch_path = os.path.abspath(os.path.join(script_path, u'..')) +site_packages = os.path.join(os.path.split(python_exe)[0], u'Lib', + u'site-packages') + +# Files and executables +pyi_build = os.path.abspath(os.path.join(branch_path, u'..', u'..', + u'pyinstaller', u'Build.py')) +lrelease_exe = os.path.join(site_packages, u'PyQt4', u'bin', u'lrelease.exe') +i18n_utils = os.path.join(script_path, u'translation_utils.py') + +# Paths source_path = os.path.join(branch_path, u'openlp') i18n_path = os.path.join(branch_path, u'resources', u'i18n') +winres_path = os.path.join(branch_path, u'resources', u'windows') build_path = os.path.join(branch_path, u'build', u'pyi.win32', u'OpenLP') dist_path = os.path.join(branch_path, u'dist', u'OpenLP') -pyinstaller_path = os.path.abspath(os.path.join(branch_path, u'..', u'..', u'pyinstaller')) -innosetup_path = os.path.join(os.getenv(u'PROGRAMFILES'), 'Inno Setup 5') -iss_path = os.path.join(branch_path, u'resources', u'innosetup') -lrelease_path = u'C:\\Python26\\Lib\\site-packages\\PyQt4\\bin\\lrelease.exe' -enchant_path = u'C:\\Python26\\Lib\\site-packages\\enchant' +enchant_path = os.path.join(site_packages, u'enchant') def clean_build_directories(): #if not os.path.exists(build_path) @@ -117,11 +130,13 @@ def clean_build_directories(): def run_pyinstaller(): print u'Running PyInstaller...' os.chdir(branch_path) - pyinstaller = Popen((u'python', os.path.join(pyinstaller_path, u'Build.py'), - u'-y', u'OpenLP.spec')) + pyinstaller = Popen((python_exe, pyi_build, u'-y', u'-o', build_path, + os.path.join(winres_path, u'OpenLP.spec')), stdout=PIPE) + output, error = pyinstaller.communicate() code = pyinstaller.wait() if code != 0: - raise Exception(u'Error running PyInstaller Build.py') + print output + raise Exception(u'Error running PyInstaller') def write_version_file(): print u'Writing version file...' @@ -155,7 +170,7 @@ def copy_enchant(): for root, dirs, files in os.walk(source): for filename in files: if not filename.endswith(u'.pyc') and not filename.endswith(u'.pyo'): - dest_path = os.path.join(dest, root[len(source)+1:]) + dest_path = os.path.join(dest, root[len(source) + 1:]) if not os.path.exists(dest_path): os.makedirs(dest_path) copy(os.path.join(root, filename), @@ -176,16 +191,18 @@ def copy_plugins(): def copy_windows_files(): print u'Copying extra files for Windows...' - copy(os.path.join(iss_path, u'OpenLP.ico'), os.path.join(dist_path, u'OpenLP.ico')) - copy(os.path.join(iss_path, u'LICENSE.txt'), os.path.join(dist_path, u'LICENSE.txt')) + copy(os.path.join(winres_path, u'OpenLP.ico'), + os.path.join(dist_path, u'OpenLP.ico')) + copy(os.path.join(winres_path, u'LICENSE.txt'), + os.path.join(dist_path, u'LICENSE.txt')) def update_translations(): print u'Updating translations...' os.chdir(script_path) - translation_utils = Popen(u'python translation_utils.py -dpu') + translation_utils = Popen((python_exe, i18n_utils, u'-qdpu')) code = translation_utils.wait() if code != 0: - print u'Error running translation_utils.py' + raise Exception(u'Error running translation_utils.py') def compile_translations(): print u'Compiling translations...' @@ -197,19 +214,17 @@ def compile_translations(): source_path = os.path.join(i18n_path, file) dest_path = os.path.join(dist_path, u'i18n', file.replace(u'.ts', u'.qm')) - lconvert = Popen(u'"%s" "%s" -qm "%s"' % (lrelease_path, \ - source_path, dest_path)) + lconvert = Popen((lrelease_exe, u'-compress', u'-silent', + source_path, u'-qm', dest_path)) code = lconvert.wait() if code != 0: - print 'Error running lconvert on %s' % source_path + raise Exception('Error running lconvert on %s' % source_path) def run_innosetup(): print u'Running Inno Setup...' - os.chdir(iss_path) - run_command = u'"%s" "%s"' % (os.path.join(innosetup_path, u'ISCC.exe'), - os.path.join(iss_path, u'OpenLP-2.0.iss')) - print run_command - innosetup = Popen(run_command) + os.chdir(winres_path) + innosetup = Popen((innosetup_exe, + os.path.join(winres_path, u'OpenLP-2.0.iss'), u'/q')) code = innosetup.wait() if code != 0: raise Exception(u'Error running Inno Setup') @@ -221,9 +236,9 @@ def main(): print "Branch path:", branch_path print "Source path:", source_path print "\"dist\" path:", dist_path - print "PyInstaller path:", pyinstaller_path + print "PyInstaller:", pyi_build print "Inno Setup path:", innosetup_path - print "ISS file path:", iss_path + print "Windows resources:", winres_path #clean_build_directories() run_pyinstaller() write_version_file()