def _create_report(self): """ Create an exception report. """ openlp_version = get_version() description = self.description_text_edit.toPlainText() traceback = self.exception_text_edit.toPlainText() system = translate( 'OpenLP.ExceptionForm', 'Platform: {platform}\n').format(platform=platform.platform()) library_versions = get_library_versions() library_versions['PyUNO'] = self._get_pyuno_version() libraries = '\n'.join([ '{}: {}'.format(library, version) for library, version in library_versions.items() ]) 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' # NOTE: Keys match the expected input for self.report_text.format() return { 'version': openlp_version, 'description': description, 'traceback': traceback, 'system': system, 'libs': libraries }
def _setup(self, version): """ Run some initial setup. This method is separate from __init__ in order to mock it out in tests. :param version: Defaults to *None*, which means that the same version number is used as OpenLP's version number. :rtype: None """ if version: self.version = version else: self.version = get_version()['version']
def test_get_version_dev_version(): """ Test the get_version() function """ # GIVEN: We're in dev mode with patch.object(sys, 'argv', ['--dev-version']), \ patch('openlp.core.version.APPLICATION_VERSION', None): # WHEN: get_version() is run version = get_version() # THEN: version is something assert version
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 :param can_show_splash: Should OpenLP show the splash screen """ data_version = Settings().value('core/application version') openlp_version = get_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\n' 'a backup of the old data folder?'), defaultButton=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.with_name( data_folder_path.name + '-' + timestamp) try: 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 message = translate( 'OpenLP', 'A backup of the data folder has been created at:\n\n' '{text}').format(text=data_folder_backup_path) QtWidgets.QMessageBox.information( None, translate('OpenLP', 'Backup'), message) # Update the version in the settings Settings().setValue('core/application version', openlp_version) if can_show_splash: self.splash.show()
def _setup(self): """ Set up the dialog. This method is mocked out in tests. """ self.setup_ui(self) application_version = get_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 {version}').format( version=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 _create_report(self): """ Create an exception report. """ openlp_version = get_version() description = self.description_text_edit.toPlainText() traceback = self.exception_text_edit.toPlainText() system = translate( 'OpenLP.ExceptionForm', 'Platform: {platform}\n').format(platform=platform.platform()) libraries = ( 'Python: {python}\nQt5: {qt5}\nPyQt5: {pyqt5}\nQtWebkit: {qtwebkit}\nSQLAlchemy: {sqalchemy}\n' 'SQLAlchemy Migrate: {migrate}\nBeautifulSoup: {soup}\nlxml: {etree}\nChardet: {chardet}\n' 'PyEnchant: {enchant}\nMako: {mako}\npyICU: {icu}\npyUNO bridge: {uno}\n' 'VLC: {vlc}\n').format(python=platform.python_version(), qt5=Qt.qVersion(), pyqt5=Qt.PYQT_VERSION_STR, qtwebkit=WEBKIT_VERSION, sqalchemy=sqlalchemy.__version__, migrate=MIGRATE_VERSION, soup=bs4.__version__, etree=etree.__version__, chardet=CHARDET_VERSION, enchant=ENCHANT_VERSION, mako=MAKO_VERSION, icu=ICU_VERSION, uno=self._pyuno_import(), vlc=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' # NOTE: Keys match the expected input for self.report_text.format() return { 'version': openlp_version, 'description': description, 'traceback': traceback, 'system': system, 'libs': libraries }
def _setup(self): """ Set up the dialog. This method is mocked out in tests. """ self.setup_ui(self) self.button_box.buttons()[0].setFocus() application_version = get_version() about_text = self.about_text_edit.toHtml() about_text = about_text.replace('{version}', application_version['version']) if application_version['build']: build_text = translate('OpenLP.AboutForm', ' build {version}').format( version=application_version['build']) else: build_text = '' about_text = about_text.replace('{revision}', build_text) self.about_text_edit.setHtml(about_text) self.contribute_button.clicked.connect( self.on_contribute_button_clicked)
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) # 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.portable: application.setApplicationName('OpenLPPortable') Settings.setDefaultFormat(Settings.IniFormat) # Get location OpenLPPortable.ini portable_path = (AppLocation.get_directory(AppLocation.AppDir) / '..' / '..').resolve() data_path = portable_path / 'Data' set_up_logging(portable_path / 'Other') log.info('Running portable') portable_settings_path = data_path / 'OpenLP.ini' # Make this our settings file log.info('INI file: {name}'.format(name=portable_settings_path)) Settings.set_filename(str(portable_settings_path)) portable_settings = Settings() # Set our data path log.info('Data path: {name}'.format(name=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) Registry().set_flag('no_web_server', args.no_web_server) application.setApplicationVersion(get_version()['version']) # Check if an instance of OpenLP is already running. Quit if there is a running instance and the user only wants one server = Server() if server.is_another_instance_running(): application.is_already_running() server.post_to_server(qt_args) sys.exit() else: server.start_server() application.server = server # If the custom data path is missing and the user wants to restore the data path, quit OpenLP. if application.is_data_path_missing(): server.close_server() sys.exit() # Upgrade settings. settings = Settings() if settings.can_upgrade(): now = datetime.now() # Only back up if OpenLP has previously run. if settings.value('core/has run wizard'): back_up_path = AppLocation.get_data_path() / ( now.strftime('%Y-%m-%d %H-%M') + '.conf') log.info( 'Settings about to be upgraded. Existing settings are being backed up to {back_up_path}' .format(back_up_path=back_up_path)) QtWidgets.QMessageBox.information( None, translate('OpenLP', 'Settings Upgrade'), translate( 'OpenLP', 'Your settings are about to be upgraded. A backup will be created at ' '{back_up_path}').format(back_up_path=back_up_path)) settings.export(back_up_path) settings.upgrade_settings() # First time checks in settings if not Settings().value('core/has run wizard'): if not FirstTimeLanguageForm().exec(): # if cancel then stop processing server.close_server() sys.exit() # i18n Set Language language = LanguageManager.get_language() translators = LanguageManager.get_translators(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 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_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.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) if song.songbook_entries: songbooks = etree.SubElement(properties, 'songbooks') for songbook_entry in song.songbook_entries: element = self._add_text_to_element( 'songbook', songbooks, None, songbook_entry.songbook.name) if songbook_entry.entry: element.set('entry', songbook_entry.entry) 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(r'\{/?\w+\}', song.lyrics) if match: # Named 'format_' - 'format' is built-in function 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') 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. optional_verses = html.escape(verse[1]) 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') xml_text = self._extract_xml(song_xml).decode() return self._chordpro_to_openlyrics(xml_text)