forked from openlp/openlp
Moved most of the presentation plugin over to pathlib
This commit is contained in:
parent
f0e7381f5c
commit
8ed5903ced
@ -29,9 +29,10 @@ import os
|
|||||||
import re
|
import re
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, Qt, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
from openlp.core.common import translate
|
from openlp.core.common import translate
|
||||||
|
from openlp.core.common.path import Path
|
||||||
|
|
||||||
log = logging.getLogger(__name__ + '.__init__')
|
log = logging.getLogger(__name__ + '.__init__')
|
||||||
|
|
||||||
@ -125,10 +126,11 @@ def build_icon(icon):
|
|||||||
Build a QIcon instance from an existing QIcon, a resource location, or a physical file location. If the icon is a
|
Build a QIcon instance from an existing QIcon, a resource location, or a physical file location. If the icon is a
|
||||||
QIcon instance, that icon is simply returned. If not, it builds a QIcon instance from the resource or file name.
|
QIcon instance, that icon is simply returned. If not, it builds a QIcon instance from the resource or file name.
|
||||||
|
|
||||||
:param icon:
|
:param QtGui.QIcon | Path | QtGui.QIcon | str icon:
|
||||||
The icon to build. This can be a QIcon, a resource string in the form ``:/resource/file.png``, or a file
|
The icon to build. This can be a QIcon, a resource string in the form ``:/resource/file.png``, or a file path
|
||||||
location like ``/path/to/file.png``. However, the **recommended** way is to specify a resource string.
|
location like ``Path(/path/to/file.png)``. However, the **recommended** way is to specify a resource string.
|
||||||
:return: The build icon.
|
:return: The build icon.
|
||||||
|
:rtype: QtGui.QIcon
|
||||||
"""
|
"""
|
||||||
if isinstance(icon, QtGui.QIcon):
|
if isinstance(icon, QtGui.QIcon):
|
||||||
return icon
|
return icon
|
||||||
@ -136,6 +138,8 @@ def build_icon(icon):
|
|||||||
button_icon = QtGui.QIcon()
|
button_icon = QtGui.QIcon()
|
||||||
if isinstance(icon, str):
|
if isinstance(icon, str):
|
||||||
pix_map = QtGui.QPixmap(icon)
|
pix_map = QtGui.QPixmap(icon)
|
||||||
|
elif isinstance(icon, Path):
|
||||||
|
pix_map = QtGui.QPixmap(str(icon))
|
||||||
elif isinstance(icon, QtGui.QImage):
|
elif isinstance(icon, QtGui.QImage):
|
||||||
pix_map = QtGui.QPixmap.fromImage(icon)
|
pix_map = QtGui.QPixmap.fromImage(icon)
|
||||||
if pix_map:
|
if pix_map:
|
||||||
@ -221,10 +225,12 @@ def validate_thumb(file_path, thumb_path):
|
|||||||
:param thumb_path: The path to the thumb.
|
:param thumb_path: The path to the thumb.
|
||||||
:return: True, False if the image has changed since the thumb was created.
|
:return: True, False if the image has changed since the thumb was created.
|
||||||
"""
|
"""
|
||||||
if not os.path.exists(thumb_path):
|
file_path = Path(file_path)
|
||||||
|
thumb_path = Path(thumb_path)
|
||||||
|
if not thumb_path.exists():
|
||||||
return False
|
return False
|
||||||
image_date = os.stat(file_path).st_mtime
|
image_date = file_path.stat().st_mtime
|
||||||
thumb_date = os.stat(thumb_path).st_mtime
|
thumb_date = thumb_path.stat().st_mtime
|
||||||
return image_date <= thumb_date
|
return image_date <= thumb_date
|
||||||
|
|
||||||
|
|
||||||
|
@ -359,10 +359,8 @@ class MediaManagerItem(QtWidgets.QWidget, RegistryProperties):
|
|||||||
:param files: The files to be loaded.
|
:param files: The files to be loaded.
|
||||||
:param target_group: The QTreeWidgetItem of the group that will be the parent of the added files
|
:param target_group: The QTreeWidgetItem of the group that will be the parent of the added files
|
||||||
"""
|
"""
|
||||||
names = []
|
|
||||||
full_list = []
|
full_list = []
|
||||||
for count in range(self.list_view.count()):
|
for count in range(self.list_view.count()):
|
||||||
names.append(self.list_view.item(count).text())
|
|
||||||
full_list.append(self.list_view.item(count).data(QtCore.Qt.UserRole))
|
full_list.append(self.list_view.item(count).data(QtCore.Qt.UserRole))
|
||||||
duplicates_found = False
|
duplicates_found = False
|
||||||
files_added = False
|
files_added = False
|
||||||
|
@ -95,3 +95,20 @@ def rmtree(*args, **kwargs):
|
|||||||
args, kwargs = replace_params(args, kwargs, ((0, 'path', path_to_str),))
|
args, kwargs = replace_params(args, kwargs, ((0, 'path', path_to_str),))
|
||||||
|
|
||||||
return shutil.rmtree(*args, **kwargs)
|
return shutil.rmtree(*args, **kwargs)
|
||||||
|
# TODO: Test and tidy
|
||||||
|
def which(*args, **kwargs):
|
||||||
|
"""
|
||||||
|
Wraps :func:shutil.rmtree` so that we can accept Path objects.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path path: Takes a Path object which is then converted to a str object
|
||||||
|
:return: Passes the return from :func:`shutil.rmtree` back
|
||||||
|
:rtype: None
|
||||||
|
|
||||||
|
See the following link for more information on the other parameters:
|
||||||
|
https://docs.python.org/3/library/shutil.html#shutil.rmtree
|
||||||
|
"""
|
||||||
|
|
||||||
|
file_name = shutil.which(*args, **kwargs)
|
||||||
|
if file_name:
|
||||||
|
return str_to_path(file_name)
|
||||||
|
return None
|
||||||
|
@ -32,11 +32,14 @@
|
|||||||
# http://nxsy.org/comparing-documents-with-openoffice-and-python
|
# http://nxsy.org/comparing-documents-with-openoffice-and-python
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from openlp.core.common import is_win, Registry, delete_file
|
from PyQt5 import QtCore
|
||||||
from openlp.core.common.path import Path
|
|
||||||
|
from openlp.core.common import Registry, delete_file, get_uno_command, get_uno_instance, is_win
|
||||||
|
from openlp.core.lib import ScreenList
|
||||||
|
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument, \
|
||||||
|
TextType
|
||||||
|
|
||||||
if is_win():
|
if is_win():
|
||||||
from win32com.client import Dispatch
|
from win32com.client import Dispatch
|
||||||
@ -55,14 +58,6 @@ else:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
uno_available = False
|
uno_available = False
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
|
||||||
|
|
||||||
from openlp.core.lib import ScreenList
|
|
||||||
from openlp.core.common import get_uno_command, get_uno_instance
|
|
||||||
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument, \
|
|
||||||
TextType
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -203,12 +198,15 @@ class ImpressDocument(PresentationDocument):
|
|||||||
Class which holds information and controls a single presentation.
|
Class which holds information and controls a single presentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, document_path):
|
||||||
"""
|
"""
|
||||||
Constructor, store information about the file and initialise.
|
Constructor, store information about the file and initialise.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path document_path: File path for the document to load
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
log.debug('Init Presentation OpenOffice')
|
log.debug('Init Presentation OpenOffice')
|
||||||
super(ImpressDocument, self).__init__(controller, presentation)
|
super().__init__(controller, document_path)
|
||||||
self.document = None
|
self.document = None
|
||||||
self.presentation = None
|
self.presentation = None
|
||||||
self.control = None
|
self.control = None
|
||||||
@ -225,10 +223,10 @@ class ImpressDocument(PresentationDocument):
|
|||||||
if desktop is None:
|
if desktop is None:
|
||||||
self.controller.start_process()
|
self.controller.start_process()
|
||||||
desktop = self.controller.get_com_desktop()
|
desktop = self.controller.get_com_desktop()
|
||||||
url = 'file:///' + self.file_path.replace('\\', '/').replace(':', '|').replace(' ', '%20')
|
url = self.file_path.as_uri()
|
||||||
else:
|
else:
|
||||||
desktop = self.controller.get_uno_desktop()
|
desktop = self.controller.get_uno_desktop()
|
||||||
url = uno.systemPathToFileUrl(self.file_path)
|
url = uno.systemPathToFileUrl(str(self.file_path))
|
||||||
if desktop is None:
|
if desktop is None:
|
||||||
return False
|
return False
|
||||||
self.desktop = desktop
|
self.desktop = desktop
|
||||||
@ -254,11 +252,11 @@ class ImpressDocument(PresentationDocument):
|
|||||||
log.debug('create thumbnails OpenOffice')
|
log.debug('create thumbnails OpenOffice')
|
||||||
if self.check_thumbnails():
|
if self.check_thumbnails():
|
||||||
return
|
return
|
||||||
|
temp_folder_path = self.get_temp_folder()
|
||||||
if is_win():
|
if is_win():
|
||||||
thumb_dir_url = 'file:///' + str(self.get_temp_folder()).replace('\\', '/') \
|
thumb_dir_url = temp_folder_path.as_uri()
|
||||||
.replace(':', '|').replace(' ', '%20')
|
|
||||||
else:
|
else:
|
||||||
thumb_dir_url = uno.systemPathToFileUrl(str(self.get_temp_folder()))
|
thumb_dir_url = uno.systemPathToFileUrl(str(temp_folder_path))
|
||||||
properties = []
|
properties = []
|
||||||
properties.append(self.create_property('FilterName', 'impress_png_Export'))
|
properties.append(self.create_property('FilterName', 'impress_png_Export'))
|
||||||
properties = tuple(properties)
|
properties = tuple(properties)
|
||||||
@ -266,17 +264,16 @@ class ImpressDocument(PresentationDocument):
|
|||||||
pages = doc.getDrawPages()
|
pages = doc.getDrawPages()
|
||||||
if not pages:
|
if not pages:
|
||||||
return
|
return
|
||||||
temp_folder_path = self.get_temp_folder()
|
if not temp_folder_path.is_dir():
|
||||||
if not temp_folder_path.isdir():
|
temp_folder_path.mkdir(parents=True)
|
||||||
temp_folder_path.mkdir()
|
|
||||||
for index in range(pages.getCount()):
|
for index in range(pages.getCount()):
|
||||||
page = pages.getByIndex(index)
|
page = pages.getByIndex(index)
|
||||||
doc.getCurrentController().setCurrentPage(page)
|
doc.getCurrentController().setCurrentPage(page)
|
||||||
url_path = '{path}/{name}.png'.format(path=thumb_dir_url, name=str(index + 1))
|
url_path = '{path}/{name:d}.png'.format(path=thumb_dir_url, name=index + 1)
|
||||||
path = temp_folder_path / '{number).png'.format(number=index + 1)
|
path = temp_folder_path / '{number:d}.png'.format(number=index + 1)
|
||||||
try:
|
try:
|
||||||
doc.storeToURL(url_path, properties)
|
doc.storeToURL(url_path, properties)
|
||||||
self.convert_thumbnail(str(path), index + 1)
|
self.convert_thumbnail(path, index + 1)
|
||||||
delete_file(path)
|
delete_file(path)
|
||||||
except ErrorCodeIOException as exception:
|
except ErrorCodeIOException as exception:
|
||||||
log.exception('ERROR! ErrorCodeIOException {error:d}'.format(error=exception.ErrCode))
|
log.exception('ERROR! ErrorCodeIOException {error:d}'.format(error=exception.ErrCode))
|
||||||
|
@ -19,15 +19,13 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
from openlp.core.common import Registry, Settings, UiStrings, translate
|
from openlp.core.common import Registry, Settings, UiStrings, translate
|
||||||
from openlp.core.common.languagemanager import get_locale_key
|
from openlp.core.common.languagemanager import get_locale_key
|
||||||
from openlp.core.common.path import path_to_str
|
from openlp.core.common.path import Path, path_to_str, str_to_path
|
||||||
from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext,\
|
from openlp.core.lib import MediaManagerItem, ItemCapabilities, ServiceItemContext,\
|
||||||
build_icon, check_item_selected, create_thumb, validate_thumb
|
build_icon, check_item_selected, create_thumb, validate_thumb
|
||||||
from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
|
from openlp.core.lib.ui import critical_error_message_box, create_horizontal_adjusting_combo_box
|
||||||
@ -128,7 +126,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
"""
|
"""
|
||||||
self.list_view.setIconSize(QtCore.QSize(88, 50))
|
self.list_view.setIconSize(QtCore.QSize(88, 50))
|
||||||
file_paths = Settings().value(self.settings_section + '/presentations files')
|
file_paths = Settings().value(self.settings_section + '/presentations files')
|
||||||
self.load_list([path_to_str(file) for file in file_paths], initial_load=True)
|
self.load_list([path_to_str(path) for path in file_paths], initial_load=True)
|
||||||
self.populate_display_types()
|
self.populate_display_types()
|
||||||
|
|
||||||
def populate_display_types(self):
|
def populate_display_types(self):
|
||||||
@ -152,54 +150,57 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
else:
|
else:
|
||||||
self.presentation_widget.hide()
|
self.presentation_widget.hide()
|
||||||
|
|
||||||
def load_list(self, files, target_group=None, initial_load=False):
|
def load_list(self, file_paths, target_group=None, initial_load=False):
|
||||||
"""
|
"""
|
||||||
Add presentations into the media manager. This is called both on initial load of the plugin to populate with
|
Add presentations into the media manager. This is called both on initial load of the plugin to populate with
|
||||||
existing files, and when the user adds new files via the media manager.
|
existing files, and when the user adds new files via the media manager.
|
||||||
|
|
||||||
|
:param list[openlp.core.common.path.Path] file_paths: List of file paths to add to the media manager.
|
||||||
"""
|
"""
|
||||||
current_list = self.get_file_list()
|
file_paths = [str_to_path(filename) for filename in file_paths]
|
||||||
titles = [file_path.name for file_path in current_list]
|
current_paths = self.get_file_list()
|
||||||
|
titles = [file_path.name for file_path in current_paths]
|
||||||
self.application.set_busy_cursor()
|
self.application.set_busy_cursor()
|
||||||
if not initial_load:
|
if not initial_load:
|
||||||
self.main_window.display_progress_bar(len(files))
|
self.main_window.display_progress_bar(len(file_paths))
|
||||||
# Sort the presentations by its filename considering language specific characters.
|
# Sort the presentations by its filename considering language specific characters.
|
||||||
files.sort(key=lambda filename: get_locale_key(os.path.split(str(filename))[1]))
|
file_paths.sort(key=lambda file_path: get_locale_key(file_path.name))
|
||||||
for file in files:
|
for file_path in file_paths:
|
||||||
if not initial_load:
|
if not initial_load:
|
||||||
self.main_window.increment_progress_bar()
|
self.main_window.increment_progress_bar()
|
||||||
if current_list.count(file) > 0:
|
if current_paths.count(file_path) > 0:
|
||||||
continue
|
continue
|
||||||
filename = os.path.split(file)[1]
|
file_name = file_path.name
|
||||||
if not os.path.exists(file):
|
if not file_path.exists():
|
||||||
item_name = QtWidgets.QListWidgetItem(filename)
|
item_name = QtWidgets.QListWidgetItem(file_name)
|
||||||
item_name.setIcon(build_icon(ERROR_IMAGE))
|
item_name.setIcon(build_icon(ERROR_IMAGE))
|
||||||
item_name.setData(QtCore.Qt.UserRole, file)
|
item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path))
|
||||||
item_name.setToolTip(file)
|
item_name.setToolTip(str(file_path))
|
||||||
self.list_view.addItem(item_name)
|
self.list_view.addItem(item_name)
|
||||||
else:
|
else:
|
||||||
if titles.count(filename) > 0:
|
if titles.count(file_name) > 0:
|
||||||
if not initial_load:
|
if not initial_load:
|
||||||
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'File Exists'),
|
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'File Exists'),
|
||||||
translate('PresentationPlugin.MediaItem',
|
translate('PresentationPlugin.MediaItem',
|
||||||
'A presentation with that filename already exists.'))
|
'A presentation with that filename already exists.'))
|
||||||
continue
|
continue
|
||||||
controller_name = self.find_controller_by_type(filename)
|
controller_name = self.find_controller_by_type(file_path)
|
||||||
if controller_name:
|
if controller_name:
|
||||||
controller = self.controllers[controller_name]
|
controller = self.controllers[controller_name]
|
||||||
doc = controller.add_document(file)
|
doc = controller.add_document(file_path)
|
||||||
thumb = str(doc.get_thumbnail_folder() / 'icon.png')
|
thumbnail_path = doc.get_thumbnail_folder() / 'icon.png'
|
||||||
preview = doc.get_thumbnail_path(1, True)
|
preview_path = doc.get_thumbnail_path(1, True)
|
||||||
if not preview and not initial_load:
|
if not preview_path and not initial_load:
|
||||||
doc.load_presentation()
|
doc.load_presentation()
|
||||||
preview = doc.get_thumbnail_path(1, True)
|
preview_path = doc.get_thumbnail_path(1, True)
|
||||||
doc.close_presentation()
|
doc.close_presentation()
|
||||||
if not (preview and os.path.exists(preview)):
|
if not (preview_path and preview_path.exists()):
|
||||||
icon = build_icon(':/general/general_delete.png')
|
icon = build_icon(':/general/general_delete.png')
|
||||||
else:
|
else:
|
||||||
if validate_thumb(preview, thumb):
|
if validate_thumb(preview_path, thumbnail_path):
|
||||||
icon = build_icon(thumb)
|
icon = build_icon(thumbnail_path)
|
||||||
else:
|
else:
|
||||||
icon = create_thumb(preview, thumb)
|
icon = create_thumb(str(preview_path), str(thumbnail_path))
|
||||||
else:
|
else:
|
||||||
if initial_load:
|
if initial_load:
|
||||||
icon = build_icon(':/general/general_delete.png')
|
icon = build_icon(':/general/general_delete.png')
|
||||||
@ -208,10 +209,10 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
translate('PresentationPlugin.MediaItem',
|
translate('PresentationPlugin.MediaItem',
|
||||||
'This type of presentation is not supported.'))
|
'This type of presentation is not supported.'))
|
||||||
continue
|
continue
|
||||||
item_name = QtWidgets.QListWidgetItem(filename)
|
item_name = QtWidgets.QListWidgetItem(file_name)
|
||||||
item_name.setData(QtCore.Qt.UserRole, file)
|
item_name.setData(QtCore.Qt.UserRole, path_to_str(file_path))
|
||||||
item_name.setIcon(icon)
|
item_name.setIcon(icon)
|
||||||
item_name.setToolTip(file)
|
item_name.setToolTip(str(file_path))
|
||||||
self.list_view.addItem(item_name)
|
self.list_view.addItem(item_name)
|
||||||
if not initial_load:
|
if not initial_load:
|
||||||
self.main_window.finished_progress_bar()
|
self.main_window.finished_progress_bar()
|
||||||
@ -228,8 +229,8 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
self.application.set_busy_cursor()
|
self.application.set_busy_cursor()
|
||||||
self.main_window.display_progress_bar(len(row_list))
|
self.main_window.display_progress_bar(len(row_list))
|
||||||
for item in items:
|
for item in items:
|
||||||
filepath = str(item.data(QtCore.Qt.UserRole))
|
file_path = str_to_path(item.data(QtCore.Qt.UserRole))
|
||||||
self.clean_up_thumbnails(filepath)
|
self.clean_up_thumbnails(file_path)
|
||||||
self.main_window.increment_progress_bar()
|
self.main_window.increment_progress_bar()
|
||||||
self.main_window.finished_progress_bar()
|
self.main_window.finished_progress_bar()
|
||||||
for row in row_list:
|
for row in row_list:
|
||||||
@ -237,30 +238,29 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
|
Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
|
||||||
self.application.set_normal_cursor()
|
self.application.set_normal_cursor()
|
||||||
|
|
||||||
def clean_up_thumbnails(self, filepath, clean_for_update=False):
|
def clean_up_thumbnails(self, file_path, clean_for_update=False):
|
||||||
"""
|
"""
|
||||||
Clean up the files created such as thumbnails
|
Clean up the files created such as thumbnails
|
||||||
|
|
||||||
:param filepath: File path of the presention to clean up after
|
:param openlp.core.common.path.Path file_path: File path of the presention to clean up after
|
||||||
:param clean_for_update: Only clean thumbnails if update is needed
|
:param bool clean_for_update: Only clean thumbnails if update is needed
|
||||||
:return: None
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
for cidx in self.controllers:
|
for cidx in self.controllers:
|
||||||
root, file_ext = os.path.splitext(filepath)
|
file_ext = file_path.suffix[1:]
|
||||||
file_ext = file_ext[1:]
|
|
||||||
if file_ext in self.controllers[cidx].supports or file_ext in self.controllers[cidx].also_supports:
|
if file_ext in self.controllers[cidx].supports or file_ext in self.controllers[cidx].also_supports:
|
||||||
doc = self.controllers[cidx].add_document(filepath)
|
doc = self.controllers[cidx].add_document(file_path)
|
||||||
if clean_for_update:
|
if clean_for_update:
|
||||||
thumb_path = doc.get_thumbnail_path(1, True)
|
thumb_path = doc.get_thumbnail_path(1, True)
|
||||||
if not thumb_path or not os.path.exists(filepath) or os.path.getmtime(
|
if not thumb_path or not file_path.exists() or \
|
||||||
thumb_path) < os.path.getmtime(filepath):
|
thumb_path.stat().st_mtime < file_path.stat().st_mtime:
|
||||||
doc.presentation_deleted()
|
doc.presentation_deleted()
|
||||||
else:
|
else:
|
||||||
doc.presentation_deleted()
|
doc.presentation_deleted()
|
||||||
doc.close_presentation()
|
doc.close_presentation()
|
||||||
|
|
||||||
def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
|
def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
|
||||||
context=ServiceItemContext.Service, presentation_file=None):
|
context=ServiceItemContext.Service, file_path=None):
|
||||||
"""
|
"""
|
||||||
Generate the slide data. Needs to be implemented by the plugin.
|
Generate the slide data. Needs to be implemented by the plugin.
|
||||||
|
|
||||||
@ -276,10 +276,9 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
items = self.list_view.selectedItems()
|
items = self.list_view.selectedItems()
|
||||||
if len(items) > 1:
|
if len(items) > 1:
|
||||||
return False
|
return False
|
||||||
filename = presentation_file
|
if file_path is None:
|
||||||
if filename is None:
|
file_path = str_to_path(items[0].data(QtCore.Qt.UserRole))
|
||||||
filename = items[0].data(QtCore.Qt.UserRole)
|
file_type = file_path.suffix.lower()[1:]
|
||||||
file_type = os.path.splitext(filename.lower())[1][1:]
|
|
||||||
if not self.display_type_combo_box.currentText():
|
if not self.display_type_combo_box.currentText():
|
||||||
return False
|
return False
|
||||||
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
service_item.add_capability(ItemCapabilities.CanEditTitle)
|
||||||
@ -292,29 +291,28 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
# force a nonexistent theme
|
# force a nonexistent theme
|
||||||
service_item.theme = -1
|
service_item.theme = -1
|
||||||
for bitem in items:
|
for bitem in items:
|
||||||
filename = presentation_file
|
if file_path is None:
|
||||||
if filename is None:
|
file_path = str_to_path(bitem.data(QtCore.Qt.UserRole))
|
||||||
filename = bitem.data(QtCore.Qt.UserRole)
|
path, file_name = file_path.parent, file_path.name
|
||||||
(path, name) = os.path.split(filename)
|
service_item.title = file_name
|
||||||
service_item.title = name
|
if file_path.exists():
|
||||||
if os.path.exists(filename):
|
processor = self.find_controller_by_type(file_path)
|
||||||
processor = self.find_controller_by_type(filename)
|
|
||||||
if not processor:
|
if not processor:
|
||||||
return False
|
return False
|
||||||
controller = self.controllers[processor]
|
controller = self.controllers[processor]
|
||||||
service_item.processor = None
|
service_item.processor = None
|
||||||
doc = controller.add_document(filename)
|
doc = controller.add_document(file_path)
|
||||||
if doc.get_thumbnail_path(1, True) is None or \
|
if doc.get_thumbnail_path(1, True) is None or \
|
||||||
not (doc.get_temp_folder() / 'mainslide001.png').is_file():
|
not (doc.get_temp_folder() / 'mainslide001.png').is_file():
|
||||||
doc.load_presentation()
|
doc.load_presentation()
|
||||||
i = 1
|
i = 1
|
||||||
image = str(doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i))
|
image_path = doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i)
|
||||||
thumbnail = str(doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i))
|
thumbnail_path = doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i)
|
||||||
while os.path.isfile(image):
|
while image_path.is_file():
|
||||||
service_item.add_from_image(image, name, thumbnail=thumbnail)
|
service_item.add_from_image(str(image_path), file_name, thumbnail=str(thumbnail_path))
|
||||||
i += 1
|
i += 1
|
||||||
image = str(doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i))
|
image_path = doc.get_temp_folder() / 'mainslide{number:0>3d}.png'.format(number=i)
|
||||||
thumbnail = str(doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i))
|
thumbnail_path = doc.get_thumbnail_folder() / 'slide{number:d}.png'.format(number=i)
|
||||||
service_item.add_capability(ItemCapabilities.HasThumbnails)
|
service_item.add_capability(ItemCapabilities.HasThumbnails)
|
||||||
doc.close_presentation()
|
doc.close_presentation()
|
||||||
return True
|
return True
|
||||||
@ -324,34 +322,34 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
|
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
|
||||||
translate('PresentationPlugin.MediaItem',
|
translate('PresentationPlugin.MediaItem',
|
||||||
'The presentation {name} no longer exists.'
|
'The presentation {name} no longer exists.'
|
||||||
).format(name=filename))
|
).format(name=file_path))
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
service_item.processor = self.display_type_combo_box.currentText()
|
service_item.processor = self.display_type_combo_box.currentText()
|
||||||
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
service_item.add_capability(ItemCapabilities.ProvidesOwnDisplay)
|
||||||
for bitem in items:
|
for bitem in items:
|
||||||
filename = bitem.data(QtCore.Qt.UserRole)
|
file_path = str_to_path(bitem.data(QtCore.Qt.UserRole))
|
||||||
(path, name) = os.path.split(filename)
|
path, file_name = file_path.parent, file_path.name
|
||||||
service_item.title = name
|
service_item.title = file_name
|
||||||
if os.path.exists(filename):
|
if file_path.exists:
|
||||||
if self.display_type_combo_box.itemData(self.display_type_combo_box.currentIndex()) == 'automatic':
|
if self.display_type_combo_box.itemData(self.display_type_combo_box.currentIndex()) == 'automatic':
|
||||||
service_item.processor = self.find_controller_by_type(filename)
|
service_item.processor = self.find_controller_by_type(file_path)
|
||||||
if not service_item.processor:
|
if not service_item.processor:
|
||||||
return False
|
return False
|
||||||
controller = self.controllers[service_item.processor]
|
controller = self.controllers[service_item.processor]
|
||||||
doc = controller.add_document(filename)
|
doc = controller.add_document(file_path)
|
||||||
if doc.get_thumbnail_path(1, True) is None:
|
if doc.get_thumbnail_path(1, True) is None:
|
||||||
doc.load_presentation()
|
doc.load_presentation()
|
||||||
i = 1
|
i = 1
|
||||||
img = doc.get_thumbnail_path(i, True)
|
thumbnail_path = doc.get_thumbnail_path(i, True)
|
||||||
if img:
|
if thumbnail_path:
|
||||||
# Get titles and notes
|
# Get titles and notes
|
||||||
titles, notes = doc.get_titles_and_notes()
|
titles, notes = doc.get_titles_and_notes()
|
||||||
service_item.add_capability(ItemCapabilities.HasDisplayTitle)
|
service_item.add_capability(ItemCapabilities.HasDisplayTitle)
|
||||||
if notes.count('') != len(notes):
|
if notes.count('') != len(notes):
|
||||||
service_item.add_capability(ItemCapabilities.HasNotes)
|
service_item.add_capability(ItemCapabilities.HasNotes)
|
||||||
service_item.add_capability(ItemCapabilities.HasThumbnails)
|
service_item.add_capability(ItemCapabilities.HasThumbnails)
|
||||||
while img:
|
while thumbnail_path:
|
||||||
# Use title and note if available
|
# Use title and note if available
|
||||||
title = ''
|
title = ''
|
||||||
if titles and len(titles) >= i:
|
if titles and len(titles) >= i:
|
||||||
@ -359,9 +357,9 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
note = ''
|
note = ''
|
||||||
if notes and len(notes) >= i:
|
if notes and len(notes) >= i:
|
||||||
note = notes[i - 1]
|
note = notes[i - 1]
|
||||||
service_item.add_from_command(path, name, img, title, note)
|
service_item.add_from_command(str(path), file_name, str(thumbnail_path), title, note)
|
||||||
i += 1
|
i += 1
|
||||||
img = doc.get_thumbnail_path(i, True)
|
thumbnail_path = doc.get_thumbnail_path(i, True)
|
||||||
doc.close_presentation()
|
doc.close_presentation()
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -371,7 +369,7 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
'Missing Presentation'),
|
'Missing Presentation'),
|
||||||
translate('PresentationPlugin.MediaItem',
|
translate('PresentationPlugin.MediaItem',
|
||||||
'The presentation {name} is incomplete, '
|
'The presentation {name} is incomplete, '
|
||||||
'please reload.').format(name=filename))
|
'please reload.').format(name=file_path))
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
# File is no longer present
|
# File is no longer present
|
||||||
@ -379,18 +377,20 @@ class PresentationMediaItem(MediaManagerItem):
|
|||||||
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
|
critical_error_message_box(translate('PresentationPlugin.MediaItem', 'Missing Presentation'),
|
||||||
translate('PresentationPlugin.MediaItem',
|
translate('PresentationPlugin.MediaItem',
|
||||||
'The presentation {name} no longer exists.'
|
'The presentation {name} no longer exists.'
|
||||||
).format(name=filename))
|
).format(name=file_path))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def find_controller_by_type(self, filename):
|
def find_controller_by_type(self, file_path):
|
||||||
"""
|
"""
|
||||||
Determine the default application controller to use for the selected file type. This is used if "Automatic" is
|
Determine the default application controller to use for the selected file type. This is used if "Automatic" is
|
||||||
set as the preferred controller. Find the first (alphabetic) enabled controller which "supports" the extension.
|
set as the preferred controller. Find the first (alphabetic) enabled controller which "supports" the extension.
|
||||||
If none found, then look for a controller which "also supports" it instead.
|
If none found, then look for a controller which "also supports" it instead.
|
||||||
|
|
||||||
:param filename: The file name
|
:param openlp.core.common.path.Path file_path: The file path
|
||||||
|
:return: The default application controller for this file type, or None if not supported
|
||||||
|
:rtype: PresentationController
|
||||||
"""
|
"""
|
||||||
file_type = os.path.splitext(filename)[1][1:]
|
file_type = file_path.suffix[1:]
|
||||||
if not file_type:
|
if not file_type:
|
||||||
return None
|
return None
|
||||||
for controller in self.controllers:
|
for controller in self.controllers:
|
||||||
|
@ -19,16 +19,15 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
|
||||||
import copy
|
import copy
|
||||||
import os
|
import logging
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
from openlp.core.common import Registry, Settings
|
from openlp.core.common import Registry, Settings
|
||||||
from openlp.core.ui import HideMode
|
from openlp.core.common.path import Path
|
||||||
from openlp.core.lib import ServiceItemContext
|
from openlp.core.lib import ServiceItemContext
|
||||||
|
from openlp.core.ui import HideMode
|
||||||
from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES
|
from openlp.plugins.presentations.lib.pdfcontroller import PDF_CONTROLLER_FILETYPES
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -325,21 +324,25 @@ class MessageListener(object):
|
|||||||
is_live = message[1]
|
is_live = message[1]
|
||||||
item = message[0]
|
item = message[0]
|
||||||
hide_mode = message[2]
|
hide_mode = message[2]
|
||||||
file = item.get_frame_path()
|
file_path = Path(item.get_frame_path())
|
||||||
self.handler = item.processor
|
self.handler = item.processor
|
||||||
# When starting presentation from the servicemanager we convert
|
# When starting presentation from the servicemanager we convert
|
||||||
# PDF/XPS/OXPS-serviceitems into image-serviceitems. When started from the mediamanager
|
# PDF/XPS/OXPS-serviceitems into image-serviceitems. When started from the mediamanager
|
||||||
# the conversion has already been done at this point.
|
# the conversion has already been done at this point.
|
||||||
file_type = os.path.splitext(file.lower())[1][1:]
|
file_type = file_path.suffix.lower()[1:]
|
||||||
if file_type in PDF_CONTROLLER_FILETYPES:
|
if file_type in PDF_CONTROLLER_FILETYPES:
|
||||||
log.debug('Converting from pdf/xps/oxps to images for serviceitem with file {name}'.format(name=file))
|
log.debug('Converting from pdf/xps/oxps to images for serviceitem with file {name}'.format(name=file_path))
|
||||||
# Create a copy of the original item, and then clear the original item so it can be filled with images
|
# Create a copy of the original item, and then clear the original item so it can be filled with images
|
||||||
item_cpy = copy.copy(item)
|
item_cpy = copy.copy(item)
|
||||||
item.__init__(None)
|
item.__init__(None)
|
||||||
if is_live:
|
if is_live:
|
||||||
self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Live, file)
|
# TODO: To Path object
|
||||||
|
self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Live,
|
||||||
|
str(file_path))
|
||||||
else:
|
else:
|
||||||
self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Preview, file)
|
# TODO: To Path object
|
||||||
|
self.media_item.generate_slide_data(item, item_cpy, False, False, ServiceItemContext.Preview,
|
||||||
|
str(file_path))
|
||||||
# Some of the original serviceitem attributes is needed in the new serviceitem
|
# Some of the original serviceitem attributes is needed in the new serviceitem
|
||||||
item.footer = item_cpy.footer
|
item.footer = item_cpy.footer
|
||||||
item.from_service = item_cpy.from_service
|
item.from_service = item_cpy.from_service
|
||||||
@ -352,13 +355,13 @@ class MessageListener(object):
|
|||||||
self.handler = None
|
self.handler = None
|
||||||
else:
|
else:
|
||||||
if self.handler == self.media_item.automatic:
|
if self.handler == self.media_item.automatic:
|
||||||
self.handler = self.media_item.find_controller_by_type(file)
|
self.handler = self.media_item.find_controller_by_type(file_path)
|
||||||
if not self.handler:
|
if not self.handler:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# the saved handler is not present so need to use one based on file suffix.
|
# the saved handler is not present so need to use one based on file_path suffix.
|
||||||
if not self.controllers[self.handler].available:
|
if not self.controllers[self.handler].available:
|
||||||
self.handler = self.media_item.find_controller_by_type(file)
|
self.handler = self.media_item.find_controller_by_type(file_path)
|
||||||
if not self.handler:
|
if not self.handler:
|
||||||
return
|
return
|
||||||
if is_live:
|
if is_live:
|
||||||
@ -370,7 +373,7 @@ class MessageListener(object):
|
|||||||
if self.handler is None:
|
if self.handler is None:
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
else:
|
else:
|
||||||
controller.add_handler(self.controllers[self.handler], file, hide_mode, message[3])
|
controller.add_handler(self.controllers[self.handler], file_path, hide_mode, message[3])
|
||||||
self.timer.start()
|
self.timer.start()
|
||||||
|
|
||||||
def slide(self, message):
|
def slide(self, message):
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from shutil import which
|
|
||||||
from subprocess import check_output, CalledProcessError
|
from subprocess import check_output, CalledProcessError
|
||||||
|
|
||||||
from openlp.core.common import AppLocation, check_binary_exists
|
from openlp.core.common import AppLocation, check_binary_exists
|
||||||
from openlp.core.common import Settings, is_win
|
from openlp.core.common import Settings, is_win
|
||||||
from openlp.core.common.path import Path, path_to_str
|
from openlp.core.common.path import Path, path_to_str
|
||||||
from openlp.core.lib import ScreenList
|
from openlp.core.lib import ScreenList
|
||||||
|
from openlp.core.lib.shutil import which
|
||||||
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
|
from openlp.plugins.presentations.lib.presentationcontroller import PresentationController, PresentationDocument
|
||||||
|
|
||||||
if is_win():
|
if is_win():
|
||||||
@ -66,11 +66,12 @@ class PdfController(PresentationController):
|
|||||||
Function that checks whether a binary is either ghostscript or mudraw or neither.
|
Function that checks whether a binary is either ghostscript or mudraw or neither.
|
||||||
Is also used from presentationtab.py
|
Is also used from presentationtab.py
|
||||||
|
|
||||||
:param program_path:The full path to the binary to check.
|
:param openlp.core.common.path.Path program_path: The full path to the binary to check.
|
||||||
:return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid.
|
:return: Type of the binary, 'gs' if ghostscript, 'mudraw' if mudraw, None if invalid.
|
||||||
|
:rtype: str | None
|
||||||
"""
|
"""
|
||||||
program_type = None
|
program_type = None
|
||||||
runlog = check_binary_exists(Path(program_path))
|
runlog = check_binary_exists(program_path)
|
||||||
# Analyse the output to see it the program is mudraw, ghostscript or neither
|
# Analyse the output to see it the program is mudraw, ghostscript or neither
|
||||||
for line in runlog.splitlines():
|
for line in runlog.splitlines():
|
||||||
decoded_line = line.decode()
|
decoded_line = line.decode()
|
||||||
@ -107,30 +108,29 @@ class PdfController(PresentationController):
|
|||||||
:return: True if program to open PDF-files was found, otherwise False.
|
:return: True if program to open PDF-files was found, otherwise False.
|
||||||
"""
|
"""
|
||||||
log.debug('check_installed Pdf')
|
log.debug('check_installed Pdf')
|
||||||
self.mudrawbin = ''
|
self.mudrawbin = None
|
||||||
self.mutoolbin = ''
|
self.mutoolbin = None
|
||||||
self.gsbin = ''
|
self.gsbin = None
|
||||||
self.also_supports = []
|
self.also_supports = []
|
||||||
# Use the user defined program if given
|
# Use the user defined program if given
|
||||||
if Settings().value('presentations/enable_pdf_program'):
|
if Settings().value('presentations/enable_pdf_program'):
|
||||||
pdf_program = path_to_str(Settings().value('presentations/pdf_program'))
|
program_path = Settings().value('presentations/pdf_program')
|
||||||
program_type = self.process_check_binary(pdf_program)
|
program_type = self.process_check_binary(program_path)
|
||||||
if program_type == 'gs':
|
if program_type == 'gs':
|
||||||
self.gsbin = pdf_program
|
self.gsbin = program_path
|
||||||
elif program_type == 'mudraw':
|
elif program_type == 'mudraw':
|
||||||
self.mudrawbin = pdf_program
|
self.mudrawbin = program_path
|
||||||
elif program_type == 'mutool':
|
elif program_type == 'mutool':
|
||||||
self.mutoolbin = pdf_program
|
self.mutoolbin = program_path
|
||||||
else:
|
else:
|
||||||
# Fallback to autodetection
|
# Fallback to autodetection
|
||||||
application_path = str(AppLocation.get_directory(AppLocation.AppDir))
|
application_path = AppLocation.get_directory(AppLocation.AppDir)
|
||||||
if is_win():
|
if is_win():
|
||||||
# for windows we only accept mudraw.exe or mutool.exe in the base folder
|
# for windows we only accept mudraw.exe or mutool.exe in the base folder
|
||||||
application_path = str(AppLocation.get_directory(AppLocation.AppDir))
|
if (application_path / 'mudraw.exe').is_file():
|
||||||
if os.path.isfile(os.path.join(application_path, 'mudraw.exe')):
|
self.mudrawbin = application_path / 'mudraw.exe'
|
||||||
self.mudrawbin = os.path.join(application_path, 'mudraw.exe')
|
elif (application_path / 'mutool.exe').is_file():
|
||||||
elif os.path.isfile(os.path.join(application_path, 'mutool.exe')):
|
self.mutoolbin = application_path / 'mutool.exe'
|
||||||
self.mutoolbin = os.path.join(application_path, 'mutool.exe')
|
|
||||||
else:
|
else:
|
||||||
DEVNULL = open(os.devnull, 'wb')
|
DEVNULL = open(os.devnull, 'wb')
|
||||||
# First try to find mudraw
|
# First try to find mudraw
|
||||||
@ -143,11 +143,11 @@ class PdfController(PresentationController):
|
|||||||
self.gsbin = which('gs')
|
self.gsbin = which('gs')
|
||||||
# Last option: check if mudraw or mutool is placed in OpenLP base folder
|
# 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:
|
if not self.mudrawbin and not self.mutoolbin and not self.gsbin:
|
||||||
application_path = str(AppLocation.get_directory(AppLocation.AppDir))
|
application_path = AppLocation.get_directory(AppLocation.AppDir)
|
||||||
if os.path.isfile(os.path.join(application_path, 'mudraw')):
|
if (application_path / 'mudraw').is_file():
|
||||||
self.mudrawbin = os.path.join(application_path, 'mudraw')
|
self.mudrawbin = application_path / 'mudraw'
|
||||||
elif os.path.isfile(os.path.join(application_path, 'mutool')):
|
elif (application_path / 'mutool').is_file():
|
||||||
self.mutoolbin = os.path.join(application_path, 'mutool')
|
self.mutoolbin = application_path / 'mutool'
|
||||||
if self.mudrawbin or self.mutoolbin:
|
if self.mudrawbin or self.mutoolbin:
|
||||||
self.also_supports = ['xps', 'oxps']
|
self.also_supports = ['xps', 'oxps']
|
||||||
return True
|
return True
|
||||||
@ -172,12 +172,15 @@ class PdfDocument(PresentationDocument):
|
|||||||
image-serviceitem on the fly and present as such. Therefore some of the 'playback'
|
image-serviceitem on the fly and present as such. Therefore some of the 'playback'
|
||||||
functions is not implemented.
|
functions is not implemented.
|
||||||
"""
|
"""
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, document_path):
|
||||||
"""
|
"""
|
||||||
Constructor, store information about the file and initialise.
|
Constructor, store information about the file and initialise.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path document_path: Path to the document to load
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
log.debug('Init Presentation Pdf')
|
log.debug('Init Presentation Pdf')
|
||||||
PresentationDocument.__init__(self, controller, presentation)
|
super().__init__(controller, document_path)
|
||||||
self.presentation = None
|
self.presentation = None
|
||||||
self.blanked = False
|
self.blanked = False
|
||||||
self.hidden = False
|
self.hidden = False
|
||||||
@ -200,13 +203,13 @@ class PdfDocument(PresentationDocument):
|
|||||||
:return: The resolution dpi to be used.
|
: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
|
# Use a postscript script to get size of the pdf. It is assumed that all pages have same size
|
||||||
gs_resolution_script = str(AppLocation.get_directory(
|
gs_resolution_script = AppLocation.get_directory(
|
||||||
AppLocation.PluginsDir)) + '/presentations/lib/ghostscript_get_resolution.ps'
|
AppLocation.PluginsDir) / 'presentations' / 'lib' / 'ghostscript_get_resolution.ps'
|
||||||
# Run the script on the pdf to get the size
|
# Run the script on the pdf to get the size
|
||||||
runlog = []
|
runlog = []
|
||||||
try:
|
try:
|
||||||
runlog = check_output([self.controller.gsbin, '-dNOPAUSE', '-dNODISPLAY', '-dBATCH',
|
runlog = check_output([str(self.controller.gsbin), '-dNOPAUSE', '-dNODISPLAY', '-dBATCH',
|
||||||
'-sFile=' + self.file_path, gs_resolution_script],
|
'-sFile={file_path}'.format(file_path=self.file_path), str(gs_resolution_script)],
|
||||||
startupinfo=self.startupinfo)
|
startupinfo=self.startupinfo)
|
||||||
except CalledProcessError as e:
|
except CalledProcessError as e:
|
||||||
log.debug(' '.join(e.cmd))
|
log.debug(' '.join(e.cmd))
|
||||||
@ -246,7 +249,7 @@ class PdfDocument(PresentationDocument):
|
|||||||
created_files = sorted(temp_dir_path.glob('*'))
|
created_files = sorted(temp_dir_path.glob('*'))
|
||||||
for image_path in created_files:
|
for image_path in created_files:
|
||||||
if image_path.is_file():
|
if image_path.is_file():
|
||||||
self.image_files.append(str(image_path))
|
self.image_files.append(image_path)
|
||||||
self.num_pages = len(self.image_files)
|
self.num_pages = len(self.image_files)
|
||||||
return True
|
return True
|
||||||
size = ScreenList().current['size']
|
size = ScreenList().current['size']
|
||||||
@ -258,27 +261,27 @@ class PdfDocument(PresentationDocument):
|
|||||||
# The %03d in the file name is handled by each binary
|
# The %03d in the file name is handled by each binary
|
||||||
if self.controller.mudrawbin:
|
if self.controller.mudrawbin:
|
||||||
log.debug('loading presentation using mudraw')
|
log.debug('loading presentation using mudraw')
|
||||||
runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()),
|
runlog = check_output([str(self.controller.mudrawbin), '-w', str(size.width()), '-h', str(size.height()),
|
||||||
'-o', str(temp_dir_path / 'mainslide%03d.png'), self.file_path],
|
'-o', str(temp_dir_path / 'mainslide%03d.png'), str(self.file_path)],
|
||||||
startupinfo=self.startupinfo)
|
startupinfo=self.startupinfo)
|
||||||
elif self.controller.mutoolbin:
|
elif self.controller.mutoolbin:
|
||||||
log.debug('loading presentation using mutool')
|
log.debug('loading presentation using mutool')
|
||||||
runlog = check_output([self.controller.mutoolbin, 'draw', '-w', str(size.width()), '-h',
|
runlog = check_output([str(self.controller.mutoolbin), 'draw', '-w', str(size.width()),
|
||||||
str(size.height()),
|
'-h', str(size.height()), '-o', str(temp_dir_path / 'mainslide%03d.png'),
|
||||||
'-o', str(temp_dir_path / 'mainslide%03d.png'), self.file_path],
|
str(self.file_path)],
|
||||||
startupinfo=self.startupinfo)
|
startupinfo=self.startupinfo)
|
||||||
elif self.controller.gsbin:
|
elif self.controller.gsbin:
|
||||||
log.debug('loading presentation using gs')
|
log.debug('loading presentation using gs')
|
||||||
resolution = self.gs_get_resolution(size)
|
resolution = self.gs_get_resolution(size)
|
||||||
runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m',
|
runlog = check_output([str(self.controller.gsbin), '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m',
|
||||||
'-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4',
|
'-r{res}'.format(res=resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4',
|
||||||
'-sOutputFile=' + str(temp_dir_path / 'mainslide%03d.png'),
|
'-sOutputFile={output}'.format(output=temp_dir_path / 'mainslide%03d.png'),
|
||||||
self.file_path], startupinfo=self.startupinfo)
|
str(self.file_path)], startupinfo=self.startupinfo)
|
||||||
created_files = sorted(temp_dir_path.glob('*'))
|
created_files = sorted(temp_dir_path.glob('*'))
|
||||||
for image_path in created_files:
|
for image_path in created_files:
|
||||||
if image_path.is_file():
|
if image_path.is_file():
|
||||||
self.image_files.append(str(image_path))
|
self.image_files.append(image_path)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
log.exception(runlog)
|
log.exception(runlog)
|
||||||
return False
|
return False
|
||||||
self.num_pages = len(self.image_files)
|
self.num_pages = len(self.image_files)
|
||||||
|
@ -120,15 +120,16 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
Class which holds information and controls a single presentation.
|
Class which holds information and controls a single presentation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, document_path):
|
||||||
"""
|
"""
|
||||||
Constructor, store information about the file and initialise.
|
Constructor, store information about the file and initialise.
|
||||||
|
|
||||||
:param controller:
|
:param controller:
|
||||||
:param presentation:
|
:param openlp.core.common.path.Path document_path: Path to the document to load
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
log.debug('Init Presentation Powerpoint')
|
log.debug('Init Presentation Powerpoint')
|
||||||
super(PowerpointDocument, self).__init__(controller, presentation)
|
super().__init__(controller, document_path)
|
||||||
self.presentation = None
|
self.presentation = None
|
||||||
self.index_map = {}
|
self.index_map = {}
|
||||||
self.slide_count = 0
|
self.slide_count = 0
|
||||||
@ -145,7 +146,7 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
try:
|
try:
|
||||||
if not self.controller.process:
|
if not self.controller.process:
|
||||||
self.controller.start_process()
|
self.controller.start_process()
|
||||||
self.controller.process.Presentations.Open(os.path.normpath(self.file_path), False, False, False)
|
self.controller.process.Presentations.Open(str(self.file_path), False, False, False)
|
||||||
self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count)
|
self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count)
|
||||||
self.create_thumbnails()
|
self.create_thumbnails()
|
||||||
self.create_titles_and_notes()
|
self.create_titles_and_notes()
|
||||||
@ -363,9 +364,8 @@ class PowerpointDocument(PresentationDocument):
|
|||||||
width=size.width(),
|
width=size.width(),
|
||||||
horizontal=(right - left)))
|
horizontal=(right - left)))
|
||||||
log.debug('window title: {title}'.format(title=window_title))
|
log.debug('window title: {title}'.format(title=window_title))
|
||||||
filename_root, filename_ext = os.path.splitext(os.path.basename(self.file_path))
|
|
||||||
if size.y() == top and size.height() == (bottom - top) and size.x() == left and \
|
if size.y() == top and size.height() == (bottom - top) and size.x() == left and \
|
||||||
size.width() == (right - left) and filename_root in window_title:
|
size.width() == (right - left) and self.file_path.stem in window_title:
|
||||||
log.debug('Found a match and will save the handle')
|
log.debug('Found a match and will save the handle')
|
||||||
self.presentation_hwnd = hwnd
|
self.presentation_hwnd = hwnd
|
||||||
# Stop powerpoint from flashing in the taskbar
|
# Stop powerpoint from flashing in the taskbar
|
||||||
|
@ -85,9 +85,9 @@ class PptviewController(PresentationController):
|
|||||||
if self.process:
|
if self.process:
|
||||||
return
|
return
|
||||||
log.debug('start PPTView')
|
log.debug('start PPTView')
|
||||||
dll_path = os.path.join(str(AppLocation.get_directory(AppLocation.AppDir)),
|
dll_path = AppLocation.get_directory(AppLocation.AppDir) \
|
||||||
'plugins', 'presentations', 'lib', 'pptviewlib', 'pptviewlib.dll')
|
/ 'plugins' / 'presentations' / 'lib' / 'pptviewlib' / 'pptviewlib.dll'
|
||||||
self.process = cdll.LoadLibrary(dll_path)
|
self.process = cdll.LoadLibrary(str(dll_path))
|
||||||
if log.isEnabledFor(logging.DEBUG):
|
if log.isEnabledFor(logging.DEBUG):
|
||||||
self.process.SetDebug(1)
|
self.process.SetDebug(1)
|
||||||
|
|
||||||
@ -104,12 +104,15 @@ class PptviewDocument(PresentationDocument):
|
|||||||
"""
|
"""
|
||||||
Class which holds information and controls a single presentation.
|
Class which holds information and controls a single presentation.
|
||||||
"""
|
"""
|
||||||
def __init__(self, controller, presentation):
|
def __init__(self, controller, document_path):
|
||||||
"""
|
"""
|
||||||
Constructor, store information about the file and initialise.
|
Constructor, store information about the file and initialise.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path document_path: File path to the document to load
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
log.debug('Init Presentation PowerPoint')
|
log.debug('Init Presentation PowerPoint')
|
||||||
super(PptviewDocument, self).__init__(controller, presentation)
|
super().__init__(controller, document_path)
|
||||||
self.presentation = None
|
self.presentation = None
|
||||||
self.ppt_id = None
|
self.ppt_id = None
|
||||||
self.blanked = False
|
self.blanked = False
|
||||||
@ -121,17 +124,16 @@ class PptviewDocument(PresentationDocument):
|
|||||||
the background PptView task started earlier.
|
the background PptView task started earlier.
|
||||||
"""
|
"""
|
||||||
log.debug('LoadPresentation')
|
log.debug('LoadPresentation')
|
||||||
temp_dir_path = self.get_temp_folder()
|
temp_path = self.get_temp_folder()
|
||||||
size = ScreenList().current['size']
|
size = ScreenList().current['size']
|
||||||
rect = RECT(size.x(), size.y(), size.right(), size.bottom())
|
rect = RECT(size.x(), size.y(), size.right(), size.bottom())
|
||||||
self.file_path = os.path.normpath(self.file_path)
|
preview_path = temp_path / 'slide'
|
||||||
preview_path = temp_dir_path / 'slide'
|
|
||||||
# Ensure that the paths are null terminated
|
# Ensure that the paths are null terminated
|
||||||
byte_file_path = self.file_path.encode('utf-16-le') + b'\0'
|
file_path_utf16 = str(self.file_path).encode('utf-16-le') + b'\0'
|
||||||
preview_file_name = str(preview_path).encode('utf-16-le') + b'\0'
|
preview_path_utf16 = str(preview_path).encode('utf-16-le') + b'\0'
|
||||||
if not temp_dir_path:
|
if not temp_path.is_dir():
|
||||||
temp_dir_path.mkdir(parents=True)
|
temp_path.mkdir(parents=True)
|
||||||
self.ppt_id = self.controller.process.OpenPPT(byte_file_path, None, rect, preview_file_name)
|
self.ppt_id = self.controller.process.OpenPPT(file_path_utf16, None, rect, preview_path_utf16)
|
||||||
if self.ppt_id >= 0:
|
if self.ppt_id >= 0:
|
||||||
self.create_thumbnails()
|
self.create_thumbnails()
|
||||||
self.stop_presentation()
|
self.stop_presentation()
|
||||||
@ -148,7 +150,7 @@ class PptviewDocument(PresentationDocument):
|
|||||||
return
|
return
|
||||||
log.debug('create_thumbnails proceeding')
|
log.debug('create_thumbnails proceeding')
|
||||||
for idx in range(self.get_slide_count()):
|
for idx in range(self.get_slide_count()):
|
||||||
path = '{folder}\\slide{index}.bmp'.format(folder=self.get_temp_folder(), index=str(idx + 1))
|
path = self.get_temp_folder() / 'slide{index:d}.bmp'.format(index=idx + 1)
|
||||||
self.convert_thumbnail(path, idx + 1)
|
self.convert_thumbnail(path, idx + 1)
|
||||||
|
|
||||||
def create_titles_and_notes(self):
|
def create_titles_and_notes(self):
|
||||||
@ -161,13 +163,12 @@ class PptviewDocument(PresentationDocument):
|
|||||||
"""
|
"""
|
||||||
titles = None
|
titles = None
|
||||||
notes = None
|
notes = None
|
||||||
filename = os.path.normpath(self.file_path)
|
|
||||||
# let's make sure we have a valid zipped presentation
|
# let's make sure we have a valid zipped presentation
|
||||||
if os.path.exists(filename) and zipfile.is_zipfile(filename):
|
if self.file_path.exists() and zipfile.is_zipfile(str(self.file_path)):
|
||||||
namespaces = {"p": "http://schemas.openxmlformats.org/presentationml/2006/main",
|
namespaces = {"p": "http://schemas.openxmlformats.org/presentationml/2006/main",
|
||||||
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"}
|
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"}
|
||||||
# open the file
|
# open the file
|
||||||
with zipfile.ZipFile(filename) as zip_file:
|
with zipfile.ZipFile(str(self.file_path)) as zip_file:
|
||||||
# find the presentation.xml to get the slide count
|
# find the presentation.xml to get the slide count
|
||||||
with zip_file.open('ppt/presentation.xml') as pres:
|
with zip_file.open('ppt/presentation.xml') as pres:
|
||||||
tree = ElementTree.parse(pres)
|
tree = ElementTree.parse(pres)
|
||||||
|
@ -19,10 +19,7 @@
|
|||||||
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
|
||||||
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
from PyQt5 import QtCore
|
from PyQt5 import QtCore
|
||||||
|
|
||||||
@ -87,19 +84,26 @@ class PresentationDocument(object):
|
|||||||
Returns a path to an image containing a preview for the requested slide
|
Returns a path to an image containing a preview for the requested slide
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, controller, name):
|
def __init__(self, controller, document_path):
|
||||||
"""
|
"""
|
||||||
Constructor for the PresentationController class
|
Constructor for the PresentationController class
|
||||||
|
|
||||||
|
:param controller:
|
||||||
|
:param openlp.core.common.path.Path document_path: Path to the document to load.
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self._setup(name)
|
self._setup(document_path)
|
||||||
|
|
||||||
def _setup(self, name):
|
def _setup(self, document_path):
|
||||||
"""
|
"""
|
||||||
Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
|
Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path document_path: Path to the document to load.
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
self.slide_number = 0
|
self.slide_number = 0
|
||||||
self.file_path = name
|
self.file_path = document_path
|
||||||
check_directory_exists(self.get_thumbnail_folder())
|
check_directory_exists(self.get_thumbnail_folder())
|
||||||
|
|
||||||
def load_presentation(self):
|
def load_presentation(self):
|
||||||
@ -126,12 +130,6 @@ class PresentationDocument(object):
|
|||||||
except OSError:
|
except OSError:
|
||||||
log.exception('Failed to delete presentation controller files')
|
log.exception('Failed to delete presentation controller files')
|
||||||
|
|
||||||
def get_file_name(self):
|
|
||||||
"""
|
|
||||||
Return just the filename of the presentation, without the directory
|
|
||||||
"""
|
|
||||||
return os.path.split(self.file_path)[1]
|
|
||||||
|
|
||||||
def get_thumbnail_folder(self):
|
def get_thumbnail_folder(self):
|
||||||
"""
|
"""
|
||||||
The location where thumbnail images will be stored
|
The location where thumbnail images will be stored
|
||||||
@ -141,9 +139,9 @@ class PresentationDocument(object):
|
|||||||
"""
|
"""
|
||||||
# TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
|
# TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
|
||||||
if Settings().value('presentations/thumbnail_scheme') == 'md5':
|
if Settings().value('presentations/thumbnail_scheme') == 'md5':
|
||||||
folder = md5_hash(self.file_path.encode('utf-8'))
|
folder = md5_hash(bytes(self.file_path))
|
||||||
else:
|
else:
|
||||||
folder = self.get_file_name()
|
folder = self.file_path.name
|
||||||
return Path(self.controller.thumbnail_folder, folder)
|
return Path(self.controller.thumbnail_folder, folder)
|
||||||
|
|
||||||
def get_temp_folder(self):
|
def get_temp_folder(self):
|
||||||
@ -155,19 +153,22 @@ class PresentationDocument(object):
|
|||||||
"""
|
"""
|
||||||
# TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
|
# TODO: If statement can be removed when the upgrade path from 2.0.x to 2.2.x is no longer needed
|
||||||
if Settings().value('presentations/thumbnail_scheme') == 'md5':
|
if Settings().value('presentations/thumbnail_scheme') == 'md5':
|
||||||
folder = md5_hash(self.file_path.encode('utf-8'))
|
folder = md5_hash(bytes(self.file_path))
|
||||||
else:
|
else:
|
||||||
folder = self.get_file_name()
|
folder = self.file_path.name
|
||||||
return Path(self.controller.temp_folder, folder)
|
return Path(self.controller.temp_folder, folder)
|
||||||
|
|
||||||
def check_thumbnails(self):
|
def check_thumbnails(self):
|
||||||
"""
|
"""
|
||||||
Returns ``True`` if the thumbnail images exist and are more recent than the powerpoint file.
|
Check that the last thumbnail image exists and is valid and are more recent than the powerpoint file.
|
||||||
|
|
||||||
|
:return: If the thumbnail is valid
|
||||||
|
:rtype: bool
|
||||||
"""
|
"""
|
||||||
last_image = self.get_thumbnail_path(self.get_slide_count(), True)
|
last_image_path = self.get_thumbnail_path(self.get_slide_count(), True)
|
||||||
if not (last_image and os.path.isfile(last_image)):
|
if not (last_image_path and last_image_path.is_file()):
|
||||||
return False
|
return False
|
||||||
return validate_thumb(self.file_path, last_image)
|
return validate_thumb(self.file_path, last_image_path)
|
||||||
|
|
||||||
def close_presentation(self):
|
def close_presentation(self):
|
||||||
"""
|
"""
|
||||||
@ -250,24 +251,28 @@ class PresentationDocument(object):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def convert_thumbnail(self, file, idx):
|
def convert_thumbnail(self, image_path, index):
|
||||||
"""
|
"""
|
||||||
Convert the slide image the application made to a scaled 360px height .png image.
|
Convert the slide image the application made to a scaled 360px height .png image.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path image_path: Path to the image to create a thumb nail of
|
||||||
|
:param int index: The index of the slide to create the thumbnail for.
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if self.check_thumbnails():
|
if self.check_thumbnails():
|
||||||
return
|
return
|
||||||
if os.path.isfile(file):
|
if image_path.is_file():
|
||||||
thumb_path = self.get_thumbnail_path(idx, False)
|
thumb_path = self.get_thumbnail_path(index, False)
|
||||||
create_thumb(file, thumb_path, False, QtCore.QSize(-1, 360))
|
create_thumb(str(image_path), str(thumb_path), False, QtCore.QSize(-1, 360))
|
||||||
|
|
||||||
def get_thumbnail_path(self, slide_no, check_exists=True):
|
def get_thumbnail_path(self, slide_no, check_exists=False):
|
||||||
"""
|
"""
|
||||||
Returns an image path containing a preview for the requested slide
|
Returns an image path containing a preview for the requested slide
|
||||||
|
|
||||||
:param int slide_no: The slide an image is required for, starting at 1
|
:param int slide_no: The slide an image is required for, starting at 1
|
||||||
:param bool check_exists: Check if the generated path exists
|
:param bool check_exists: Check if the generated path exists
|
||||||
:return: The path, or None if the :param:`check_exists` is True and the file does not exist
|
:return: The path, or None if the :param:`check_exists` is True and the file does not exist
|
||||||
:rtype: openlp.core.common.path.Path, None
|
:rtype: openlp.core.common.path.Path | None
|
||||||
"""
|
"""
|
||||||
path = self.get_thumbnail_folder() / (self.controller.thumbnail_prefix + str(slide_no) + '.png')
|
path = self.get_thumbnail_folder() / (self.controller.thumbnail_prefix + str(slide_no) + '.png')
|
||||||
if path.is_file() or not check_exists:
|
if path.is_file() or not check_exists:
|
||||||
@ -313,23 +318,17 @@ class PresentationDocument(object):
|
|||||||
Reads the titles from the titles file and
|
Reads the titles from the titles file and
|
||||||
the notes files and returns the content in two lists
|
the notes files and returns the content in two lists
|
||||||
"""
|
"""
|
||||||
titles = []
|
|
||||||
notes = []
|
notes = []
|
||||||
titles_file = str(self.get_thumbnail_folder() / 'titles.txt')
|
titles_path = self.get_thumbnail_folder() / 'titles.txt'
|
||||||
if os.path.exists(titles_file):
|
|
||||||
try:
|
try:
|
||||||
with open(titles_file, encoding='utf-8') as fi:
|
titles = titles_path.read_text().splitlines()
|
||||||
titles = fi.read().splitlines()
|
|
||||||
except:
|
except:
|
||||||
log.exception('Failed to open/read existing titles file')
|
log.exception('Failed to open/read existing titles file')
|
||||||
titles = []
|
titles = []
|
||||||
for slide_no, title in enumerate(titles, 1):
|
for slide_no, title in enumerate(titles, 1):
|
||||||
notes_file = str(self.get_thumbnail_folder() / 'slideNotes{number:d}.txt'.format(number=slide_no))
|
notes_path = self.get_thumbnail_folder() / 'slideNotes{number:d}.txt'.format(number=slide_no)
|
||||||
note = ''
|
|
||||||
if os.path.exists(notes_file):
|
|
||||||
try:
|
try:
|
||||||
with open(notes_file, encoding='utf-8') as fn:
|
note = notes_path.read_text()
|
||||||
note = fn.read()
|
|
||||||
except:
|
except:
|
||||||
log.exception('Failed to open/read notes file')
|
log.exception('Failed to open/read notes file')
|
||||||
note = ''
|
note = ''
|
||||||
@ -338,18 +337,19 @@ class PresentationDocument(object):
|
|||||||
|
|
||||||
def save_titles_and_notes(self, titles, notes):
|
def save_titles_and_notes(self, titles, notes):
|
||||||
"""
|
"""
|
||||||
Performs the actual persisting of titles to the titles.txt
|
Performs the actual persisting of titles to the titles.txt and notes to the slideNote%.txt
|
||||||
and notes to the slideNote%.txt
|
|
||||||
|
:param list[str] titles: The titles to save
|
||||||
|
:param list[str] notes: The notes to save
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
if titles:
|
if titles:
|
||||||
titles_path = self.get_thumbnail_folder() / 'titles.txt'
|
titles_path = self.get_thumbnail_folder() / 'titles.txt'
|
||||||
with titles_path.open(mode='wt', encoding='utf-8') as fo:
|
titles_path.write_text('\n'.join(titles))
|
||||||
fo.writelines(titles)
|
|
||||||
if notes:
|
if notes:
|
||||||
for slide_no, note in enumerate(notes, 1):
|
for slide_no, note in enumerate(notes, 1):
|
||||||
notes_path = self.get_thumbnail_folder() / 'slideNotes{number:d}.txt'.format(number=slide_no)
|
notes_path = self.get_thumbnail_folder() / 'slideNotes{number:d}.txt'.format(number=slide_no)
|
||||||
with notes_path.open(mode='wt', encoding='utf-8') as fn:
|
notes_path.write_text(note)
|
||||||
fn.write(note)
|
|
||||||
|
|
||||||
|
|
||||||
class PresentationController(object):
|
class PresentationController(object):
|
||||||
@ -426,12 +426,11 @@ class PresentationController(object):
|
|||||||
self.document_class = document_class
|
self.document_class = document_class
|
||||||
self.settings_section = self.plugin.settings_section
|
self.settings_section = self.plugin.settings_section
|
||||||
self.available = None
|
self.available = None
|
||||||
self.temp_folder = os.path.join(str(AppLocation.get_section_data_path(self.settings_section)), name)
|
self.temp_folder = AppLocation.get_section_data_path(self.settings_section) / name
|
||||||
self.thumbnail_folder = os.path.join(
|
self.thumbnail_folder = AppLocation.get_section_data_path(self.settings_section) / 'thumbnails'
|
||||||
str(AppLocation.get_section_data_path(self.settings_section)), 'thumbnails')
|
|
||||||
self.thumbnail_prefix = 'slide'
|
self.thumbnail_prefix = 'slide'
|
||||||
check_directory_exists(Path(self.thumbnail_folder))
|
check_directory_exists(self.thumbnail_folder)
|
||||||
check_directory_exists(Path(self.temp_folder))
|
check_directory_exists(self.temp_folder)
|
||||||
|
|
||||||
def enabled(self):
|
def enabled(self):
|
||||||
"""
|
"""
|
||||||
@ -466,11 +465,15 @@ class PresentationController(object):
|
|||||||
log.debug('Kill')
|
log.debug('Kill')
|
||||||
self.close_presentation()
|
self.close_presentation()
|
||||||
|
|
||||||
def add_document(self, name):
|
def add_document(self, document_path):
|
||||||
"""
|
"""
|
||||||
Called when a new presentation document is opened.
|
Called when a new presentation document is opened.
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path document_path: Path to the document to load
|
||||||
|
:return: The document
|
||||||
|
:rtype: PresentationDocument
|
||||||
"""
|
"""
|
||||||
document = self.document_class(self, name)
|
document = self.document_class(self, document_path)
|
||||||
self.docs.append(document)
|
self.docs.append(document)
|
||||||
return document
|
return document
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ class PresentationTab(SettingsTab):
|
|||||||
"""
|
"""
|
||||||
Constructor
|
Constructor
|
||||||
"""
|
"""
|
||||||
self.parent = parent
|
|
||||||
self.controllers = controllers
|
self.controllers = controllers
|
||||||
super(PresentationTab, self).__init__(parent, title, visible_title, icon_path)
|
super(PresentationTab, self).__init__(parent, title, visible_title, icon_path)
|
||||||
self.activated = False
|
self.activated = False
|
||||||
@ -194,7 +193,7 @@ class PresentationTab(SettingsTab):
|
|||||||
pdf_program_path = self.program_path_edit.path
|
pdf_program_path = self.program_path_edit.path
|
||||||
enable_pdf_program = self.pdf_program_check_box.checkState()
|
enable_pdf_program = self.pdf_program_check_box.checkState()
|
||||||
# If the given program is blank disable using the program
|
# If the given program is blank disable using the program
|
||||||
if not pdf_program_path:
|
if pdf_program_path is None:
|
||||||
enable_pdf_program = 0
|
enable_pdf_program = 0
|
||||||
if pdf_program_path != Settings().value(self.settings_section + '/pdf_program'):
|
if pdf_program_path != Settings().value(self.settings_section + '/pdf_program'):
|
||||||
Settings().setValue(self.settings_section + '/pdf_program', pdf_program_path)
|
Settings().setValue(self.settings_section + '/pdf_program', pdf_program_path)
|
||||||
@ -220,9 +219,11 @@ class PresentationTab(SettingsTab):
|
|||||||
|
|
||||||
def on_program_path_edit_path_changed(self, new_path):
|
def on_program_path_edit_path_changed(self, new_path):
|
||||||
"""
|
"""
|
||||||
Select the mudraw or ghostscript binary that should be used.
|
Handle the `pathEditChanged` signal from program_path_edit
|
||||||
|
|
||||||
|
:param openlp.core.common.path.Path new_path: File path to the new program
|
||||||
|
:rtype: None
|
||||||
"""
|
"""
|
||||||
new_path = path_to_str(new_path)
|
|
||||||
if new_path:
|
if new_path:
|
||||||
if not PdfController.process_check_binary(new_path):
|
if not PdfController.process_check_binary(new_path):
|
||||||
critical_error_message_box(UiStrings().Error,
|
critical_error_message_box(UiStrings().Error,
|
||||||
|
@ -244,20 +244,3 @@ class TestPresentationDocument(TestCase):
|
|||||||
|
|
||||||
# THEN: load_presentation should return false
|
# THEN: load_presentation should return false
|
||||||
self.assertFalse(result, "PresentationDocument.load_presentation should return false.")
|
self.assertFalse(result, "PresentationDocument.load_presentation should return false.")
|
||||||
|
|
||||||
def test_get_file_name(self):
|
|
||||||
"""
|
|
||||||
Test the PresentationDocument.get_file_name method.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# GIVEN: A mocked os.path.split which returns a list, an instance of PresentationDocument and
|
|
||||||
# arbitary file_path.
|
|
||||||
self.mock_os.path.split.return_value = ['directory', 'file.ext']
|
|
||||||
instance = PresentationDocument(self.mock_controller, 'Name')
|
|
||||||
instance.file_path = 'filepath'
|
|
||||||
|
|
||||||
# WHEN: Calling get_file_name
|
|
||||||
result = instance.get_file_name()
|
|
||||||
|
|
||||||
# THEN: get_file_name should return 'file.ext'
|
|
||||||
self.assertEqual(result, 'file.ext')
|
|
||||||
|
Loading…
Reference in New Issue
Block a user