diff --git a/openlp/plugins/bibles/forms/bibleimportform.py b/openlp/plugins/bibles/forms/bibleimportform.py index 66ba252fc..3289e66e9 100644 --- a/openlp/plugins/bibles/forms/bibleimportform.py +++ b/openlp/plugins/bibles/forms/bibleimportform.py @@ -577,7 +577,7 @@ class BibleImportForm(OpenLPWizard): :param index: The index of the combo box. """ self.web_translation_combo_box.clear() - if self.web_bible_list: + if self.web_bible_list and index in self.web_bible_list: bibles = list(self.web_bible_list[index].keys()) bibles.sort(key=get_locale_key) self.web_translation_combo_box.addItems(bibles) diff --git a/openlp/plugins/bibles/lib/http.py b/openlp/plugins/bibles/lib/http.py index 4398688ee..2076bec87 100644 --- a/openlp/plugins/bibles/lib/http.py +++ b/openlp/plugins/bibles/lib/http.py @@ -520,7 +520,7 @@ class CWExtract(RegistryProperties): returns a list in the form [(biblename, biblekey, language_code)] """ log.debug('CWExtract.get_bibles_from_http') - bible_url = 'http://www.biblestudytools.com/search/bible-search.part/' + bible_url = 'http://www.biblestudytools.com/' soup = get_soup_for_bible_ref(bible_url) if not soup: return None @@ -528,7 +528,7 @@ class CWExtract(RegistryProperties): if not bible_select: log.debug('No select tags found - did site change?') return None - option_tags = bible_select.find_all('option') + option_tags = bible_select.find_all('option', {'class': 'log-translation'}) if not option_tags: log.debug('No option tags found - did site change?') return None diff --git a/openlp/plugins/media/mediaplugin.py b/openlp/plugins/media/mediaplugin.py index 1d5529084..f9874c57b 100644 --- a/openlp/plugins/media/mediaplugin.py +++ b/openlp/plugins/media/mediaplugin.py @@ -71,8 +71,12 @@ class MediaPlugin(Plugin): :return: true or false """ log.debug('check_installed Mediainfo') - # Use the user defined program if given - return process_check_binary('mediainfo') + # Try to find mediainfo in the path + exists = process_check_binary('mediainfo') + # If mediainfo is not in the path, try to find it in the application folder + if not exists: + exists = process_check_binary(os.path.join(AppLocation.get_directory(AppLocation.AppDir), 'mediainfo')) + return exists def app_startup(self): """ @@ -160,7 +164,6 @@ def process_check_binary(program_path): """ program_type = None runlog = check_binary_exists(program_path) - print(runlog, type(runlog)) # Analyse the output to see it the program is mediainfo for line in runlog.splitlines(): decoded_line = line.decode() diff --git a/openlp/plugins/presentations/lib/pdfcontroller.py b/openlp/plugins/presentations/lib/pdfcontroller.py index 48150a9f2..cf89d8d32 100644 --- a/openlp/plugins/presentations/lib/pdfcontroller.py +++ b/openlp/plugins/presentations/lib/pdfcontroller.py @@ -77,6 +77,12 @@ class PdfController(PresentationController): if found_mudraw: program_type = 'mudraw' break + found_mutool = re.search('usage: mutool.*', decoded_line, re.IGNORECASE) + if found_mutool: + # Test that mutool contains mudraw + if re.search('draw\s+--\s+convert document.*', runlog.decode(), re.IGNORECASE | re.MULTILINE): + program_type = 'mutool' + break found_gs = re.search('GPL Ghostscript.*', decoded_line, re.IGNORECASE) if found_gs: program_type = 'gs' @@ -101,6 +107,7 @@ class PdfController(PresentationController): """ log.debug('check_installed Pdf') self.mudrawbin = '' + self.mutoolbin = '' self.gsbin = '' self.also_supports = [] # Use the user defined program if given @@ -111,27 +118,36 @@ class PdfController(PresentationController): 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 in the base folder + # 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 mupdf + # First try to find mudraw self.mudrawbin = which('mudraw') - # if mupdf isn't installed, fallback to ghostscript + # if mudraw isn't installed, try mutool 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: + self.mutoolbin = which('mutool') + # Check we got a working mutool + if not self.mutoolbin or self.process_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') - if self.mudrawbin: + 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: @@ -238,10 +254,18 @@ class PdfDocument(PresentationDocument): if not os.path.isdir(self.get_temp_folder()): os.makedirs(self.get_temp_folder()) if self.controller.mudrawbin: + log.debug('loading presentation using mudraw') runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()), '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], startupinfo=self.startupinfo) + elif self.controller.mutoolbin: + log.debug('loading presentation using mutool') + runlog = check_output([self.controller.mutoolbin, 'draw', '-w', str(size.width()), '-h', + str(size.height()), + '-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path], + startupinfo=self.startupinfo) elif self.controller.gsbin: + log.debug('loading presentation using gs') resolution = self.gs_get_resolution(size) runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m', '-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4', diff --git a/openlp/plugins/presentations/lib/presentationtab.py b/openlp/plugins/presentations/lib/presentationtab.py index cbe881853..8076b33fe 100644 --- a/openlp/plugins/presentations/lib/presentationtab.py +++ b/openlp/plugins/presentations/lib/presentationtab.py @@ -235,7 +235,7 @@ class PresentationTab(SettingsTab): self, translate('PresentationPlugin.PresentationTab', 'Select mudraw or ghostscript binary.'), self.pdf_program_path.text()) if filename: - program_type = PdfController.check_binary(filename) + program_type = PdfController.process_check_binary(filename) if not program_type: critical_error_message_box(UiStrings().Error, translate('PresentationPlugin.PresentationTab', diff --git a/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py b/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py index 79b907230..f73655dc7 100644 --- a/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py +++ b/tests/functional/openlp_plugins/presentations/test_pdfcontroller.py @@ -29,7 +29,7 @@ from tempfile import mkdtemp from PyQt5 import QtCore, QtGui from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument -from tests.functional import MagicMock +from tests.functional import MagicMock, patch from openlp.core.common import Settings from openlp.core.lib import ScreenList from tests.utils.constants import TEST_RESOURCES_PATH @@ -137,3 +137,74 @@ class TestPdfController(TestCase, TestMixin): else: self.assertEqual(768, image.height(), 'The height should be 768') self.assertEqual(543, image.width(), 'The width should be 543') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_mudraw_test(self, mocked_check_binary_exists): + """ + Test that the correct output from mudraw is detected + """ + # GIVEN: A mocked check_binary_exists that returns mudraw output + mudraw_output = (b'usage: mudraw [options] input [pages]\n\t-o -\toutput filename (%d for page number)n\t\tsupp' + b'orted formats: pgm, ppm, pam, png, pbmn\t-p -\tpasswordn\t-r -\tresolution in dpi (default: ' + b'72)n\t-w -\twidth (in pixels) (maximum width if -r is specified)n\t-h -\theight (in pixels) ' + b'(maximum height if -r is specified)') + mocked_check_binary_exists.return_value = mudraw_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mudraw should be detected + self.assertEqual('mudraw', ret, 'mudraw should have been detected') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_new_motool_test(self, mocked_check_binary_exists): + """ + Test that the correct output from the new mutool is detected + """ + # GIVEN: A mocked check_binary_exists that returns new mutool output + new_mutool_output = (b'usage: mutool [options]\n\tdraw\t-- convert document\n\trun\t-- run javascript' + b'\n\tclean\t-- rewrite pdf file\n\textract\t-- extract font and image resources\n\tinfo\t' + b'-- show information about pdf resources\n\tpages\t-- show information about pdf pages\n' + b'\tposter\t-- split large page into many tiles\n\tshow\t-- show internal pdf objects\n\t' + b'create\t-- create pdf document\n\tmerge\t-- merge pages from multiple pdf sources into a' + b'new pdf\n') + mocked_check_binary_exists.return_value = new_mutool_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mutool should be detected + self.assertEqual('mutool', ret, 'mutool should have been detected') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_old_motool_test(self, mocked_check_binary_exists): + """ + Test that the output from the old mutool is not accepted + """ + # GIVEN: A mocked check_binary_exists that returns old mutool output + old_mutool_output = (b'usage: mutool [options]\n\tclean\t-- rewrite pdf file\n\textract\t-- extract ' + b'font and image resources\n\tinfo\t-- show information about pdf resources\n\tposter\t-- ' + b'split large page into many tiles\n\tshow\t-- show internal pdf objects') + mocked_check_binary_exists.return_value = old_mutool_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mutool should be detected + self.assertIsNone(ret, 'old mutool should not be accepted!') + + @patch('openlp.plugins.presentations.lib.pdfcontroller.check_binary_exists') + def process_check_binary_gs_test(self, mocked_check_binary_exists): + """ + Test that the correct output from gs is detected + """ + # GIVEN: A mocked check_binary_exists that returns gs output + gs_output = (b'GPL Ghostscript 9.19 (2016-03-23)\nCopyright (C) 2016 Artifex Software, Inc. All rights reserv' + b'ed.\nUsage: gs [switches] [file1.ps file2.ps ...]') + mocked_check_binary_exists.return_value = gs_output + + # WHEN: Calling process_check_binary + ret = PdfController.process_check_binary('test') + + # THEN: mutool should be detected + self.assertEqual('gs', ret, 'mutool should have been detected')