Added possible to point to a binary to use for pdf-processing.

This commit is contained in:
Tomas Groth 2013-08-04 20:51:22 +01:00
parent 308d5ed5ee
commit d28d75a2ce
5 changed files with 158 additions and 15 deletions

View File

@ -249,8 +249,6 @@ class PresentationMediaItem(MediaManagerItem):
file_type = os.path.splitext(filename)[1][1:] file_type = os.path.splitext(filename)[1][1:]
if not self.display_type_combo_box.currentText(): if not self.display_type_combo_box.currentText():
return False return False
service_item.processor = self.display_type_combo_box.currentText()
if context == ServiceItemContext.Live and (file_type == u'pdf' or file_type == u'xps'): if context == ServiceItemContext.Live and (file_type == u'pdf' or file_type == u'xps'):
service_item.add_capability(ItemCapabilities.CanMaintain) service_item.add_capability(ItemCapabilities.CanMaintain)
@ -266,12 +264,11 @@ class PresentationMediaItem(MediaManagerItem):
(path, name) = os.path.split(filename) (path, name) = os.path.split(filename)
service_item.title = name service_item.title = name
if os.path.exists(filename): if os.path.exists(filename):
if service_item.processor == self.Automatic: processor = self.findControllerByType(filename)
service_item.processor = self.findControllerByType(filename) if not processor:
if not service_item.processor: return False
return False controller = self.controllers[processor]
controller = self.controllers[service_item.processor] service_item.processor = None
#service_item.processor = None
doc = controller.add_document(filename) doc = controller.add_document(filename)
if doc.get_thumbnail_path(1, True) is None: if doc.get_thumbnail_path(1, True) is None:
doc.load_presentation() doc.load_presentation()
@ -300,6 +297,7 @@ class PresentationMediaItem(MediaManagerItem):
translate('PresentationPlugin.MediaItem', 'The presentation %s no longer exists.') % filename) translate('PresentationPlugin.MediaItem', 'The presentation %s no longer exists.') % filename)
return False return False
else: else:
service_item.processor = self.display_type_combo_box.currentText()
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay) service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
# Why the loop when we above return False if len(items) is > 1? # Why the loop when we above return False if len(items) is > 1?

View File

@ -324,7 +324,12 @@ class MessageListener(object):
controller = self.live_handler controller = self.live_handler
else: else:
controller = self.preview_handler controller = self.preview_handler
controller.add_handler(self.controllers[self.handler], file, hide_mode, message[3]) # when presenting PDF, we're using the image presentation code,
# so handler & processor is set to None, and we skip adding the handler.
if self.handler == None:
self.controller = controller
else:
controller.add_handler(self.controllers[self.handler], file, hide_mode, message[3])
def slide(self, message): def slide(self, message):
""" """

View File

@ -31,16 +31,40 @@ import os
import logging import logging
from tempfile import NamedTemporaryFile from tempfile import NamedTemporaryFile
import re import re
from subprocess import check_output, CalledProcessError from subprocess import check_output, CalledProcessError, STDOUT
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.utils import AppLocation from openlp.core.utils import AppLocation
from openlp.core.lib import ScreenList from openlp.core.lib import ScreenList, Settings
from presentationcontroller import PresentationController, PresentationDocument from presentationcontroller import PresentationController, PresentationDocument
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
def check_binary(program_path):
"""
Function that checks whether a binary is either ghostscript or mudraw or neither.
"""
program_type = None
runlog = u''
try:
runlog = check_output([program_path, u'--help'], stderr=STDOUT)
except CalledProcessError as e:
runlog = e.output
except Exception:
runlog = u''
# Analyse the output to see it the program is mudraw, ghostscript or neither
for line in runlog.splitlines():
found_mudraw = re.search(u'usage: mudraw.*', line)
if found_mudraw:
program_type = u'mudraw'
break
found_gs = re.search(u'GPL Ghostscript.*', line)
if found_gs:
program_type = u'gs'
break
return program_type
class PdfController(PresentationController): class PdfController(PresentationController):
""" """
@ -72,8 +96,20 @@ class PdfController(PresentationController):
""" """
Check the viewer is installed. Check the viewer is installed.
""" """
application_path = AppLocation.get_directory(AppLocation.AppDir)
log.debug(u'check_installed Pdf') log.debug(u'check_installed Pdf')
# Use the user defined program if given
if (Settings().value(u'presentations/enable_given_pdf_program')):
given_pdf_program = Settings().value(u'presentations/given_pdf_program')
type = check_binary(given_pdf_program)
if type == u'gs':
self.gsbin = given_pdf_program
return True
elif type == u'mudraw':
self.mudrawbin = given_pdf_program
return True
# Fallback to autodetection
application_path = AppLocation.get_directory(AppLocation.AppDir)
if os.name != u'nt': if os.name != u'nt':
# First try to find mupdf # First try to find mupdf
try: try:
@ -153,7 +189,12 @@ quit \n\
tmpfile.close() tmpfile.close()
# Run the script on the pdf to get the size # Run the script on the pdf to get the size
runlog = check_output([self.controller.gsbin, u'-dNOPAUSE', u'-dNODISPLAY', u'-dBATCH', u'-sFile=' + self.filepath, tmpfile.name]) runlog = []
try:
runlog = check_output([self.controller.gsbin, u'-dNOPAUSE', u'-dNODISPLAY', u'-dBATCH', u'-sFile=' + self.filepath, tmpfile.name])
except CalledProcessError as e:
log.debug(u' '.join(e.cmd))
log.debug(e.output)
os.unlink(tmpfile.name) os.unlink(tmpfile.name)
# Extract the pdf resolution from output, the format is " Size: x: <width>, y: <height>" # Extract the pdf resolution from output, the format is " Size: x: <width>, y: <height>"

View File

@ -29,8 +29,9 @@
from PyQt4 import QtGui from PyQt4 import QtGui
from openlp.core.lib import Settings, SettingsTab, UiStrings, translate from openlp.core.lib import Settings, SettingsTab, UiStrings, translate, build_icon
from openlp.core.lib.ui import critical_error_message_box
from pdfcontroller import check_binary
class PresentationTab(SettingsTab): class PresentationTab(SettingsTab):
""" """
@ -63,6 +64,7 @@ class PresentationTab(SettingsTab):
self.presenter_check_boxes[controller.name] = checkbox self.presenter_check_boxes[controller.name] = checkbox
self.controllers_layout.addWidget(checkbox) self.controllers_layout.addWidget(checkbox)
self.left_layout.addWidget(self.controllers_group_box) self.left_layout.addWidget(self.controllers_group_box)
# Advanced
self.advanced_group_box = QtGui.QGroupBox(self.left_column) self.advanced_group_box = QtGui.QGroupBox(self.left_column)
self.advanced_group_box.setObjectName(u'advanced_group_box') self.advanced_group_box.setObjectName(u'advanced_group_box')
self.advanced_layout = QtGui.QVBoxLayout(self.advanced_group_box) self.advanced_layout = QtGui.QVBoxLayout(self.advanced_group_box)
@ -70,7 +72,33 @@ class PresentationTab(SettingsTab):
self.override_app_check_box = QtGui.QCheckBox(self.advanced_group_box) self.override_app_check_box = QtGui.QCheckBox(self.advanced_group_box)
self.override_app_check_box.setObjectName(u'override_app_check_box') self.override_app_check_box.setObjectName(u'override_app_check_box')
self.advanced_layout.addWidget(self.override_app_check_box) self.advanced_layout.addWidget(self.override_app_check_box)
# Pdf options
self.pdf_group_box = QtGui.QGroupBox(self.left_column)
self.pdf_group_box.setObjectName(u'pdf_group_box')
self.pdf_layout = QtGui.QFormLayout(self.pdf_group_box)
self.pdf_layout.setObjectName(u'pdf_layout')
self.pdf_program_check_box = QtGui.QCheckBox(self.pdf_group_box)
self.pdf_program_check_box.setObjectName(u'pdf_program_check_box')
self.pdf_layout.addWidget(self.pdf_program_check_box)
self.pdf_program_path_layout = QtGui.QHBoxLayout()
self.pdf_program_path_layout.setObjectName(u'pdf_program_path_layout')
self.pdf_program_path = QtGui.QLineEdit(self.pdf_group_box)
self.pdf_program_path.setObjectName(u'pdf_program_path')
self.pdf_program_path.setReadOnly(True)
self.pdf_program_path.setPalette(self.get_grey_text_palette(True))
self.pdf_program_path_layout.addWidget(self.pdf_program_path)
self.pdf_program_browse_button = QtGui.QToolButton(self.pdf_group_box)
self.pdf_program_browse_button.setObjectName(u'pdf_program_browse_button')
self.pdf_program_browse_button.setIcon(build_icon(u':/general/general_open.png'))
self.pdf_program_browse_button.setEnabled(False)
self.pdf_program_path_layout.addWidget(self.pdf_program_browse_button)
self.pdf_layout.addRow(self.pdf_program_path_layout)
self.pdf_program_path.editingFinished.connect(self.on_pdf_program_path_edit_finished)
self.pdf_program_browse_button.clicked.connect(self.on_pdf_program_browse_button_clicked)
self.pdf_program_check_box.clicked.connect(self.on_pdf_program_check_box_clicked)
self.left_layout.addWidget(self.advanced_group_box) self.left_layout.addWidget(self.advanced_group_box)
self.left_layout.addWidget(self.pdf_group_box)
self.left_layout.addStretch() self.left_layout.addStretch()
self.right_layout.addStretch() self.right_layout.addStretch()
@ -84,8 +112,12 @@ class PresentationTab(SettingsTab):
checkbox = self.presenter_check_boxes[controller.name] checkbox = self.presenter_check_boxes[controller.name]
self.set_controller_text(checkbox, controller) self.set_controller_text(checkbox, controller)
self.advanced_group_box.setTitle(UiStrings().Advanced) self.advanced_group_box.setTitle(UiStrings().Advanced)
self.pdf_group_box.setTitle(translate('PresentationPlugin.PresentationTab', 'PDF options'))
self.override_app_check_box.setText( self.override_app_check_box.setText(
translate('PresentationPlugin.PresentationTab', 'Allow presentation application to be overridden')) translate('PresentationPlugin.PresentationTab', 'Allow presentation application to be overridden'))
self.pdf_program_check_box.setText(
translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:'))
def set_controller_text(self, checkbox, controller): def set_controller_text(self, checkbox, controller):
if checkbox.isEnabled(): if checkbox.isEnabled():
@ -102,6 +134,15 @@ class PresentationTab(SettingsTab):
checkbox = self.presenter_check_boxes[controller.name] checkbox = self.presenter_check_boxes[controller.name]
checkbox.setChecked(Settings().value(self.settings_section + u'/' + controller.name)) checkbox.setChecked(Settings().value(self.settings_section + u'/' + controller.name))
self.override_app_check_box.setChecked(Settings().value(self.settings_section + u'/override app')) self.override_app_check_box.setChecked(Settings().value(self.settings_section + u'/override app'))
# load pdf-program settings
enable_given_pdf_program = Settings().value(self.settings_section + u'/enable_given_pdf_program')
self.pdf_program_check_box.setChecked(enable_given_pdf_program)
self.pdf_program_path.setReadOnly(not enable_given_pdf_program)
self.pdf_program_path.setPalette(self.get_grey_text_palette(not enable_given_pdf_program))
self.pdf_program_browse_button.setEnabled(enable_given_pdf_program)
pdf_program = Settings().value(self.settings_section + u'/given_pdf_program')
if pdf_program:
self.pdf_program_path.setText(pdf_program)
def save(self): def save(self):
""" """
@ -127,10 +168,25 @@ class PresentationTab(SettingsTab):
if Settings().value(setting_key) != self.override_app_check_box.checkState(): if Settings().value(setting_key) != self.override_app_check_box.checkState():
Settings().setValue(setting_key, self.override_app_check_box.checkState()) Settings().setValue(setting_key, self.override_app_check_box.checkState())
changed = True changed = True
# Save pdf-settings
pdf_program = self.pdf_program_path.text()
enable_given_pdf_program = self.pdf_program_check_box.checkState()
# If the given program is blank disable using the program
if pdf_program == u'':
enable_given_pdf_program = 0
if pdf_program != Settings().value(self.settings_section + u'/given_pdf_program'):
Settings().setValue(self.settings_section + u'/given_pdf_program', pdf_program)
changed = True
if enable_given_pdf_program != Settings().value(self.settings_section + u'/enable_given_pdf_program'):
Settings().setValue(self.settings_section + u'/enable_given_pdf_program', enable_given_pdf_program)
changed = True
if changed: if changed:
self.settings_form.register_post_process(u'mediaitem_suffix_reset') self.settings_form.register_post_process(u'mediaitem_suffix_reset')
self.settings_form.register_post_process(u'mediaitem_presentation_rebuild') self.settings_form.register_post_process(u'mediaitem_presentation_rebuild')
self.settings_form.register_post_process(u'mediaitem_suffixes') self.settings_form.register_post_process(u'mediaitem_suffixes')
def tab_visible(self): def tab_visible(self):
""" """
@ -142,3 +198,44 @@ class PresentationTab(SettingsTab):
checkbox = self.presenter_check_boxes[controller.name] checkbox = self.presenter_check_boxes[controller.name]
checkbox.setEnabled(controller.is_available()) checkbox.setEnabled(controller.is_available())
self.set_controller_text(checkbox, controller) self.set_controller_text(checkbox, controller)
def on_pdf_program_path_edit_finished(self):
"""
After selecting/typing in a program it is validated that it is a actually ghostscript or mudraw
"""
type = None
if self.pdf_program_path.text() != u'':
type = check_binary(self.pdf_program_path.text())
if not type:
critical_error_message_box(UiStrings().Error,
translate('PresentationPlugin.PresentationTab', 'The program is not ghostscript or mudraw which is required.'))
self.pdf_program_path.setFocus()
def on_pdf_program_browse_button_clicked(self):
"""
Select the mudraw or ghostscript binary that should be used.
"""
filename = QtGui.QFileDialog.getOpenFileName(self, translate('PresentationPlugin.PresentationTab', 'Select mudraw or ghostscript binary.'))
if filename:
self.pdf_program_path.setText(filename)
self.pdf_program_path.setFocus()
def on_pdf_program_check_box_clicked(self, checked):
"""
When checkbox for manual entering pdf-program is clicked,
enable or disable the textbox for the programpath and the browse-button.
"""
self.pdf_program_path.setReadOnly(not checked)
self.pdf_program_path.setPalette(self.get_grey_text_palette(not checked))
self.pdf_program_browse_button.setEnabled(checked)
def get_grey_text_palette(self, greyed):
"""
Returns a QPalette with greyed out text as used for placeholderText.
"""
palette = QtGui.QPalette()
color = self.palette().color(QtGui.QPalette.Active, QtGui.QPalette.Text)
if greyed:
color.setAlpha(128)
palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Text, color)
return palette

View File

@ -45,6 +45,8 @@ log = logging.getLogger(__name__)
__default_settings__ = { __default_settings__ = {
u'presentations/override app': QtCore.Qt.Unchecked, u'presentations/override app': QtCore.Qt.Unchecked,
u'presentations/enable_given_pdf_program': QtCore.Qt.Unchecked,
u'presentations/given_pdf_program': u'',
u'presentations/Impress': QtCore.Qt.Checked, u'presentations/Impress': QtCore.Qt.Checked,
u'presentations/Powerpoint': QtCore.Qt.Checked, u'presentations/Powerpoint': QtCore.Qt.Checked,
u'presentations/Powerpoint Viewer': QtCore.Qt.Checked, u'presentations/Powerpoint Viewer': QtCore.Qt.Checked,