def _create_report(self): """ Create an exception report. """ openlp_version = get_application_version() description = self.description_text_edit.toPlainText() traceback = self.exception_text_edit.toPlainText() system = translate('OpenLP.ExceptionForm', 'Platform: %s\n') % platform.platform() libraries = 'Python: %s\n' % platform.python_version() + \ 'Qt4: %s\n' % Qt.qVersion() + \ 'Phonon: %s\n' % PHONON_VERSION + \ 'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \ 'QtWebkit: %s\n' % WEBKIT_VERSION + \ 'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \ 'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \ 'BeautifulSoup: %s\n' % bs4.__version__ + \ 'lxml: %s\n' % etree.__version__ + \ 'Chardet: %s\n' % CHARDET_VERSION + \ 'PyEnchant: %s\n' % ENCHANT_VERSION + \ 'Mako: %s\n' % MAKO_VERSION + \ 'pyICU: %s\n' % ICU_VERSION + \ 'pyUNO bridge: %s\n' % self._pyuno_import() + \ 'VLC: %s\n' % VLC_VERSION if is_linux(): if os.environ.get('KDE_FULL_SESSION') == 'true': system += 'Desktop: KDE SC\n' elif os.environ.get('GNOME_DESKTOP_SESSION_ID'): system += 'Desktop: GNOME\n' elif os.environ.get('DESKTOP_SESSION') == 'xfce': system += 'Desktop: Xfce\n' return openlp_version, description, traceback, system, libraries
def backup_on_upgrade(self, has_run_wizard): """ Check if OpenLP has been upgraded, and ask if a backup of data should be made :param has_run_wizard: OpenLP has been run before """ data_version = Settings().value('core/application version') openlp_version = get_application_version()['version'] # New installation, no need to create backup if not has_run_wizard: Settings().setValue('core/application version', openlp_version) # If data_version is different from the current version ask if we should backup the data folder elif data_version != openlp_version: if QtGui.QMessageBox.question(None, translate('OpenLP', 'Backup'), translate('OpenLP', 'OpenLP has been upgraded, ' 'do you want to create a backup of OpenLPs data folder?'), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.Yes) == QtGui.QMessageBox.Yes: # Create copy of data folder data_folder_path = AppLocation.get_data_path() timestamp = time.strftime("%Y%m%d-%H%M%S") data_folder_backup_path = data_folder_path + '-' + timestamp try: shutil.copytree(data_folder_path, data_folder_backup_path) except OSError: QtGui.QMessageBox.warning(None, translate('OpenLP', 'Backup'), translate('OpenLP', 'Backup of the data folder failed!')) return QtGui.QMessageBox.information(None, translate('OpenLP', 'Backup'), translate('OpenLP', 'A backup of the data folder has been created at %s') % data_folder_backup_path) # Update the version in the settings Settings().setValue('core/application version', openlp_version)
def _createReport(self): """ Create an exception report. """ openlp_version = get_application_version() description = self.descriptionTextEdit.toPlainText() traceback = self.exceptionTextEdit.toPlainText() system = translate('OpenLP.ExceptionForm', 'Platform: %s\n') % platform.platform() libraries = u'Python: %s\n' % platform.python_version() + \ u'Qt4: %s\n' % Qt.qVersion() + \ u'Phonon: %s\n' % PHONON_VERSION + \ u'PyQt4: %s\n' % Qt.PYQT_VERSION_STR + \ u'QtWebkit: %s\n' % WEBKIT_VERSION + \ u'SQLAlchemy: %s\n' % sqlalchemy.__version__ + \ u'SQLAlchemy Migrate: %s\n' % MIGRATE_VERSION + \ u'BeautifulSoup: %s\n' % BeautifulSoup.__version__ + \ u'lxml: %s\n' % etree.__version__ + \ u'Chardet: %s\n' % CHARDET_VERSION + \ u'PyEnchant: %s\n' % ENCHANT_VERSION + \ u'PySQLite: %s\n' % SQLITE_VERSION + \ u'Mako: %s\n' % MAKO_VERSION + \ u'pyUNO bridge: %s\n' % UNO_VERSION if platform.system() == u'Linux': if os.environ.get(u'KDE_FULL_SESSION') == u'true': system += u'Desktop: KDE SC\n' elif os.environ.get(u'GNOME_DESKTOP_SESSION_ID'): system += u'Desktop: GNOME\n' return (openlp_version, description, traceback, system, libraries)
def __init__(self, name, default_settings, media_item_class=None, settings_tab_class=None, version=None): """ This is the constructor for the plugin object. This provides an easy way for descendent plugins to populate common data. This method *must* be overridden, like so:: class MyPlugin(Plugin): def __init__(self): Plugin.__init__(self, u'MyPlugin', version=u'0.1') ``name`` Defaults to *None*. The name of the plugin. ``default_settings`` A dict containing the plugin's settings. The value to each key is the default value to be used. ``media_item_class`` The class name of the plugin's media item. ``settings_tab_class`` The class name of the plugin's settings tab. ``version`` Defaults to *None*, which means that the same version number is used as OpenLP's version number. """ log.debug(u'Plugin %s initialised' % name) QtCore.QObject.__init__(self) self.name = name self.textStrings = {} self.setPluginTextStrings() self.nameStrings = self.textStrings[StringContent.Name] if version: self.version = version else: self.version = get_application_version()[u'version'] self.settingsSection = self.name self.icon = None self.mediaItemClass = media_item_class self.settingsTabClass = settings_tab_class self.settingsTab = None self.mediaItem = None self.weight = 0 self.status = PluginStatus.Inactive # Add the default status to the default settings. default_settings[name + u'/status'] = PluginStatus.Inactive default_settings[name + u'/last directory'] = u'' # Append a setting for files in the mediamanager (note not all plugins # which have a mediamanager need this). if media_item_class is not None: default_settings[u'%s/%s files' % (name, name)] = [] # Add settings to the dict of all settings. Settings.extend_default_settings(default_settings) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_add_service_item' % self.name), self.processAddServiceEvent) QtCore.QObject.connect(Receiver.get_receiver(), QtCore.SIGNAL(u'%s_config_updated' % self.name), self.configUpdated)
def __init__(self, name, default_settings, media_item_class=None, settings_tab_class=None, version=None): """ This is the constructor for the plugin object. This provides an easy way for descendant plugins to populate common data. This method *must* be overridden, like so:: class MyPlugin(Plugin): def __init__(self): super(MyPlugin, self).__init__('MyPlugin', version='0.1') :param name: Defaults to *None*. The name of the plugin. :param default_settings: A dict containing the plugin's settings. The value to each key is the default value to be used. :param media_item_class: The class name of the plugin's media item. :param settings_tab_class: The class name of the plugin's settings tab. :param version: Defaults to *None*, which means that the same version number is used as OpenLP's version number. """ log.debug('Plugin %s initialised' % name) super(Plugin, self).__init__() self.name = name self.text_strings = {} self.set_plugin_text_strings() self.name_strings = self.text_strings[StringContent.Name] if version: self.version = version else: self.version = get_application_version()['version'] self.settings_section = self.name self.icon = None self.media_item_class = media_item_class self.settings_tab_class = settings_tab_class self.settings_tab = None self.media_item = None self.weight = 0 self.status = PluginStatus.Inactive # Add the default status to the default settings. default_settings[name + '/status'] = PluginStatus.Inactive default_settings[name + '/last directory'] = '' # Append a setting for files in the mediamanager (note not all plugins # which have a mediamanager need this). if media_item_class is not None: default_settings['%s/%s files' % (name, name)] = [] # Add settings to the dict of all settings. Settings.extend_default_settings(default_settings) Registry().register_function('%s_add_service_item' % self.name, self.process_add_service_event) Registry().register_function('%s_config_updated' % self.name, self.config_update)
def _setup(self): """ Set up the dialog. This method is mocked out in tests. """ self.setup_ui(self) application_version = get_application_version() about_text = self.about_text_edit.toPlainText() about_text = about_text.replace("<version>", application_version["version"]) if application_version["build"]: build_text = translate("OpenLP.AboutForm", " build %s") % application_version["build"] else: build_text = "" about_text = about_text.replace("<revision>", build_text) self.about_text_edit.setPlainText(about_text) self.volunteer_button.clicked.connect(self.on_volunteer_button_clicked)
def __init__(self, parent): """ Do some initialisation stuff """ super(AboutForm, self).__init__(parent) application_version = get_application_version() self.setupUi(self) about_text = self.about_text_edit.toPlainText() about_text = about_text.replace('<version>', application_version['version']) if application_version['build']: build_text = translate('OpenLP.AboutForm', ' build %s') % application_version['build'] else: build_text = '' about_text = about_text.replace('<revision>', build_text) self.about_text_edit.setPlainText(about_text) self.volunteer_button.clicked.connect(self.on_volunteer_button_clicked)
def __init__(self, parent): """ Do some initialisation stuff """ QtGui.QDialog.__init__(self, parent) applicationVersion = get_application_version() self.setupUi(self) about_text = self.aboutTextEdit.toPlainText() about_text = about_text.replace(u'<version>', applicationVersion[u'version']) if applicationVersion[u'build']: build_text = translate('OpenLP.AboutForm', ' build %s') % applicationVersion[u'build'] else: build_text = u'' about_text = about_text.replace(u'<revision>', build_text) self.aboutTextEdit.setPlainText(about_text) QtCore.QObject.connect(self.volunteerButton, QtCore.SIGNAL(u'clicked()'), self.onVolunteerButtonClicked)
def _setup(self): """ Set up the dialog. This method is mocked out in tests. """ self.setup_ui(self) application_version = get_application_version() about_text = self.about_text_edit.toPlainText() about_text = about_text.replace('<version>', application_version['version']) if application_version['build']: build_text = translate('OpenLP.AboutForm', ' build %s') % application_version['build'] else: build_text = '' about_text = about_text.replace('<revision>', build_text) self.about_text_edit.setPlainText(about_text) self.volunteer_button.clicked.connect(self.on_volunteer_button_clicked)
def backup_on_upgrade(self, has_run_wizard, can_show_splash): """ Check if OpenLP has been upgraded, and ask if a backup of data should be made :param has_run_wizard: OpenLP has been run before """ data_version = Settings().value('core/application version') openlp_version = get_application_version()['version'] # New installation, no need to create backup if not has_run_wizard: Settings().setValue('core/application version', openlp_version) # If data_version is different from the current version ask if we should backup the data folder elif data_version != openlp_version: if can_show_splash and self.splash.isVisible(): self.splash.hide() if QtWidgets.QMessageBox.question( None, translate('OpenLP', 'Backup'), translate( 'OpenLP', 'OpenLP has been upgraded, do you want to create ' 'a backup of OpenLPs data folder?'), QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.Yes) == QtWidgets.QMessageBox.Yes: # Create copy of data folder data_folder_path = AppLocation.get_data_path() timestamp = time.strftime("%Y%m%d-%H%M%S") data_folder_backup_path = data_folder_path + '-' + timestamp try: shutil.copytree(data_folder_path, data_folder_backup_path) except OSError: QtWidgets.QMessageBox.warning( None, translate('OpenLP', 'Backup'), translate('OpenLP', 'Backup of the data folder failed!')) return QtWidgets.QMessageBox.information( None, translate('OpenLP', 'Backup'), translate( 'OpenLP', 'A backup of the data folder has been created at %s') % data_folder_backup_path) # Update the version in the settings Settings().setValue('core/application version', openlp_version) if can_show_splash: self.splash.show()
def song_to_xml(self, song): """ Convert the song to OpenLyrics Format. """ sxml = SongXML() song_xml = objectify.fromstring(u'<song/>') # Append the necessary meta data to the song. song_xml.set(u'xmlns', NAMESPACE) song_xml.set(u'version', OpenLyrics.IMPLEMENTED_VERSION) application_name = u'OpenLP ' + get_application_version()[u'version'] song_xml.set(u'createdIn', application_name) song_xml.set(u'modifiedIn', application_name) # "Convert" 2012-08-27 11:49:15 to 2012-08-27T11:49:15. song_xml.set(u'modifiedDate', unicode(song.last_modified).replace(u' ', u'T')) properties = etree.SubElement(song_xml, u'properties') titles = etree.SubElement(properties, u'titles') self._add_text_to_element(u'title', titles, song.title) if song.alternate_title: self._add_text_to_element(u'title', titles, song.alternate_title) if song.comments: comments = etree.SubElement(properties, u'comments') self._add_text_to_element(u'comment', comments, song.comments) if song.copyright: self._add_text_to_element(u'copyright', properties, song.copyright) if song.verse_order: self._add_text_to_element( u'verseOrder', properties, song.verse_order.lower()) if song.ccli_number: self._add_text_to_element(u'ccliNo', properties, song.ccli_number) if song.authors: authors = etree.SubElement(properties, u'authors') for author in song.authors: self._add_text_to_element(u'author', authors, author.display_name) book = self.manager.get_object_filtered(Book, Book.id == song.song_book_id) if book is not None: book = book.name songbooks = etree.SubElement(properties, u'songbooks') element = self._add_text_to_element(u'songbook', songbooks, None, book) if song.song_number: element.set(u'entry', song.song_number) if song.topics: themes = etree.SubElement(properties, u'themes') for topic in song.topics: self._add_text_to_element(u'theme', themes, topic.name) # Process the formatting tags. # Have we any tags in song lyrics? tags_element = None match = re.search(u'\{/?\w+\}', song.lyrics, re.UNICODE) if match: # Named 'format_' - 'format' is built-in fuction in Python. format_ = etree.SubElement(song_xml, u'format') tags_element = etree.SubElement(format_, u'tags') tags_element.set(u'application', u'OpenLP') # Process the song's lyrics. lyrics = etree.SubElement(song_xml, u'lyrics') verse_list = sxml.get_verses(song.lyrics) # Add a suffix letter to each verse verse_tags = [] for verse in verse_list: verse_tag = verse[0][u'type'][0].lower() verse_number = verse[0][u'label'] verse_def = verse_tag + verse_number verse_tags.append(verse_def) # Create the letter from the number of duplicates verse[0][u'suffix'] = chr(96 + verse_tags.count(verse_def)) # If the verse tag is a duplicate use the suffix letter for verse in verse_list: verse_tag = verse[0][u'type'][0].lower() verse_number = verse[0][u'label'] verse_def = verse_tag + verse_number if verse_tags.count(verse_def) > 1: verse_def += verse[0][u'suffix'] verse_element = self._add_text_to_element(u'verse', lyrics, None, verse_def) if u'lang' in verse[0]: verse_element.set(u'lang', verse[0][u'lang']) # Create a list with all "optional" verses. optional_verses = cgi.escape(verse[1]) optional_verses = optional_verses.split(u'\n[---]\n') start_tags = u'' end_tags = u'' for index, optional_verse in enumerate(optional_verses): # Fix up missing end and start tags such as {r} or {/r}. optional_verse = start_tags + optional_verse start_tags, end_tags = self._get_missing_tags(optional_verse) optional_verse += end_tags # Add formatting tags to text lines_element = self._add_text_with_tags_to_lines(verse_element, optional_verse, tags_element) # Do not add the break attribute to the last lines element. if index < len(optional_verses) - 1: lines_element.set(u'break', u'optional') return self._extract_xml(song_xml)
def main(args=None): """ The main function which parses command line options and then runs the PyQt4 Application. """ # Set up command line options. usage = 'Usage: %prog [options] [qt-options]' parser = OptionParser(usage=usage) parser.add_option('-e', '--no-error-form', dest='no_error_form', action='store_true', help='Disable the error notification form.') parser.add_option('-l', '--log-level', dest='loglevel', default='warning', metavar='LEVEL', help='Set logging to LEVEL level. Valid values are "debug", "info", "warning".') 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).') # Parse command line options and deal with them. # Use args supplied programatically if possible. (options, args) = parser.parse_args(args) if args else parser.parse_args() qt_args = [] if options.loglevel.lower() in ['d', 'debug']: log.setLevel(logging.DEBUG) elif options.loglevel.lower() in ['w', 'warning']: log.setLevel(logging.WARNING) else: log.setLevel(logging.INFO) if options.style: qt_args.extend(['-style', options.style]) # Throw the rest of the arguments at Qt, just in case. qt_args.extend(args) # Bug #1018855: Set the WM_CLASS property in X11 if platform.system() not in ['Windows', 'Darwin']: qt_args.append('OpenLP') # Initialise the resources qInitResources() # Now create and actually run the application. application = OpenLP(qt_args) application.setOrganizationName(u'OpenLP') application.setOrganizationDomain(u'openlp.org') if options.portable: application.setApplicationName(u'OpenLPPortable') Settings.setDefaultFormat(Settings.IniFormat) # Get location OpenLPPortable.ini application_path = AppLocation.get_directory(AppLocation.AppDir) set_up_logging(os.path.abspath(os.path.join(application_path, u'..', u'..', u'Other'))) log.info(u'Running portable') portable_settings_file = os.path.abspath(os.path.join(application_path, u'..', u'..', u'Data', u'OpenLP.ini')) # Make this our settings file log.info(u'INI file: %s', portable_settings_file) Settings.set_filename(portable_settings_file) portable_settings = Settings() # Set our data path data_path = os.path.abspath(os.path.join(application_path, u'..', u'..', u'Data',)) log.info(u'Data path: %s', data_path) # Point to our data path portable_settings.setValue(u'advanced/data path', data_path) portable_settings.setValue(u'advanced/is portable', True) portable_settings.sync() else: application.setApplicationName(u'OpenLP') set_up_logging(AppLocation.get_directory(AppLocation.CacheDir)) Registry.create() Registry().register(u'application', application) application.setApplicationVersion(get_application_version()[u'version']) # Instance check if application.is_already_running(): sys.exit() # First time checks in settings if not Settings().value(u'general/has run wizard'): if not FirstTimeLanguageForm().exec_(): # if cancel then stop processing sys.exit() # i18n Set Language language = LanguageManager.get_language() application_translator, default_translator = LanguageManager.get_translator(language) if not application_translator.isEmpty(): application.installTranslator(application_translator) if not default_translator.isEmpty(): application.installTranslator(default_translator) else: log.debug(u'Could not find default_translator.') if not options.no_error_form: sys.excepthook = application.hook_exception sys.exit(application.run(qt_args))
def main(args=None): """ The main function which parses command line options and then runs :param args: Some args """ args = parse_options(args) qt_args = [] if args and args.loglevel.lower() in ['d', 'debug']: log.setLevel(logging.DEBUG) elif args and args.loglevel.lower() in ['w', 'warning']: log.setLevel(logging.WARNING) else: log.setLevel(logging.INFO) if args and args.style: qt_args.extend(['-style', args.style]) # Throw the rest of the arguments at Qt, just in case. qt_args.extend(args.rargs) # Bug #1018855: Set the WM_CLASS property in X11 if not is_win() and not is_macosx(): qt_args.append('OpenLP') # Initialise the resources qInitResources() # Now create and actually run the application. application = OpenLP(qt_args) application.setOrganizationName('OpenLP') application.setOrganizationDomain('openlp.org') application.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) application.setAttribute(QtCore.Qt.AA_DontCreateNativeWidgetSiblings, True) if args and args.portable: application.setApplicationName('OpenLPPortable') Settings.setDefaultFormat(Settings.IniFormat) # Get location OpenLPPortable.ini application_path = AppLocation.get_directory(AppLocation.AppDir) set_up_logging( os.path.abspath(os.path.join(application_path, '..', '..', 'Other'))) log.info('Running portable') portable_settings_file = os.path.abspath( os.path.join(application_path, '..', '..', 'Data', 'OpenLP.ini')) # Make this our settings file log.info('INI file: %s', portable_settings_file) Settings.set_filename(portable_settings_file) portable_settings = Settings() # Set our data path data_path = os.path.abspath( os.path.join( application_path, '..', '..', 'Data', )) log.info('Data path: %s', data_path) # Point to our data path portable_settings.setValue('advanced/data path', data_path) portable_settings.setValue('advanced/is portable', True) portable_settings.sync() else: application.setApplicationName('OpenLP') set_up_logging(AppLocation.get_directory(AppLocation.CacheDir)) Registry.create() Registry().register('application', application) application.setApplicationVersion(get_application_version()['version']) # Check if an instance of OpenLP is already running. Quit if there is a running instance and the user only wants one if application.is_already_running(): sys.exit() # If the custom data path is missing and the user wants to restore the data path, quit OpenLP. if application.is_data_path_missing(): application.shared_memory.detach() sys.exit() # Remove/convert obsolete settings. Settings().remove_obsolete_settings() # First time checks in settings if not Settings().value('core/has run wizard'): if not FirstTimeLanguageForm().exec(): # if cancel then stop processing sys.exit() # i18n Set Language language = LanguageManager.get_language() translators = LanguageManager.get_translator(language) for translator in translators: if not translator.isEmpty(): application.installTranslator(translator) if not translators: log.debug('Could not find translators.') if args and not args.no_error_form: sys.excepthook = application.hook_exception sys.exit(application.run(qt_args))
def main(args=None): """ The main function which parses command line options and then runs :param args: Some args """ (options, args) = parse_options(args) qt_args = [] if options.loglevel.lower() in ['d', 'debug']: log.setLevel(logging.DEBUG) elif options.loglevel.lower() in ['w', 'warning']: log.setLevel(logging.WARNING) else: log.setLevel(logging.INFO) if options.style: qt_args.extend(['-style', options.style]) # Throw the rest of the arguments at Qt, just in case. qt_args.extend(args) # Bug #1018855: Set the WM_CLASS property in X11 if not is_win() and not is_macosx(): qt_args.append('OpenLP') # Initialise the resources qInitResources() # Now create and actually run the application. application = OpenLP(qt_args) application.setOrganizationName('OpenLP') application.setOrganizationDomain('openlp.org') if options.portable: application.setApplicationName('OpenLPPortable') Settings.setDefaultFormat(Settings.IniFormat) # Get location OpenLPPortable.ini application_path = AppLocation.get_directory(AppLocation.AppDir) set_up_logging(os.path.abspath(os.path.join(application_path, '..', '..', 'Other'))) log.info('Running portable') portable_settings_file = os.path.abspath(os.path.join(application_path, '..', '..', 'Data', 'OpenLP.ini')) # Make this our settings file log.info('INI file: %s', portable_settings_file) Settings.set_filename(portable_settings_file) portable_settings = Settings() # Set our data path data_path = os.path.abspath(os.path.join(application_path, '..', '..', 'Data',)) log.info('Data path: %s', data_path) # Point to our data path portable_settings.setValue('advanced/data path', data_path) portable_settings.setValue('advanced/is portable', True) portable_settings.sync() else: application.setApplicationName('OpenLP') set_up_logging(AppLocation.get_directory(AppLocation.CacheDir)) Registry.create() Registry().register('application', application) application.setApplicationVersion(get_application_version()['version']) # Instance check if application.is_already_running(): sys.exit() # Remove/convert obsolete settings. Settings().remove_obsolete_settings() # First time checks in settings if not Settings().value('core/has run wizard'): if not FirstTimeLanguageForm().exec_(): # if cancel then stop processing sys.exit() # i18n Set Language language = LanguageManager.get_language() application_translator, default_translator = LanguageManager.get_translator(language) if not application_translator.isEmpty(): application.installTranslator(application_translator) if not default_translator.isEmpty(): application.installTranslator(default_translator) else: log.debug('Could not find default_translator.') if not options.no_error_form: sys.excepthook = application.hook_exception sys.exit(application.run(qt_args))
def song_to_xml(self, song): """ Convert the song to OpenLyrics Format. """ sxml = SongXML() song_xml = objectify.fromstring("<song/>") # Append the necessary meta data to the song. song_xml.set("xmlns", NAMESPACE) song_xml.set("version", OpenLyrics.IMPLEMENTED_VERSION) application_name = "OpenLP " + get_application_version()["version"] song_xml.set("createdIn", application_name) song_xml.set("modifiedIn", application_name) # "Convert" 2012-08-27 11:49:15 to 2012-08-27T11:49:15. song_xml.set("modifiedDate", str(song.last_modified).replace(" ", "T")) properties = etree.SubElement(song_xml, "properties") titles = etree.SubElement(properties, "titles") self._add_text_to_element("title", titles, song.title) if song.alternate_title: self._add_text_to_element("title", titles, song.alternate_title) if song.comments: comments = etree.SubElement(properties, "comments") self._add_text_to_element("comment", comments, song.comments) if song.copyright: self._add_text_to_element("copyright", properties, song.copyright) if song.song_key: self._add_text_to_element("key", properties, song.song_key) if song.transpose_by: self._add_text_to_element("transposition", properties, song.transpose_by) if song.verse_order: self._add_text_to_element("verseOrder", properties, song.verse_order.lower()) if song.ccli_number: self._add_text_to_element("ccliNo", properties, song.ccli_number) if song.authors_songs: authors = etree.SubElement(properties, "authors") for author_song in song.authors_songs: element = self._add_text_to_element("author", authors, author_song.author.display_name) if author_song.author_type: # Handle the special case 'words+music': Need to create two separate authors for that if author_song.author_type == AuthorType.WordsAndMusic: element.set("type", AuthorType.Words) element = self._add_text_to_element("author", authors, author_song.author.display_name) element.set("type", AuthorType.Music) else: element.set("type", author_song.author_type) book = self.manager.get_object_filtered(Book, Book.id == song.song_book_id) if book is not None: book = book.name songbooks = etree.SubElement(properties, "songbooks") element = self._add_text_to_element("songbook", songbooks, None, book) if song.song_number: element.set("entry", song.song_number) if song.topics: themes = etree.SubElement(properties, "themes") for topic in song.topics: self._add_text_to_element("theme", themes, topic.name) # Process the formatting tags. # Have we any tags in song lyrics? tags_element = None match = re.search("\{/?\w+\}", song.lyrics, re.UNICODE) if match: # Named 'format_' - 'format' is built-in fuction in Python. format_ = etree.SubElement(song_xml, "format") tags_element = etree.SubElement(format_, "tags") tags_element.set("application", "OpenLP") # Process the song's lyrics. lyrics = etree.SubElement(song_xml, "lyrics") if song.chords: verse_list = sxml.get_verses(song.chords) else: verse_list = sxml.get_verses(song.lyrics) # Add a suffix letter to each verse verse_tags = [] for verse in verse_list: verse_tag = verse[0]["type"][0].lower() verse_number = verse[0]["label"] verse_def = verse_tag + verse_number # Create the letter from the number of duplicates verse[0][u"suffix"] = chr(97 + (verse_tags.count(verse_def) % 26)) verse_tags.append(verse_def) # If the verse tag is a duplicate use the suffix letter for verse in verse_list: verse_tag = verse[0]["type"][0].lower() verse_number = verse[0]["label"] verse_def = verse_tag + verse_number if verse_tags.count(verse_def) > 1: verse_def += verse[0]["suffix"] verse_element = self._add_text_to_element("verse", lyrics, None, verse_def) if "lang" in verse[0]: verse_element.set("lang", verse[0]["lang"]) # Create a list with all "optional" verses. # Don't html.escape the chord tags optional_verses = "" for lyric_chord_part in re.split('(<[\w\+#"=// ]* />)', verse[1]): if lyric_chord_part.startswith("<"): optional_verses += lyric_chord_part else: optional_verses += html.escape(lyric_chord_part) optional_verses = optional_verses.split("\n[---]\n") start_tags = "" end_tags = "" for index, optional_verse in enumerate(optional_verses): # Fix up missing end and start tags such as {r} or {/r}. optional_verse = start_tags + optional_verse start_tags, end_tags = self._get_missing_tags(optional_verse) optional_verse += end_tags # Add formatting tags to text lines_element = self._add_text_with_tags_to_lines(verse_element, optional_verse, tags_element) # Do not add the break attribute to the last lines element. if index < len(optional_verses) - 1: lines_element.set("break", "optional") return self._extract_xml(song_xml).decode()
def song_to_xml(self, song): """ Convert the song to OpenLyrics Format. """ sxml = SongXML() song_xml = objectify.fromstring('<song/>') # Append the necessary meta data to the song. song_xml.set('xmlns', NAMESPACE) song_xml.set('version', OpenLyrics.IMPLEMENTED_VERSION) application_name = 'OpenLP ' + get_application_version()['version'] song_xml.set('createdIn', application_name) song_xml.set('modifiedIn', application_name) # "Convert" 2012-08-27 11:49:15 to 2012-08-27T11:49:15. song_xml.set('modifiedDate', str(song.last_modified).replace(' ', 'T')) properties = etree.SubElement(song_xml, 'properties') titles = etree.SubElement(properties, 'titles') self._add_text_to_element('title', titles, song.title) if song.alternate_title: self._add_text_to_element('title', titles, song.alternate_title) if song.comments: comments = etree.SubElement(properties, 'comments') self._add_text_to_element('comment', comments, song.comments) if song.copyright: self._add_text_to_element('copyright', properties, song.copyright) if song.song_key: self._add_text_to_element('key', properties, song.song_key) if song.transpose_by: self._add_text_to_element('transposition', properties, song.transpose_by) if song.verse_order: self._add_text_to_element('verseOrder', properties, song.verse_order.lower()) if song.ccli_number: self._add_text_to_element('ccliNo', properties, song.ccli_number) if song.authors_songs: authors = etree.SubElement(properties, 'authors') for author_song in song.authors_songs: element = self._add_text_to_element( 'author', authors, author_song.author.display_name) if author_song.author_type: # Handle the special case 'words+music': Need to create two separate authors for that if author_song.author_type == AuthorType.WordsAndMusic: element.set('type', AuthorType.Words) element = self._add_text_to_element( 'author', authors, author_song.author.display_name) element.set('type', AuthorType.Music) else: element.set('type', author_song.author_type) book = self.manager.get_object_filtered(Book, Book.id == song.song_book_id) if book is not None: book = book.name songbooks = etree.SubElement(properties, 'songbooks') element = self._add_text_to_element('songbook', songbooks, None, book) if song.song_number: element.set('entry', song.song_number) if song.topics: themes = etree.SubElement(properties, 'themes') for topic in song.topics: self._add_text_to_element('theme', themes, topic.name) # Process the formatting tags. # Have we any tags in song lyrics? tags_element = None match = re.search('\{/?\w+\}', song.lyrics, re.UNICODE) if match: # Named 'format_' - 'format' is built-in fuction in Python. format_ = etree.SubElement(song_xml, 'format') tags_element = etree.SubElement(format_, 'tags') tags_element.set('application', 'OpenLP') # Process the song's lyrics. lyrics = etree.SubElement(song_xml, 'lyrics') if song.chords: verse_list = sxml.get_verses(song.chords) else: verse_list = sxml.get_verses(song.lyrics) # Add a suffix letter to each verse verse_tags = [] for verse in verse_list: verse_tag = verse[0]['type'][0].lower() verse_number = verse[0]['label'] verse_def = verse_tag + verse_number # Create the letter from the number of duplicates verse[0][u'suffix'] = chr(97 + (verse_tags.count(verse_def) % 26)) verse_tags.append(verse_def) # If the verse tag is a duplicate use the suffix letter for verse in verse_list: verse_tag = verse[0]['type'][0].lower() verse_number = verse[0]['label'] verse_def = verse_tag + verse_number if verse_tags.count(verse_def) > 1: verse_def += verse[0]['suffix'] verse_element = self._add_text_to_element('verse', lyrics, None, verse_def) if 'lang' in verse[0]: verse_element.set('lang', verse[0]['lang']) # Create a list with all "optional" verses. # Don't html.escape the chord tags optional_verses = '' for lyric_chord_part in re.split('(<[\w\+#"=// ]* />)', verse[1]): if lyric_chord_part.startswith('<'): optional_verses += lyric_chord_part else: optional_verses += html.escape(lyric_chord_part) optional_verses = optional_verses.split('\n[---]\n') start_tags = '' end_tags = '' for index, optional_verse in enumerate(optional_verses): # Fix up missing end and start tags such as {r} or {/r}. optional_verse = start_tags + optional_verse start_tags, end_tags = self._get_missing_tags(optional_verse) optional_verse += end_tags # Add formatting tags to text lines_element = self._add_text_with_tags_to_lines( verse_element, optional_verse, tags_element) # Do not add the break attribute to the last lines element. if index < len(optional_verses) - 1: lines_element.set('break', 'optional') return self._extract_xml(song_xml).decode()
def song_to_xml(self, song): """ Convert the song to OpenLyrics Format. """ sxml = SongXML() song_xml = objectify.fromstring('<song/>') # Append the necessary meta data to the song. song_xml.set('xmlns', NAMESPACE) song_xml.set('version', OpenLyrics.IMPLEMENTED_VERSION) application_name = 'OpenLP ' + get_application_version()['version'] song_xml.set('createdIn', application_name) song_xml.set('modifiedIn', application_name) # "Convert" 2012-08-27 11:49:15 to 2012-08-27T11:49:15. song_xml.set('modifiedDate', str(song.last_modified).replace(' ', 'T')) properties = etree.SubElement(song_xml, 'properties') titles = etree.SubElement(properties, 'titles') self._add_text_to_element('title', titles, song.title) if song.alternate_title: self._add_text_to_element('title', titles, song.alternate_title) if song.comments: comments = etree.SubElement(properties, 'comments') self._add_text_to_element('comment', comments, song.comments) if song.copyright: self._add_text_to_element('copyright', properties, song.copyright) if song.song_key: self._add_text_to_element('key', properties, song.song_key) if song.transpose_by: self._add_text_to_element('transposition', properties, song.transpose_by) if song.verse_order: self._add_text_to_element( 'verseOrder', properties, song.verse_order.lower()) if song.ccli_number: self._add_text_to_element('ccliNo', properties, song.ccli_number) if song.authors_songs: authors = etree.SubElement(properties, 'authors') for author_song in song.authors_songs: element = self._add_text_to_element('author', authors, author_song.author.display_name) if author_song.author_type: # Handle the special case 'words+music': Need to create two separate authors for that if author_song.author_type == AuthorType.WordsAndMusic: element.set('type', AuthorType.Words) element = self._add_text_to_element('author', authors, author_song.author.display_name) element.set('type', AuthorType.Music) else: element.set('type', author_song.author_type) book = self.manager.get_object_filtered(Book, Book.id == song.song_book_id) if book is not None: book = book.name songbooks = etree.SubElement(properties, 'songbooks') element = self._add_text_to_element('songbook', songbooks, None, book) if song.song_number: element.set('entry', song.song_number) if song.topics: themes = etree.SubElement(properties, 'themes') for topic in song.topics: self._add_text_to_element('theme', themes, topic.name) # Process the formatting tags. # Have we any tags in song lyrics? tags_element = None match = re.search('\{/?\w+\}', song.lyrics, re.UNICODE) if match: # Named 'format_' - 'format' is built-in fuction in Python. format_ = etree.SubElement(song_xml, 'format') tags_element = etree.SubElement(format_, 'tags') tags_element.set('application', 'OpenLP') # Process the song's lyrics. lyrics = etree.SubElement(song_xml, 'lyrics') if song.chords: verse_list = sxml.get_verses(song.chords) else: verse_list = sxml.get_verses(song.lyrics) # Add a suffix letter to each verse verse_tags = [] for verse in verse_list: verse_tag = verse[0]['type'][0].lower() verse_number = verse[0]['label'] verse_def = verse_tag + verse_number # Create the letter from the number of duplicates verse[0][u'suffix'] = chr(97 + (verse_tags.count(verse_def) % 26)) verse_tags.append(verse_def) # If the verse tag is a duplicate use the suffix letter for verse in verse_list: verse_tag = verse[0]['type'][0].lower() verse_number = verse[0]['label'] verse_def = verse_tag + verse_number if verse_tags.count(verse_def) > 1: verse_def += verse[0]['suffix'] verse_element = self._add_text_to_element('verse', lyrics, None, verse_def) if 'lang' in verse[0]: verse_element.set('lang', verse[0]['lang']) # Create a list with all "optional" verses. # Don't html.escape the chord tags optional_verses = '' for lyric_chord_part in re.split('(<[\w\+#"=// ]* />)', verse[1]): if lyric_chord_part.startswith('<'): optional_verses += lyric_chord_part else: optional_verses += html.escape(lyric_chord_part) optional_verses = optional_verses.split('\n[---]\n') start_tags = '' end_tags = '' for index, optional_verse in enumerate(optional_verses): # Fix up missing end and start tags such as {r} or {/r}. optional_verse = start_tags + optional_verse start_tags, end_tags = self._get_missing_tags(optional_verse) optional_verse += end_tags # Add formatting tags to text lines_element = self._add_text_with_tags_to_lines(verse_element, optional_verse, tags_element) # Do not add the break attribute to the last lines element. if index < len(optional_verses) - 1: lines_element.set('break', 'optional') return self._extract_xml(song_xml).decode()