openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #21559
[Merge] lp:~tomasgroth/openlp/mupdf into lp:openlp
Tomas Groth has proposed merging lp:~tomasgroth/openlp/mupdf into lp:openlp.
Requested reviews:
OpenLP Core (openlp-core)
For more details, see:
https://code.launchpad.net/~tomasgroth/openlp/mupdf/+merge/182009
Support for presenting PDF using mupdf or ghostscript.
--
https://code.launchpad.net/~tomasgroth/openlp/mupdf/+merge/182009
Your team OpenLP Core is requested to review the proposed merge of lp:~tomasgroth/openlp/mupdf into lp:openlp.
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2013-07-17 21:07:52 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2013-08-25 20:30:40 +0000
@@ -244,45 +244,90 @@
items = self.list_view.selectedItems()
if len(items) > 1:
return False
- service_item.processor = self.display_type_combo_box.currentText()
- service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
+
+ filename = items[0].data(QtCore.Qt.UserRole)
+ file_type = os.path.splitext(filename)[1][1:]
if not self.display_type_combo_box.currentText():
return False
- for bitem in items:
- filename = bitem.data(QtCore.Qt.UserRole)
- (path, name) = os.path.split(filename)
- service_item.title = name
- if os.path.exists(filename):
- if service_item.processor == self.Automatic:
- service_item.processor = self.findControllerByType(filename)
- if not service_item.processor:
+
+ 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.CanPreview)
+ service_item.add_capability(ItemCapabilities.CanLoop)
+ service_item.add_capability(ItemCapabilities.CanAppend)
+ # force a nonexistent theme
+ service_item.theme = -1
+
+ # Why the loop when we above return False if len(items) is > 1?
+ for bitem in items:
+ filename = bitem.data(QtCore.Qt.UserRole)
+ (path, name) = os.path.split(filename)
+ service_item.title = name
+ if os.path.exists(filename):
+ processor = self.findControllerByType(filename)
+ if not processor:
return False
- controller = self.controllers[service_item.processor]
- doc = controller.add_document(filename)
- if doc.get_thumbnail_path(1, True) is None:
- doc.load_presentation()
- i = 1
- img = doc.get_thumbnail_path(i, True)
- if img:
- while img:
- service_item.add_from_command(path, name, img)
+ controller = self.controllers[processor]
+ service_item.processor = None
+ doc = controller.add_document(filename)
+ if doc.get_thumbnail_path(1, True) is None or not os.path.isfile(os.path.join(doc.get_temp_folder(), u'mainslide001.png')):
+ doc.load_presentation()
+ i = 1
+ imagefile = u'mainslide%03d.png' % i
+ img = os.path.join(doc.get_temp_folder(), imagefile)
+ while os.path.isfile(img):
+ service_item.add_from_image(img, name)
i += 1
- img = doc.get_thumbnail_path(i, True)
+ imagefile = u'mainslide%03d.png' % i
+ img = os.path.join(doc.get_temp_folder(), imagefile)
doc.close_presentation()
return True
else:
# File is no longer present
if not remote:
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
- translate('PresentationPlugin.MediaItem',
- 'The presentation %s is incomplete, please reload.') % filename)
- return False
- else:
- # File is no longer present
- if not remote:
- critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
- translate('PresentationPlugin.MediaItem', 'The presentation %s no longer exists.') % filename)
- return False
+ translate('PresentationPlugin.MediaItem', 'The presentation %s no longer exists.') % filename)
+ return False
+ else:
+ service_item.processor = self.display_type_combo_box.currentText()
+ service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
+
+ # Why the loop when we above return False if len(items) is > 1?
+ for bitem in items:
+ filename = bitem.data(QtCore.Qt.UserRole)
+ (path, name) = os.path.split(filename)
+ service_item.title = name
+ if os.path.exists(filename):
+ if service_item.processor == self.Automatic:
+ service_item.processor = self.findControllerByType(filename)
+ if not service_item.processor:
+ return False
+ controller = self.controllers[service_item.processor]
+ doc = controller.add_document(filename)
+ if doc.get_thumbnail_path(1, True) is None:
+ doc.load_presentation()
+ i = 1
+ img = doc.get_thumbnail_path(i, True)
+ if img:
+ while img:
+ service_item.add_from_command(path, name, img)
+ i += 1
+ img = doc.get_thumbnail_path(i, True)
+ doc.close_presentation()
+ return True
+ else:
+ # File is no longer present
+ if not remote:
+ critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
+ translate('PresentationPlugin.MediaItem',
+ 'The presentation %s is incomplete, please reload.') % filename)
+ return False
+ else:
+ # File is no longer present
+ if not remote:
+ critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
+ translate('PresentationPlugin.MediaItem', 'The presentation %s no longer exists.') % filename)
+ return False
def findControllerByType(self, filename):
"""
=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py 2013-05-26 17:03:14 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py 2013-08-25 20:30:40 +0000
@@ -324,7 +324,12 @@
controller = self.live_handler
else:
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):
"""
=== added file 'openlp/plugins/presentations/lib/pdfcontroller.py'
--- openlp/plugins/presentations/lib/pdfcontroller.py 1970-01-01 00:00:00 +0000
+++ openlp/plugins/presentations/lib/pdfcontroller.py 2013-08-25 20:30:40 +0000
@@ -0,0 +1,302 @@
+# -*- coding: utf-8 -*-
+# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
+
+###############################################################################
+# OpenLP - Open Source Lyrics Projection #
+# --------------------------------------------------------------------------- #
+# Copyright (c) 2008-2013 Raoul Snyman #
+# Portions copyright (c) 2008-2013 Tim Bentley, Gerald Britton, Jonathan #
+# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
+# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
+# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
+# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
+# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
+# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
+# --------------------------------------------------------------------------- #
+# This program is free software; you can redistribute it and/or modify it #
+# under the terms of the GNU General Public License as published by the Free #
+# Software Foundation; version 2 of the License. #
+# #
+# This program is distributed in the hope that it will be useful, but WITHOUT #
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
+# more details. #
+# #
+# You should have received a copy of the GNU General Public License along #
+# with this program; if not, write to the Free Software Foundation, Inc., 59 #
+# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
+###############################################################################
+
+import os
+import logging
+from tempfile import NamedTemporaryFile
+import re
+from subprocess import check_output, CalledProcessError, STDOUT
+from PyQt4 import QtCore, QtGui
+
+from openlp.core.utils import AppLocation
+from openlp.core.lib import ScreenList, Settings
+from presentationcontroller import PresentationController, PresentationDocument
+
+
+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 to control PDF presentations
+ """
+ log.info(u'PdfController loaded')
+
+ def __init__(self, plugin):
+ """
+ Initialise the class
+ """
+ log.debug(u'Initialising')
+ self.process = None
+ PresentationController.__init__(self, plugin, u'Pdf', PdfDocument)
+ self.supports = [u'pdf']
+ self.mudrawbin = u''
+ self.gsbin = u''
+ if self.check_installed() and self.mudrawbin != u'':
+ self.also_supports = [u'xps']
+
+ def check_available(self):
+ """
+ PdfController is able to run on this machine.
+ """
+ log.debug(u'check_available Pdf')
+ return self.check_installed()
+
+ def check_installed(self):
+ """
+ Check the viewer is installed.
+ """
+ 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':
+ # First try to find mupdf
+ try:
+ self.mudrawbin = check_output([u'which', u'mudraw']).rstrip('\n')
+ except CalledProcessError:
+ self.mudrawbin = u''
+
+ # if mupdf isn't installed, fallback to ghostscript
+ if self.mudrawbin == u'':
+ try:
+ self.gsbin = check_output([u'which', u'gs']).rstrip('\n')
+ except CalledProcessError:
+ self.gsbin = u''
+
+ # Last option: check if mudraw is placed in OpenLP base folder
+ if self.mudrawbin == u'' and self.gsbin == u'':
+ application_path = AppLocation.get_directory(AppLocation.AppDir)
+ if os.path.isfile(application_path + u'/../mudraw'):
+ self.mudrawbin = application_path + u'/../mudraw'
+ else:
+ # for windows we only accept mudraw.exe in the base folder
+ application_path = AppLocation.get_directory(AppLocation.AppDir)
+ if os.path.isfile(application_path + u'/../mudraw.exe'):
+ self.mudrawbin = application_path + u'/../mudraw.exe'
+
+ if self.mudrawbin == u'' and self.gsbin == u'':
+ return False
+ else:
+ return True
+
+ def kill(self):
+ """
+ Called at system exit to clean up any running presentations
+ """
+ log.debug(u'Kill pdfviewer')
+ while self.docs:
+ self.docs[0].close_presentation()
+
+
+class PdfDocument(PresentationDocument):
+ """
+ Class which holds information of a single presentation.
+ """
+ def __init__(self, controller, presentation):
+ """
+ Constructor, store information about the file and initialise.
+ """
+ log.debug(u'Init Presentation Pdf')
+ PresentationDocument.__init__(self, controller, presentation)
+ self.presentation = None
+ self.blanked = False
+ self.hidden = False
+ self.image_files = []
+ self.num_pages = -1
+
+ def gs_get_resolution(self, size):
+ """
+ Only used when using ghostscript
+ Ghostscript can't scale automaticly while keeping aspect like mupdf, so we need
+ to get the ratio bewteen the screen size and the PDF to scale
+ """
+ # Use a postscript script to get size of the pdf. It is assumed that all pages have same size
+ postscript = u'%!PS \n\
+() = \n\
+File dup (r) file runpdfbegin \n\
+1 pdfgetpage dup \n\
+/MediaBox pget { \n\
+aload pop exch 4 1 roll exch sub 3 1 roll sub \n\
+( Size: x: ) print =print (, y: ) print =print (\n) print \n\
+} if \n\
+flush \n\
+quit \n\
+'
+ # Put postscript into tempfile
+ tmpfile = NamedTemporaryFile(delete=False)
+ tmpfile.write(postscript)
+ tmpfile.close()
+
+ # Run the script on the pdf to get the size
+ 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)
+
+ # Extract the pdf resolution from output, the format is " Size: x: <width>, y: <height>"
+ width = 0
+ height = 0
+ for line in runlog.splitlines():
+ try:
+ width = re.search(u'.*Size: x: (\d+\.?\d*), y: \d+.*', line).group(1)
+ height = re.search(u'.*Size: x: \d+\.?\d*, y: (\d+\.?\d*).*', line).group(1)
+ break;
+ except AttributeError:
+ pass
+
+ # Calculate the ratio from pdf to screen
+ if width > 0 and height > 0:
+ width_ratio = size.right() / float(width)
+ height_ratio = size.bottom() / float(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 load_presentation(self):
+ """
+ Called when a presentation is added to the SlideController. It generates images from the PDF.
+ """
+ log.debug(u'load_presentation pdf')
+
+ # Check if the images has already been created, and if yes load them
+ if os.path.isfile(os.path.join(self.get_temp_folder(), u'mainslide001.png')):
+ created_files = sorted(os.listdir(self.get_temp_folder()))
+ for fn in created_files:
+ if os.path.isfile(os.path.join(self.get_temp_folder(), fn)):
+ self.image_files.append(os.path.join(self.get_temp_folder(), fn))
+ self.num_pages = len(self.image_files)
+ return True
+
+ size = ScreenList().current[u'size']
+ # Generate images from PDF that will fit the frame.
+ runlog = u''
+ try:
+ if not os.path.isdir(self.get_temp_folder()):
+ os.makedirs(self.get_temp_folder())
+ if self.controller.mudrawbin != u'':
+ runlog = check_output([self.controller.mudrawbin, u'-w', str(size.right()), u'-h', str(size.bottom()), u'-o', os.path.join(self.get_temp_folder(), u'mainslide%03d.png'), self.filepath])
+ elif self.controller.gsbin != u'':
+ resolution = self.gs_get_resolution(size)
+ runlog = check_output([self.controller.gsbin, u'-dSAFER', u'-dNOPAUSE', u'-dBATCH', u'-sDEVICE=png16m', u'-r' + str(resolution), u'-dTextAlphaBits=4', u'-dGraphicsAlphaBits=4', u'-sOutputFile=' + os.path.join(self.get_temp_folder(), u'mainslide%03d.png'), self.filepath])
+ created_files = sorted(os.listdir(self.get_temp_folder()))
+ for fn in created_files:
+ if os.path.isfile(os.path.join(self.get_temp_folder(), fn)):
+ self.image_files.append(os.path.join(self.get_temp_folder(), fn))
+ except Exception as e:
+ log.debug(e)
+ log.debug(runlog)
+ return False
+ self.num_pages = len(self.image_files)
+
+ # Create thumbnails
+ self.create_thumbnails()
+ return True
+
+ def create_thumbnails(self):
+ """
+ Generates thumbnails
+ """
+ log.debug(u'create_thumbnails pdf')
+ if self.check_thumbnails():
+ return
+ log.debug(u'create_thumbnails proceeding')
+
+ # use builtin function to create thumbnails from generated images
+ index = 1
+ for image in self.image_files:
+ self.convert_thumbnail(image, index)
+ index += 1
+
+ def close_presentation(self):
+ """
+ Close presentation and clean up objects. Triggered by new object being added to SlideController or OpenLP being
+ shut down.
+ """
+ log.debug(u'close_presentation pdf')
+ self.controller.remove_doc(self)
+
+ def is_loaded(self):
+ """
+ Returns true if a presentation is loaded.
+ """
+ log.debug(u'is_loaded pdf')
+ if self.num_pages < 0:
+ return False
+ return True
+
+ def is_active(self):
+ """
+ Returns true if a presentation is currently active.
+ """
+ log.debug(u'is_active pdf')
+ return self.is_loaded() and not self.hidden
+
=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
--- openlp/plugins/presentations/lib/presentationtab.py 2013-04-19 18:52:39 +0000
+++ openlp/plugins/presentations/lib/presentationtab.py 2013-08-25 20:30:40 +0000
@@ -29,8 +29,9 @@
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):
"""
@@ -63,6 +64,7 @@
self.presenter_check_boxes[controller.name] = checkbox
self.controllers_layout.addWidget(checkbox)
self.left_layout.addWidget(self.controllers_group_box)
+ # Advanced
self.advanced_group_box = QtGui.QGroupBox(self.left_column)
self.advanced_group_box.setObjectName(u'advanced_group_box')
self.advanced_layout = QtGui.QVBoxLayout(self.advanced_group_box)
@@ -70,7 +72,33 @@
self.override_app_check_box = QtGui.QCheckBox(self.advanced_group_box)
self.override_app_check_box.setObjectName(u'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.pdf_group_box)
self.left_layout.addStretch()
self.right_layout.addStretch()
@@ -84,8 +112,12 @@
checkbox = self.presenter_check_boxes[controller.name]
self.set_controller_text(checkbox, controller)
self.advanced_group_box.setTitle(UiStrings().Advanced)
+ self.pdf_group_box.setTitle(translate('PresentationPlugin.PresentationTab', 'PDF options'))
self.override_app_check_box.setText(
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):
if checkbox.isEnabled():
@@ -102,6 +134,15 @@
checkbox = self.presenter_check_boxes[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'))
+ # 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):
"""
@@ -127,10 +168,25 @@
if Settings().value(setting_key) != self.override_app_check_box.checkState():
Settings().setValue(setting_key, self.override_app_check_box.checkState())
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:
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_suffixes')
+
def tab_visible(self):
"""
@@ -142,3 +198,44 @@
checkbox = self.presenter_check_boxes[controller.name]
checkbox.setEnabled(controller.is_available())
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
=== modified file 'openlp/plugins/presentations/presentationplugin.py'
--- openlp/plugins/presentations/presentationplugin.py 2013-05-24 20:17:47 +0000
+++ openlp/plugins/presentations/presentationplugin.py 2013-08-25 20:30:40 +0000
@@ -45,9 +45,12 @@
__default_settings__ = {
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/Powerpoint': QtCore.Qt.Checked,
u'presentations/Powerpoint Viewer': QtCore.Qt.Checked,
+ u'presentations/Pdf': QtCore.Qt.Checked,
u'presentations/presentations files': []
}
=== modified file 'resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py'
--- resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py 2013-07-18 19:28:35 +0000
+++ resources/pyinstaller/hook-openlp.plugins.presentations.presentationplugin.py 2013-08-25 20:30:40 +0000
@@ -29,4 +29,5 @@
hiddenimports = ['openlp.plugins.presentations.lib.impresscontroller',
'openlp.plugins.presentations.lib.powerpointcontroller',
- 'openlp.plugins.presentations.lib.pptviewcontroller']
+ 'openlp.plugins.presentations.lib.pptviewcontroller',
+ 'openlp.plugins.presentations.lib.pdfcontroller']
Follow ups