def check_installed(self): """ Check the viewer is installed. :return: True if program to open PDF-files was found, otherwise False. """ log.debug('check_installed Pdf') self.mudrawbin = '' self.mutoolbin = '' self.gsbin = '' self.also_supports = [] # Use the user defined program if given if Settings().value('presentations/enable_pdf_program'): pdf_program = Settings().value('presentations/pdf_program') program_type = self.check_binary(pdf_program) if program_type == 'gs': self.gsbin = pdf_program elif program_type == 'mudraw': self.mudrawbin = pdf_program elif program_type == 'mutool': self.mutoolbin = pdf_program else: # Fallback to autodetection application_path = AppLocation.get_directory(AppLocation.AppDir) if is_win(): # for windows we only accept mudraw.exe or mutool.exe in the base folder application_path = AppLocation.get_directory(AppLocation.AppDir) if os.path.isfile(os.path.join(application_path, 'mudraw.exe')): self.mudrawbin = os.path.join(application_path, 'mudraw.exe') elif os.path.isfile(os.path.join(application_path, 'mutool.exe')): self.mutoolbin = os.path.join(application_path, 'mutool.exe') else: DEVNULL = open(os.devnull, 'wb') # First try to find mudraw self.mudrawbin = which('mudraw') # if mudraw isn't installed, try mutool if not self.mudrawbin: self.mutoolbin = which('mutool') # Check we got a working mutool if not self.mutoolbin or self.check_binary(self.mutoolbin) != 'mutool': self.gsbin = which('gs') # Last option: check if mudraw or mutool is placed in OpenLP base folder if not self.mudrawbin and not self.mutoolbin and not self.gsbin: application_path = AppLocation.get_directory(AppLocation.AppDir) if os.path.isfile(os.path.join(application_path, 'mudraw')): self.mudrawbin = os.path.join(application_path, 'mudraw') elif os.path.isfile(os.path.join(application_path, 'mutool')): self.mutoolbin = os.path.join(application_path, 'mutool') if self.mudrawbin or self.mutoolbin: self.also_supports = ['xps', 'oxps'] return True elif self.gsbin: return True else: return False
def find_qm_files(): """ Find all available language files in this OpenLP install """ log.debug('Translation files: %s', AppLocation.get_directory( AppLocation.LanguageDir)) trans_dir = QtCore.QDir(AppLocation.get_directory(AppLocation.LanguageDir)) file_names = trans_dir.entryList('*.qm', QtCore.QDir.Files, QtCore.QDir.Name) # Remove qm files from the list which start with "qt_". file_names = [file_ for file_ in file_names if not file_.startswith('qt_')] return list(map(trans_dir.filePath, file_names))
def checkPreConditions(self): """ Check to see if we have any presentation software available If Not do not install the plugin. """ log.debug(u'checkPreConditions') controller_dir = os.path.join( AppLocation.get_directory(AppLocation.PluginsDir), u'presentations', u'lib') for filename in os.listdir(controller_dir): if filename.endswith(u'controller.py') and not filename == 'presentationcontroller.py': path = os.path.join(controller_dir, filename) if os.path.isfile(path): modulename = u'openlp.plugins.presentations.lib.' + os.path.splitext(filename)[0] log.debug(u'Importing controller %s', modulename) try: __import__(modulename, globals(), locals(), []) except ImportError: log.warn(u'Failed to import %s on path %s', modulename, path) controller_classes = PresentationController.__subclasses__() for controller_class in controller_classes: controller = controller_class(self) self.registerControllers(controller) return bool(self.controllers)
def __init__(self): """ Initialise the router """ self.routes = [ ('^/$', self.serve_file), ('^/(stage)$', self.serve_file), ('^/(main)$', self.serve_file), (r'^/files/(.*)$', self.serve_file), (r'^/api/poll$', self.poll), (r'^/stage/poll$', self.poll), (r'^/main/poll$', self.main_poll), (r'^/main/image$', self.main_image), (r'^/api/controller/(live|preview)/(.*)$', self.controller), (r'^/stage/controller/(live|preview)/(.*)$', self.controller), (r'^/api/service/(.*)$', self.service), (r'^/stage/service/(.*)$', self.service), (r'^/api/display/(hide|show|blank|theme|desktop)$', self.display), (r'^/api/alert$', self.alert), (r'^/api/plugin/(search)$', self.plugin_info), (r'^/api/(.*)/search$', self.search), (r'^/api/(.*)/live$', self.go_live), (r'^/api/(.*)/add$', self.add_to_service) ] self.translate() self.html_dir = os.path.join(AppLocation.get_directory(AppLocation.PluginsDir), 'remotes', 'html')
def define_config(self): """ Define the configuration of the server. """ if Settings().value(self.settings_section + '/https enabled'): port = Settings().value(self.settings_section + '/https port') address = Settings().value(self.settings_section + '/ip address') local_data = AppLocation.get_directory(AppLocation.DataDir) cherrypy.config.update({'server.socket_host': str(address), 'server.socket_port': port, 'server.ssl_certificate': os.path.join(local_data, 'remotes', 'openlp.crt'), 'server.ssl_private_key': os.path.join(local_data, 'remotes', 'openlp.key')}) else: port = Settings().value(self.settings_section + '/port') address = Settings().value(self.settings_section + '/ip address') cherrypy.config.update({'server.socket_host': str(address)}) cherrypy.config.update({'server.socket_port': port}) cherrypy.config.update({'environment': 'embedded'}) cherrypy.config.update({'engine.autoreload_on': False}) directory_config = {'/': {'tools.staticdir.on': True, 'tools.staticdir.dir': self.router.html_dir, 'tools.basic_auth.on': Settings().value('remotes/authentication enabled'), 'tools.basic_auth.realm': 'OpenLP Remote Login', 'tools.basic_auth.users': fetch_password, 'tools.basic_auth.encrypt': make_sha_hash}, '/files': {'tools.staticdir.on': True, 'tools.staticdir.dir': self.router.html_dir, 'tools.basic_auth.on': False}, '/stage': {'tools.staticdir.on': True, 'tools.staticdir.dir': self.router.html_dir, 'tools.basic_auth.on': False}, '/main': {'tools.staticdir.on': True, 'tools.staticdir.dir': self.router.html_dir, 'tools.basic_auth.on': False}} return directory_config
def check_available_media_players(self): """ Check to see if we have any media Player's available. """ log.debug('_check_available_media_players') controller_dir = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'core', 'ui', 'media') for filename in os.listdir(controller_dir): if filename.endswith('player.py') and not filename == 'mediaplayer.py': path = os.path.join(controller_dir, filename) if os.path.isfile(path): modulename = 'openlp.core.ui.media.' + os.path.splitext(filename)[0] log.debug('Importing controller %s', modulename) try: __import__(modulename, globals(), locals(), []) # On some platforms importing vlc.py might cause # also OSError exceptions. (e.g. Mac OS X) except (ImportError, OSError): log.warn('Failed to import %s on path %s', modulename, path) player_classes = MediaPlayer.__subclasses__() for player_class in player_classes: player = player_class(self) self.register_players(player) if not self.media_players: return False savedPlayers, overriddenPlayer = get_media_players() invalid_media_players = [mediaPlayer for mediaPlayer in savedPlayers if not mediaPlayer in self.media_players or not self.media_players[mediaPlayer].check_available()] if invalid_media_players: for invalidPlayer in invalid_media_players: savedPlayers.remove(invalidPlayer) set_media_players(savedPlayers, overriddenPlayer) self._set_active_players() self._generate_extensions_lists() return True
def __init__(self, parent, **kwargs): log.debug(self.__class__.__name__) BibleDB.__init__(self, parent, **kwargs) self.filename = kwargs[u'filename'] self.language_regex = re.compile(r'<language.*>(.*?)</language>') self.verse_regex = re.compile( r'<verse osisID="([a-zA-Z0-9 ]*).([0-9]*).([0-9]*)">(.*?)</verse>') self.note_regex = re.compile(r'<note(.*?)>(.*?)</note>') self.title_regex = re.compile(r'<title(.*?)>(.*?)</title>') self.milestone_regex = re.compile(r'<milestone(.*?)/>') self.fi_regex = re.compile(r'<FI>(.*?)<Fi>') self.rf_regex = re.compile(r'<RF>(.*?)<Rf>') self.lb_regex = re.compile(r'<lb(.*?)>') self.lg_regex = re.compile(r'<lg(.*?)>') self.l_regex = re.compile(r'<l (.*?)>') self.w_regex = re.compile(r'<w (.*?)>') self.q_regex = re.compile(r'<q(.*?)>') self.q1_regex = re.compile(r'<q(.*?)level="1"(.*?)>') self.q2_regex = re.compile(r'<q(.*?)level="2"(.*?)>') self.trans_regex = re.compile(r'<transChange(.*?)>(.*?)</transChange>') self.divine_name_regex = re.compile( r'<divineName(.*?)>(.*?)</divineName>') self.spaces_regex = re.compile(r'([ ]{2,})') filepath = os.path.join( AppLocation.get_directory(AppLocation.PluginsDir), u'bibles', u'resources', u'osisbooks.csv')
def check_installed(self): """ Check the viewer is installed. :return: True if program to open PDF-files was found, otherwise False. """ log.debug('check_installed Pdf') self.mudrawbin = '' self.gsbin = '' self.also_supports = [] # Use the user defined program if given if Settings().value('presentations/enable_pdf_program'): pdf_program = Settings().value('presentations/pdf_program') program_type = self.check_binary(pdf_program) if program_type == 'gs': self.gsbin = pdf_program elif program_type == 'mudraw': self.mudrawbin = pdf_program else: # Fallback to autodetection application_path = AppLocation.get_directory(AppLocation.AppDir) if is_win(): # for windows we only accept mudraw.exe in the base folder application_path = AppLocation.get_directory(AppLocation.AppDir) if os.path.isfile(os.path.join(application_path, 'mudraw.exe')): self.mudrawbin = os.path.join(application_path, 'mudraw.exe') else: DEVNULL = open(os.devnull, 'wb') # First try to find mupdf self.mudrawbin = which('mudraw') # if mupdf isn't installed, fallback to ghostscript if not self.mudrawbin: self.gsbin = which('gs') # Last option: check if mudraw is placed in OpenLP base folder if not self.mudrawbin and not self.gsbin: application_path = AppLocation.get_directory(AppLocation.AppDir) if os.path.isfile(os.path.join(application_path, 'mudraw')): self.mudrawbin = os.path.join(application_path, 'mudraw') if self.mudrawbin: self.also_supports = ['xps', 'oxps'] return True elif self.gsbin: return True else: return False
def get_cursor(): """ Return the cursor object. Instantiate one if it doesn't exist yet. """ if BiblesResourcesDB.cursor is None: filepath = os.path.join(AppLocation.get_directory(AppLocation.PluginsDir), u'bibles', u'resources', u'bibles_resources.sqlite') conn = sqlite3.connect(filepath) BiblesResourcesDB.cursor = conn.cursor() return BiblesResourcesDB.cursor
def get_directory_for_app_dir_test(self): """ Test the AppLocation.get_directory() method for AppLocation.AppDir """ with patch(u'openlp.core.utils._get_frozen_path') as mocked_get_frozen_path: mocked_get_frozen_path.return_value = u'app/dir' # WHEN: We call AppLocation.get_directory directory = AppLocation.get_directory(AppLocation.AppDir) # THEN: assert directory == u'app/dir', u'Directory should be "app/dir"'
def __init__(self, plugin): """ Initialise the httpserver, and start the server. """ log.debug(u'Initialise httpserver') self.plugin = plugin self.html_dir = os.path.join(AppLocation.get_directory(AppLocation.PluginsDir), u'remotes', u'html') self.connections = [] self.current_item = None self.current_slide = None self.start_tcp()
def start_process(self): """ Loads the PPTVIEWLIB library. """ if self.process: return log.debug('start PPTView') dll_path = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'plugins', 'presentations', 'lib', 'pptviewlib', 'pptviewlib.dll') self.process = cdll.LoadLibrary(dll_path) if log.isEnabledFor(logging.DEBUG): self.process.SetDebug(1)
def start_process(self): """ Loads the PPTVIEWLIB library. """ if self.process: return log.debug('start PPTView') dll_path = os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'plugins', 'presentations', 'lib', 'pptviewlib', 'pptviewlib.dll') self.process = cdll.LoadLibrary(dll_path) if log.isEnabledFor(logging.DEBUG): self.process.SetDebug(1)
def __init__(self): """ The constructor for the plugin manager. Passes the controllers on to the plugins for them to interact with via their ServiceItems. """ log.info('Plugin manager Initialising') Registry().register('plugin_manager', self) Registry().register_function('bootstrap_initialise', self.bootstrap_initialise) self.base_path = os.path.abspath(AppLocation.get_directory(AppLocation.PluginsDir)) log.debug('Base path %s ', self.base_path) self.plugins = [] log.info('Plugin manager Initialised')
def gs_get_resolution(self, size): """ Only used when using ghostscript Ghostscript can't scale automatically while keeping aspect like mupdf, so we need to get the ratio between the screen size and the PDF to scale :param size: Size struct containing the screen size. :return: The resolution dpi to be used. """ # Use a postscript script to get size of the pdf. It is assumed that all pages have same size gs_resolution_script = AppLocation.get_directory( AppLocation.PluginsDir ) + '/presentations/lib/ghostscript_get_resolution.ps' # Run the script on the pdf to get the size runlog = [] try: runlog = check_output([ self.controller.gsbin, '-dNOPAUSE', '-dNODISPLAY', '-dBATCH', '-sFile=' + self.file_path, gs_resolution_script ], startupinfo=self.startupinfo) except CalledProcessError as e: log.debug(' '.join(e.cmd)) log.debug(e.output) # Extract the pdf resolution from output, the format is " Size: x: <width>, y: <height>" width = 0.0 height = 0.0 for line in runlog.splitlines(): try: width = float( re.search('.*Size: x: (\d+\.?\d*), y: \d+.*', line.decode()).group(1)) height = float( re.search('.*Size: x: \d+\.?\d*, y: (\d+\.?\d*).*', line.decode()).group(1)) break except AttributeError: continue # Calculate the ratio from pdf to screen if width > 0 and height > 0: width_ratio = size.width() / width height_ratio = size.height() / height # return the resolution that should be used. 72 is default. if width_ratio > height_ratio: return int(height_ratio * 72) else: return int(width_ratio * 72) else: return 72
def get_directory_for_plugins_dir_test(self): """ Test the AppLocation.get_directory() method for AppLocation.PluginsDir """ with patch(u'openlp.core.utils._get_frozen_path') as mocked_get_frozen_path, \ patch(u'openlp.core.utils.os.path.abspath') as mocked_abspath, \ patch(u'openlp.core.utils.os.path.split') as mocked_split, \ patch(u'openlp.core.utils.sys') as mocked_sys: mocked_abspath.return_value = u'plugins/dir' mocked_split.return_value = [u'openlp'] mocked_get_frozen_path.return_value = u'plugins/dir' mocked_sys.frozen = 1 mocked_sys.argv = ['openlp'] # WHEN: We call AppLocation.get_directory directory = AppLocation.get_directory(AppLocation.PluginsDir) # THEN: assert directory == u'plugins/dir', u'Directory should be "plugins/dir"'
def get_translator(language): """ Set up a translator to use in this instance of OpenLP ``language`` The language to load into the translator """ if LanguageManager.auto_language: language = QtCore.QLocale.system().name() lang_path = AppLocation.get_directory(AppLocation.LanguageDir) app_translator = QtCore.QTranslator() app_translator.load(language, lang_path) # A translator for buttons and other default strings provided by Qt. if sys.platform != 'win32' and sys.platform != 'darwin': lang_path = QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath) default_translator = QtCore.QTranslator() default_translator.load('qt_%s' % language, lang_path) return app_translator, default_translator
def gs_get_resolution(self, size): """ Only used when using ghostscript Ghostscript can't scale automatically while keeping aspect like mupdf, so we need to get the ratio between the screen size and the PDF to scale :param size: Size struct containing the screen size. :return: The resolution dpi to be used. """ # Use a postscript script to get size of the pdf. It is assumed that all pages have same size gs_resolution_script = AppLocation.get_directory( AppLocation.PluginsDir) + '/presentations/lib/ghostscript_get_resolution.ps' # Run the script on the pdf to get the size runlog = [] try: runlog = check_output([self.controller.gsbin, '-dNOPAUSE', '-dNODISPLAY', '-dBATCH', '-sFile=' + self.file_path, gs_resolution_script], startupinfo=self.startupinfo) except CalledProcessError as e: log.debug(' '.join(e.cmd)) log.debug(e.output) # Extract the pdf resolution from output, the format is " Size: x: <width>, y: <height>" width = 0.0 height = 0.0 for line in runlog.splitlines(): try: width = float(re.search('.*Size: x: (\d+\.?\d*), y: \d+.*', line.decode()).group(1)) height = float(re.search('.*Size: x: \d+\.?\d*, y: (\d+\.?\d*).*', line.decode()).group(1)) break except AttributeError: continue # Calculate the ratio from pdf to screen if width > 0 and height > 0: width_ratio = size.width() / width height_ratio = size.height() / height # return the resolution that should be used. 72 is default. if width_ratio > height_ratio: return int(height_ratio * 72) else: return int(width_ratio * 72) else: return 72
def get_cursor(): """ Return the cursor object. Instantiate one if it doesn't exist yet. If necessary loads up the database and creates the tables if the database doesn't exist. """ if AlternativeBookNamesDB.cursor is None: filepath = os.path.join( AppLocation.get_directory(AppLocation.DataDir), u'bibles', u'alternative_book_names.sqlite') if not os.path.exists(filepath): #create new DB, create table alternative_book_names AlternativeBookNamesDB.conn = sqlite3.connect(filepath) AlternativeBookNamesDB.conn.execute(u'CREATE TABLE ' u'alternative_book_names(id INTEGER NOT NULL, ' u'book_reference_id INTEGER, language_id INTEGER, name ' u'VARCHAR(50), PRIMARY KEY (id))') else: #use existing DB AlternativeBookNamesDB.conn = sqlite3.connect(filepath) AlternativeBookNamesDB.cursor = AlternativeBookNamesDB.conn.cursor() return AlternativeBookNamesDB.cursor
def on_data_directory_default_button_clicked(self): """ Re-set the data directory location to the 'default' location. """ new_data_path = AppLocation.get_directory(AppLocation.DataDir) if self.current_data_path.lower() != new_data_path.lower(): # Make sure they want to change the data location back to the # default. answer = QtGui.QMessageBox.question(self, translate('OpenLP.AdvancedTab', 'Reset Data Directory'), translate('OpenLP.AdvancedTab', 'Are you sure you want to change the location of the OpenLP ' 'data directory to the default location?\n\nThis location will be used after OpenLP is closed.'), QtGui.QMessageBox.StandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No), QtGui.QMessageBox.No) if answer != QtGui.QMessageBox.Yes: return self.check_data_overwrite(new_data_path) # Save the new location. self.main_window.set_new_data_path(new_data_path) self.new_data_directory_edit.setText(os.path.abspath(new_data_path)) self.data_directory_cancel_button.show() else: # We cancel the change in case user changed their mind. self.on_data_directory_cancel_button_clicked()
def load(self): """ Load the configuration and update the server configuration if necessary """ self.port_spin_box.setValue(Settings().value(self.settings_section + '/port')) self.https_port_spin_box.setValue(Settings().value(self.settings_section + '/https port')) self.address_edit.setText(Settings().value(self.settings_section + '/ip address')) self.twelve_hour = Settings().value(self.settings_section + '/twelve hour') self.twelve_hour_check_box.setChecked(self.twelve_hour) local_data = AppLocation.get_directory(AppLocation.DataDir) if not os.path.exists(os.path.join(local_data, 'remotes', 'openlp.crt')) or \ not os.path.exists(os.path.join(local_data, 'remotes', 'openlp.key')): self.https_settings_group_box.setChecked(False) self.https_settings_group_box.setEnabled(False) self.https_error_label.setVisible(True) else: self.https_settings_group_box.setChecked(Settings().value(self.settings_section + '/https enabled')) self.https_settings_group_box.setEnabled(True) self.https_error_label.setVisible(False) self.user_login_group_box.setChecked(Settings().value(self.settings_section + '/authentication enabled')) self.user_id.setText(Settings().value(self.settings_section + '/user id')) self.password.setText(Settings().value(self.settings_section + '/password')) self.set_urls() self.https_changed()
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))