forked from openlp/openlp
Merge branch 'master' into 'master'
Clean PDF Controller and its tests See merge request openlp/openlp!245
This commit is contained in:
commit
b367015342
@ -30,7 +30,7 @@ install:
|
|||||||
# Update pip
|
# Update pip
|
||||||
- python -m pip install --upgrade pip
|
- python -m pip install --upgrade pip
|
||||||
# Install generic dependencies from pypi
|
# Install generic dependencies from pypi
|
||||||
- python -m pip install sqlalchemy alembic appdirs chardet beautifulsoup4 lxml Mako mysql-connector-python pytest mock psycopg2-binary websockets asyncio waitress six webob requests QtAwesome PyQt5 PyQtWebEngine pymediainfo PyMuPDF==1.16.7 QDarkStyle python-vlc Pyro4 zeroconf flask-cors pytest-qt pyenchant pysword
|
- python -m pip install sqlalchemy alembic appdirs chardet beautifulsoup4 lxml Mako mysql-connector-python pytest mock psycopg2-binary websockets asyncio waitress six webob requests QtAwesome PyQt5 PyQtWebEngine pymediainfo PyMuPDF QDarkStyle python-vlc Pyro4 zeroconf flask-cors pytest-qt pyenchant pysword
|
||||||
# Install Windows only dependencies
|
# Install Windows only dependencies
|
||||||
- cmd: python -m pip install pyodbc pypiwin32
|
- cmd: python -m pip install pyodbc pypiwin32
|
||||||
# Mac only dependencies
|
# Mac only dependencies
|
||||||
|
@ -31,7 +31,6 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
from ipaddress import IPv4Address, IPv6Address, AddressValueError
|
from ipaddress import IPv4Address, IPv6Address, AddressValueError
|
||||||
from shutil import which
|
from shutil import which
|
||||||
from subprocess import check_output, CalledProcessError, STDOUT
|
|
||||||
|
|
||||||
from PyQt5 import QtGui
|
from PyQt5 import QtGui
|
||||||
from PyQt5.QtCore import QCryptographicHash as QHash
|
from PyQt5.QtCore import QCryptographicHash as QHash
|
||||||
@ -472,33 +471,6 @@ def clean_filename(filename):
|
|||||||
return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename))
|
return INVALID_FILE_CHARS.sub('_', CONTROL_CHARS.sub('', filename))
|
||||||
|
|
||||||
|
|
||||||
def check_binary_exists(program_path):
|
|
||||||
"""
|
|
||||||
Function that checks whether a binary exists.
|
|
||||||
|
|
||||||
:param pathlib.Path program_path: The full path to the binary to check.
|
|
||||||
:return: program output to be parsed
|
|
||||||
:rtype: bytes
|
|
||||||
"""
|
|
||||||
log.debug('testing program_path: {text}'.format(text=program_path))
|
|
||||||
try:
|
|
||||||
# Setup startupinfo options for check_output to avoid console popping up on windows
|
|
||||||
if is_win():
|
|
||||||
from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW
|
|
||||||
startupinfo = STARTUPINFO()
|
|
||||||
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
|
||||||
else:
|
|
||||||
startupinfo = None
|
|
||||||
run_log = check_output([str(program_path), '--help'], stderr=STDOUT, startupinfo=startupinfo)
|
|
||||||
except CalledProcessError as e:
|
|
||||||
run_log = e.output
|
|
||||||
except Exception:
|
|
||||||
trace_error_handler(log)
|
|
||||||
run_log = ''
|
|
||||||
log.debug('check_output returned: {text}'.format(text=run_log))
|
|
||||||
return run_log
|
|
||||||
|
|
||||||
|
|
||||||
def get_file_encoding(file_path):
|
def get_file_encoding(file_path):
|
||||||
"""
|
"""
|
||||||
Utility function to incrementally detect the file encoding.
|
Utility function to incrementally detect the file encoding.
|
||||||
|
@ -20,14 +20,10 @@
|
|||||||
##########################################################################
|
##########################################################################
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from openlp.core.common import is_win
|
|
||||||
from openlp.core.display.screens import ScreenList
|
from openlp.core.display.screens import ScreenList
|
||||||
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
|
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
|
||||||
|
|
||||||
|
|
||||||
if is_win():
|
|
||||||
from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import fitz
|
import fitz
|
||||||
PYMUPDF_AVAILABLE = True
|
PYMUPDF_AVAILABLE = True
|
||||||
@ -55,31 +51,16 @@ class PdfController(PresentationController):
|
|||||||
super(PdfController, self).__init__(plugin, 'Pdf', PdfDocument)
|
super(PdfController, self).__init__(plugin, 'Pdf', PdfDocument)
|
||||||
self.process = None
|
self.process = None
|
||||||
self.supports = ['pdf']
|
self.supports = ['pdf']
|
||||||
self.also_supports = []
|
self.also_supports = ['xps', 'oxps', 'epub', 'cbz', 'fb2']
|
||||||
# Determine whether mudraw or ghostscript is used
|
|
||||||
self.check_installed()
|
|
||||||
|
|
||||||
def check_available(self):
|
def check_available(self):
|
||||||
"""
|
"""
|
||||||
PdfController is able to run on this machine.
|
PdfController is able to run on this machine.
|
||||||
|
|
||||||
:return: True if program to open PDF-files was found, otherwise False.
|
:return: True if PyMuPDF is installed, otherwise False.
|
||||||
"""
|
"""
|
||||||
log.debug('check_available Pdf')
|
log.debug('check_available Pdf')
|
||||||
return self.check_installed()
|
return PYMUPDF_AVAILABLE
|
||||||
|
|
||||||
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.also_supports = []
|
|
||||||
if PYMUPDF_AVAILABLE:
|
|
||||||
self.also_supports = ['xps', 'oxps', 'epub', 'cbz', 'fb2']
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def kill(self):
|
def kill(self):
|
||||||
"""
|
"""
|
||||||
@ -111,12 +92,6 @@ class PdfDocument(PresentationDocument):
|
|||||||
self.hidden = False
|
self.hidden = False
|
||||||
self.image_files = []
|
self.image_files = []
|
||||||
self.num_pages = -1
|
self.num_pages = -1
|
||||||
# Setup startupinfo options for check_output to avoid console popping up on windows
|
|
||||||
if is_win():
|
|
||||||
self.startupinfo = STARTUPINFO()
|
|
||||||
self.startupinfo.dwFlags |= STARTF_USESHOWWINDOW
|
|
||||||
else:
|
|
||||||
self.startupinfo = None
|
|
||||||
|
|
||||||
def load_presentation(self):
|
def load_presentation(self):
|
||||||
"""
|
"""
|
||||||
|
@ -58,7 +58,6 @@ LINUX_MODULES = [
|
|||||||
# Optical drive detection.
|
# Optical drive detection.
|
||||||
'dbus',
|
'dbus',
|
||||||
'distro',
|
'distro',
|
||||||
'Xlib',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
MACOSX_MODULES = [
|
MACOSX_MODULES = [
|
||||||
|
1
setup.py
1
setup.py
@ -138,7 +138,6 @@ using a computer and a data projector.""",
|
|||||||
'pysword',
|
'pysword',
|
||||||
'pytest',
|
'pytest',
|
||||||
'pytest-qt',
|
'pytest-qt',
|
||||||
'python-xlib; platform_system=="Linux"',
|
|
||||||
'flake8',
|
'flake8',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -26,12 +26,10 @@ import pytest
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
from unittest import skipIf
|
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui
|
from PyQt5 import QtCore, QtGui
|
||||||
|
|
||||||
from openlp.core.common import is_macosx, is_linux, is_win
|
|
||||||
from openlp.core.display.screens import ScreenList
|
from openlp.core.display.screens import ScreenList
|
||||||
from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument
|
from openlp.plugins.presentations.lib.pdfcontroller import PdfController, PdfDocument
|
||||||
from tests.utils.constants import RESOURCE_PATH
|
from tests.utils.constants import RESOURCE_PATH
|
||||||
@ -47,41 +45,11 @@ def pdf_env(settings, mock_plugin, mocked_qapp):
|
|||||||
mocked_qapp.primaryScreen = MagicMock()
|
mocked_qapp.primaryScreen = MagicMock()
|
||||||
mocked_qapp.primaryScreen.return_value = mocked_screen
|
mocked_qapp.primaryScreen.return_value = mocked_screen
|
||||||
ScreenList.create(mocked_qapp)
|
ScreenList.create(mocked_qapp)
|
||||||
yield settings, mock_plugin, temp_folder_path, thumbnail_folder_path
|
yield mock_plugin, temp_folder_path, thumbnail_folder_path
|
||||||
rmtree(thumbnail_folder_path)
|
rmtree(thumbnail_folder_path)
|
||||||
rmtree(temp_folder_path)
|
rmtree(temp_folder_path)
|
||||||
|
|
||||||
|
|
||||||
SCREEN = {
|
|
||||||
'primary': False,
|
|
||||||
'number': 1,
|
|
||||||
'size': QtCore.QRect(0, 0, 1024, 768)
|
|
||||||
}
|
|
||||||
IS_CI = 'GITLAB_CI' in os.environ or 'APPVEYOR' in os.environ
|
|
||||||
IS_QT_QPA_PLATFORM_OFFSCREEN = 'QT_QPA_PLATFORM' in os.environ and os.environ['QT_QPA_PLATFORM'] == 'offscreen'
|
|
||||||
|
|
||||||
|
|
||||||
def get_screen_resolution():
|
|
||||||
"""
|
|
||||||
Get the screen resolution
|
|
||||||
"""
|
|
||||||
if is_macosx():
|
|
||||||
# Magic numbers... don't ask me why
|
|
||||||
return 1024, 768
|
|
||||||
elif is_win():
|
|
||||||
from win32api import GetSystemMetrics
|
|
||||||
return GetSystemMetrics(0), GetSystemMetrics(1)
|
|
||||||
elif is_linux():
|
|
||||||
if IS_CI:
|
|
||||||
return 1024, 768
|
|
||||||
else:
|
|
||||||
from Xlib.display import Display
|
|
||||||
resolution = Display().screen().root.get_geometry()
|
|
||||||
return resolution.width, resolution.height
|
|
||||||
else:
|
|
||||||
return 1024, 768
|
|
||||||
|
|
||||||
|
|
||||||
def test_constructor(settings, mock_plugin):
|
def test_constructor(settings, mock_plugin):
|
||||||
"""
|
"""
|
||||||
Test the Constructor from the PdfController
|
Test the Constructor from the PdfController
|
||||||
@ -104,9 +72,9 @@ def load_pdf(pdf_env):
|
|||||||
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
|
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
|
||||||
|
|
||||||
# WHEN: The Pdf is loaded
|
# WHEN: The Pdf is loaded
|
||||||
mock_plugin = pdf_env[1]
|
mock_plugin = pdf_env[0]
|
||||||
temp_folder_path = pdf_env[2]
|
temp_folder_path = pdf_env[1]
|
||||||
thumbnail_folder_path = pdf_env[3]
|
thumbnail_folder_path = pdf_env[2]
|
||||||
controller = PdfController(plugin=mock_plugin)
|
controller = PdfController(plugin=mock_plugin)
|
||||||
controller.temp_folder = temp_folder_path
|
controller.temp_folder = temp_folder_path
|
||||||
controller.thumbnail_folder = thumbnail_folder_path
|
controller.thumbnail_folder = thumbnail_folder_path
|
||||||
@ -118,7 +86,6 @@ def load_pdf(pdf_env):
|
|||||||
assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.'
|
assert 3 == document.get_slide_count(), 'The pagecount of the PDF should be 3.'
|
||||||
|
|
||||||
|
|
||||||
@skipIf(IS_QT_QPA_PLATFORM_OFFSCREEN, 'This test fails when QT_QPA_PLATFORM is set to "offscreen".')
|
|
||||||
def load_pdf_pictures(pdf_env):
|
def load_pdf_pictures(pdf_env):
|
||||||
"""
|
"""
|
||||||
Test loading a Pdf and check the generated pictures' size
|
Test loading a Pdf and check the generated pictures' size
|
||||||
@ -127,9 +94,9 @@ def load_pdf_pictures(pdf_env):
|
|||||||
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
|
test_file_path = RESOURCE_PATH / 'presentations' / 'pdf_test1.pdf'
|
||||||
|
|
||||||
# WHEN: The Pdf is loaded
|
# WHEN: The Pdf is loaded
|
||||||
mock_plugin = pdf_env[1]
|
mock_plugin = pdf_env[0]
|
||||||
temp_folder_path = pdf_env[2]
|
temp_folder_path = pdf_env[1]
|
||||||
thumbnail_folder_path = pdf_env[3]
|
thumbnail_folder_path = pdf_env[2]
|
||||||
controller = PdfController(plugin=mock_plugin)
|
controller = PdfController(plugin=mock_plugin)
|
||||||
controller.temp_folder = temp_folder_path
|
controller.temp_folder = temp_folder_path
|
||||||
controller.thumbnail_folder = thumbnail_folder_path
|
controller.thumbnail_folder = thumbnail_folder_path
|
||||||
@ -139,9 +106,8 @@ def load_pdf_pictures(pdf_env):
|
|||||||
# THEN: The load should succeed and pictures should be created and have been scaled to fit the screen
|
# THEN: The load should succeed and pictures should be created and have been scaled to fit the screen
|
||||||
assert loaded is True, 'The loading of the PDF should succeed.'
|
assert loaded is True, 'The loading of the PDF should succeed.'
|
||||||
image = QtGui.QImage(os.path.join(str(temp_folder_path), 'pdf_test1.pdf', 'mainslide001.png'))
|
image = QtGui.QImage(os.path.join(str(temp_folder_path), 'pdf_test1.pdf', 'mainslide001.png'))
|
||||||
# Based on the converter used the resolution will differ a bit
|
|
||||||
width, height = get_screen_resolution()
|
|
||||||
# Calculate the width of the PDF based on the aspect ratio of the PDF
|
# Calculate the width of the PDF based on the aspect ratio of the PDF
|
||||||
|
height = 768
|
||||||
width = int(round(height * 0.70703125, 0))
|
width = int(round(height * 0.70703125, 0))
|
||||||
assert image.height() == height, 'The height should be {height}'.format(height=height)
|
assert image.height() == height, 'The height should be {height}'.format(height=height)
|
||||||
assert image.width() == width, 'The width should be {width}'.format(width=width)
|
assert image.width() == width, 'The width should be {width}'.format(width=width)
|
||||||
|
Loading…
Reference in New Issue
Block a user