forked from openlp/openlp
Presentations
This commit is contained in:
parent
9773afc61c
commit
0da1b7b5f7
@ -52,6 +52,7 @@ else:
|
||||
import uno
|
||||
from com.sun.star.beans import PropertyValue
|
||||
from com.sun.star.task import ErrorCodeIOException
|
||||
|
||||
uno_available = True
|
||||
except ImportError:
|
||||
uno_available = False
|
||||
@ -183,9 +184,9 @@ class ImpressController(PresentationController):
|
||||
docs = desktop.getComponents()
|
||||
cnt = 0
|
||||
if docs.hasElements():
|
||||
list = docs.createEnumeration()
|
||||
while list.hasMoreElements():
|
||||
doc = list.nextElement()
|
||||
list_elements = docs.createEnumeration()
|
||||
while list_elements.hasMoreElements():
|
||||
doc = list_elements.nextElement()
|
||||
if doc.getImplementationName() != 'com.sun.star.comp.framework.BackingComp':
|
||||
cnt += 1
|
||||
if cnt > 0:
|
||||
@ -203,7 +204,7 @@ class ImpressDocument(PresentationDocument):
|
||||
Class which holds information and controls a single presentation.
|
||||
"""
|
||||
|
||||
def __init__(self, controller, presentation):
|
||||
def __init__ (self, controller, presentation):
|
||||
"""
|
||||
Constructor, store information about the file and initialise.
|
||||
"""
|
||||
@ -225,10 +226,10 @@ class ImpressDocument(PresentationDocument):
|
||||
if desktop is None:
|
||||
self.controller.start_process()
|
||||
desktop = self.controller.get_com_desktop()
|
||||
url = 'file:///' + self.filepath.replace('\\', '/').replace(':', '|').replace(' ', '%20')
|
||||
url = 'file:///' + self.file_path.replace('\\', '/').replace(':', '|').replace(' ', '%20')
|
||||
else:
|
||||
desktop = self.controller.get_uno_desktop()
|
||||
url = uno.systemPathToFileUrl(self.filepath)
|
||||
url = uno.systemPathToFileUrl(self.file_path)
|
||||
if desktop is None:
|
||||
return False
|
||||
self.desktop = desktop
|
||||
@ -352,7 +353,7 @@ class ImpressDocument(PresentationDocument):
|
||||
log.debug('unblank screen OpenOffice')
|
||||
return self.control.resume()
|
||||
|
||||
def blank_screen(self):
|
||||
def blank_screen (self):
|
||||
"""
|
||||
Blanks the screen.
|
||||
"""
|
||||
@ -409,11 +410,13 @@ class ImpressDocument(PresentationDocument):
|
||||
"""
|
||||
return self.document.getDrawPages().getCount()
|
||||
|
||||
def goto_slide(self, slideno):
|
||||
def goto_slide(self, slide_no):
|
||||
"""
|
||||
Go to a specific slide (from 1).
|
||||
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
self.control.gotoSlideIndex(slideno-1)
|
||||
self.control.gotoSlideIndex(slide_no - 1)
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
@ -435,8 +438,7 @@ class ImpressDocument(PresentationDocument):
|
||||
"""
|
||||
Returns the text on the slide.
|
||||
|
||||
``slide_no``
|
||||
The slide the text is required for, starting at 1
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
return self.__get_text_from_page(slide_no)
|
||||
|
||||
@ -444,8 +446,7 @@ class ImpressDocument(PresentationDocument):
|
||||
"""
|
||||
Returns the text in the slide notes.
|
||||
|
||||
``slide_no``
|
||||
The slide the notes are required for, starting at 1
|
||||
:param slide_no: The slide the notes are required for, starting at 1
|
||||
"""
|
||||
return self.__get_text_from_page(slide_no, True)
|
||||
|
||||
@ -453,8 +454,8 @@ class ImpressDocument(PresentationDocument):
|
||||
"""
|
||||
Return any text extracted from the presentation page.
|
||||
|
||||
``notes``
|
||||
A boolean. If set the method searches the notes of the slide.
|
||||
:param slide_no: The slide the notes are required for, starting at 1
|
||||
:param notes: A boolean. If set the method searches the notes of the slide.
|
||||
"""
|
||||
text = ''
|
||||
pages = self.document.getDrawPages()
|
||||
|
@ -183,7 +183,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
translate('PresentationPlugin.MediaItem',
|
||||
'A presentation with that filename already exists.'))
|
||||
continue
|
||||
controller_name = self.findControllerByType(filename)
|
||||
controller_name = self.find_controller_by_type(filename)
|
||||
if controller_name:
|
||||
controller = self.controllers[controller_name]
|
||||
doc = controller.add_document(file)
|
||||
@ -240,11 +240,16 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
self.list_view.takeItem(row)
|
||||
Settings().setValue(self.settings_section + '/presentations files', self.get_file_list())
|
||||
|
||||
def generate_slide_data(self, service_item, item=None, xml_version=False,
|
||||
remote=False, context=ServiceItemContext.Service, presentation_file=None):
|
||||
def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False,
|
||||
context=ServiceItemContext.Service, presentation_file=None):
|
||||
"""
|
||||
Load the relevant information for displaying the presentation in the slidecontroller. In the case of
|
||||
powerpoints, an image for each slide.
|
||||
Generate the slide data. Needs to be implemented by the plugin.
|
||||
|
||||
:param service_item: The service item to be built on
|
||||
:param item: The Song item to be used
|
||||
:param xml_version: The xml version (not used)
|
||||
:param remote: Triggered from remote
|
||||
:param context: Why is it being generated
|
||||
"""
|
||||
if item:
|
||||
items = [item]
|
||||
@ -272,7 +277,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
(path, name) = os.path.split(filename)
|
||||
service_item.title = name
|
||||
if os.path.exists(filename):
|
||||
processor = self.findControllerByType(filename)
|
||||
processor = self.find_controller_by_type(filename)
|
||||
if not processor:
|
||||
return False
|
||||
controller = self.controllers[processor]
|
||||
@ -282,13 +287,13 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
os.path.join(doc.get_temp_folder(), 'mainslide001.png')):
|
||||
doc.load_presentation()
|
||||
i = 1
|
||||
imagefile = 'mainslide%03d.png' % i
|
||||
image = os.path.join(doc.get_temp_folder(), imagefile)
|
||||
image_file = 'mainslide%03d.png' % i
|
||||
image = os.path.join(doc.get_temp_folder(), image_file)
|
||||
while os.path.isfile(image):
|
||||
service_item.add_from_image(image, name)
|
||||
i += 1
|
||||
imagefile = 'mainslide%03d.png' % i
|
||||
image = os.path.join(doc.get_temp_folder(), imagefile)
|
||||
image_file = 'mainslide%03d.png' % i
|
||||
image = os.path.join(doc.get_temp_folder(), image_file)
|
||||
doc.close_presentation()
|
||||
return True
|
||||
else:
|
||||
@ -307,7 +312,7 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
service_item.title = name
|
||||
if os.path.exists(filename):
|
||||
if service_item.processor == self.automatic:
|
||||
service_item.processor = self.findControllerByType(filename)
|
||||
service_item.processor = self.find_controller_by_type(filename)
|
||||
if not service_item.processor:
|
||||
return False
|
||||
controller = self.controllers[service_item.processor]
|
||||
@ -340,11 +345,13 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
'The presentation %s no longer exists.') % filename)
|
||||
return False
|
||||
|
||||
def findControllerByType(self, filename):
|
||||
def find_controller_by_type(self, filename):
|
||||
"""
|
||||
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.
|
||||
If none found, then look for a controller which "also supports" it instead.
|
||||
|
||||
:param filename: The file name
|
||||
"""
|
||||
file_type = os.path.splitext(filename)[1][1:]
|
||||
if not file_type:
|
||||
@ -360,6 +367,13 @@ class PresentationMediaItem(MediaManagerItem):
|
||||
return None
|
||||
|
||||
def search(self, string, show_error):
|
||||
"""
|
||||
Search in files
|
||||
|
||||
:param string: name to be found
|
||||
:param show_error: not used
|
||||
:return:
|
||||
"""
|
||||
files = Settings().value(self.settings_section + '/presentations files')
|
||||
results = []
|
||||
string = string.lower()
|
||||
|
@ -71,7 +71,7 @@ class Controller(object):
|
||||
return
|
||||
self.doc.slidenumber = slide_no
|
||||
self.hide_mode = hide_mode
|
||||
log.debug('add_handler, slidenumber: %d' % slide_no)
|
||||
log.debug('add_handler, slide_number: %d' % slide_no)
|
||||
if self.is_live:
|
||||
if hide_mode == HideMode.Screen:
|
||||
Registry().execute('live_display_hide', HideMode.Screen)
|
||||
@ -342,7 +342,7 @@ class MessageListener(object):
|
||||
# so handler & processor is set to None, and we skip adding the handler.
|
||||
self.handler = None
|
||||
if self.handler == self.media_item.automatic:
|
||||
self.handler = self.media_item.findControllerByType(file)
|
||||
self.handler = self.media_item.find_controller_by_type(file)
|
||||
if not self.handler:
|
||||
return
|
||||
if is_live:
|
||||
@ -359,6 +359,8 @@ class MessageListener(object):
|
||||
def slide(self, message):
|
||||
"""
|
||||
React to the message to move to a specific slide.
|
||||
|
||||
:param message: The message {1} is_live {2} slide
|
||||
"""
|
||||
is_live = message[1]
|
||||
slide = message[2]
|
||||
@ -370,6 +372,8 @@ class MessageListener(object):
|
||||
def first(self, message):
|
||||
"""
|
||||
React to the message to move to the first slide.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -380,6 +384,8 @@ class MessageListener(object):
|
||||
def last(self, message):
|
||||
"""
|
||||
React to the message to move to the last slide.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -390,6 +396,8 @@ class MessageListener(object):
|
||||
def next(self, message):
|
||||
"""
|
||||
React to the message to move to the next animation/slide.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -400,6 +408,8 @@ class MessageListener(object):
|
||||
def previous(self, message):
|
||||
"""
|
||||
React to the message to move to the previous animation/slide.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -410,6 +420,8 @@ class MessageListener(object):
|
||||
def shutdown(self, message):
|
||||
"""
|
||||
React to message to shutdown the presentation. I.e. end the show and close the file.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -420,6 +432,8 @@ class MessageListener(object):
|
||||
def hide(self, message):
|
||||
"""
|
||||
React to the message to show the desktop.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
@ -428,6 +442,8 @@ class MessageListener(object):
|
||||
def blank(self, message):
|
||||
"""
|
||||
React to the message to blank the display.
|
||||
|
||||
:param message: The message {1} is_live {2} slide
|
||||
"""
|
||||
is_live = message[1]
|
||||
hide_mode = message[2]
|
||||
@ -437,6 +453,8 @@ class MessageListener(object):
|
||||
def unblank(self, message):
|
||||
"""
|
||||
React to the message to unblank the display.
|
||||
|
||||
:param message: The message {1} is_live
|
||||
"""
|
||||
is_live = message[1]
|
||||
if is_live:
|
||||
|
@ -113,7 +113,7 @@ class PdfController(PresentationController):
|
||||
self.gsbin = ''
|
||||
self.also_supports = []
|
||||
# Use the user defined program if given
|
||||
if (Settings().value('presentations/enable_pdf_program')):
|
||||
if Settings().value('presentations/enable_pdf_program'):
|
||||
pdf_program = Settings().value('presentations/pdf_program')
|
||||
program_type = self.check_binary(pdf_program)
|
||||
if program_type == 'gs':
|
||||
@ -197,7 +197,7 @@ class PdfDocument(PresentationDocument):
|
||||
runlog = []
|
||||
try:
|
||||
runlog = check_output([self.controller.gsbin, '-dNOPAUSE', '-dNODISPLAY', '-dBATCH',
|
||||
'-sFile=' + self.filepath, gs_resolution_script])
|
||||
'-sFile=' + self.file_path, gs_resolution_script])
|
||||
except CalledProcessError as e:
|
||||
log.debug(' '.join(e.cmd))
|
||||
log.debug(e.output)
|
||||
@ -246,13 +246,13 @@ class PdfDocument(PresentationDocument):
|
||||
os.makedirs(self.get_temp_folder())
|
||||
if self.controller.mudrawbin:
|
||||
runlog = check_output([self.controller.mudrawbin, '-w', str(size.right()), '-h', str(size.bottom()),
|
||||
'-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.filepath])
|
||||
'-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path])
|
||||
elif self.controller.gsbin:
|
||||
resolution = self.gs_get_resolution(size)
|
||||
runlog = check_output([self.controller.gsbin, '-dSAFER', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m',
|
||||
'-r' + str(resolution), '-dTextAlphaBits=4', '-dGraphicsAlphaBits=4',
|
||||
'-sOutputFile=' + os.path.join(self.get_temp_folder(), 'mainslide%03d.png'),
|
||||
self.filepath])
|
||||
self.file_path])
|
||||
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)):
|
||||
|
@ -112,6 +112,9 @@ class PowerpointDocument(PresentationDocument):
|
||||
def __init__(self, controller, presentation):
|
||||
"""
|
||||
Constructor, store information about the file and initialise.
|
||||
|
||||
:param controller:
|
||||
:param presentation:
|
||||
"""
|
||||
log.debug('Init Presentation Powerpoint')
|
||||
super(PowerpointDocument, self).__init__(controller, presentation)
|
||||
@ -126,7 +129,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
if not self.controller.process or not self.controller.process.Visible:
|
||||
self.controller.start_process()
|
||||
try:
|
||||
self.controller.process.Presentations.Open(self.filepath, False, False, True)
|
||||
self.controller.process.Presentations.Open(self.file_path, False, False, True)
|
||||
except pywintypes.com_error:
|
||||
log.debug('PPT open failed')
|
||||
return False
|
||||
@ -275,12 +278,14 @@ class PowerpointDocument(PresentationDocument):
|
||||
log.debug('get_slide_count')
|
||||
return self.presentation.Slides.Count
|
||||
|
||||
def goto_slide(self, slideno):
|
||||
def goto_slide(self, slide_no):
|
||||
"""
|
||||
Moves to a specific slide in the presentation.
|
||||
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
log.debug('goto_slide')
|
||||
self.presentation.SlideShowWindow.View.GotoSlide(slideno)
|
||||
self.presentation.SlideShowWindow.View.GotoSlide(slide_no)
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
@ -302,8 +307,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
"""
|
||||
Returns the text on the slide.
|
||||
|
||||
``slide_no``
|
||||
The slide the text is required for, starting at 1.
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
return _get_text_from_shapes(self.presentation.Slides(slide_no).Shapes)
|
||||
|
||||
@ -311,8 +315,7 @@ class PowerpointDocument(PresentationDocument):
|
||||
"""
|
||||
Returns the text on the slide.
|
||||
|
||||
``slide_no``
|
||||
The slide the notes are required for, starting at 1.
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
return _get_text_from_shapes(self.presentation.Slides(slide_no).NotesPage.Shapes)
|
||||
|
||||
@ -321,8 +324,7 @@ def _get_text_from_shapes(shapes):
|
||||
"""
|
||||
Returns any text extracted from the shapes on a presentation slide.
|
||||
|
||||
``shapes``
|
||||
A set of shapes to search for text.
|
||||
:param shapes: A set of shapes to search for text.
|
||||
"""
|
||||
text = ''
|
||||
for index in range(shapes.Count):
|
||||
|
@ -124,7 +124,7 @@ class PptviewDocument(PresentationDocument):
|
||||
temp_folder = self.get_temp_folder()
|
||||
size = ScreenList().current['size']
|
||||
rect = RECT(size.x(), size.y(), size.right(), size.bottom())
|
||||
file_path = os.path.normpath(self.filepath)
|
||||
file_path = os.path.normpath(self.file_path)
|
||||
preview_path = os.path.join(temp_folder, 'slide')
|
||||
# Ensure that the paths are null terminated
|
||||
file_path = file_path.encode('utf-16-le') + b'\0'
|
||||
@ -228,11 +228,13 @@ class PptviewDocument(PresentationDocument):
|
||||
"""
|
||||
return self.controller.process.GetSlideCount(self.ppt_id)
|
||||
|
||||
def goto_slide(self, slideno):
|
||||
def goto_slide(self, slide_no):
|
||||
"""
|
||||
Moves to a specific slide in the presentation.
|
||||
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
self.controller.process.GotoSlide(self.ppt_id, slideno)
|
||||
self.controller.process.GotoSlide(self.ppt_id, slide_no)
|
||||
|
||||
def next_step(self):
|
||||
"""
|
||||
|
@ -103,8 +103,8 @@ class PresentationDocument(object):
|
||||
"""
|
||||
Run some initial setup. This method is separate from __init__ in order to mock it out in tests.
|
||||
"""
|
||||
self.slidenumber = 0
|
||||
self.filepath = name
|
||||
self.slide_number = 0
|
||||
self.file_path = name
|
||||
check_directory_exists(self.get_thumbnail_folder())
|
||||
|
||||
def load_presentation(self):
|
||||
@ -131,7 +131,7 @@ class PresentationDocument(object):
|
||||
"""
|
||||
Return just the filename of the presentation, without the directory
|
||||
"""
|
||||
return os.path.split(self.filepath)[1]
|
||||
return os.path.split(self.file_path)[1]
|
||||
|
||||
def get_thumbnail_folder(self):
|
||||
"""
|
||||
@ -149,10 +149,10 @@ class PresentationDocument(object):
|
||||
"""
|
||||
Returns ``True`` if the thumbnail images exist and are more recent than the powerpoint file.
|
||||
"""
|
||||
lastimage = self.get_thumbnail_path(self.get_slide_count(), True)
|
||||
if not (lastimage and os.path.isfile(lastimage)):
|
||||
last_image = self.get_thumbnail_path(self.get_slide_count(), True)
|
||||
if not (last_image and os.path.isfile(last_image)):
|
||||
return False
|
||||
return validate_thumb(self.filepath, lastimage)
|
||||
return validate_thumb(self.file_path, last_image)
|
||||
|
||||
def close_presentation(self):
|
||||
"""
|
||||
@ -253,8 +253,7 @@ class PresentationDocument(object):
|
||||
``slide_no``
|
||||
The slide an image is required for, starting at 1
|
||||
"""
|
||||
path = os.path.join(self.get_thumbnail_folder(),
|
||||
self.controller.thumbnail_prefix + str(slide_no) + '.png')
|
||||
path = os.path.join(self.get_thumbnail_folder(), self.controller.thumbnail_prefix + str(slide_no) + '.png')
|
||||
if os.path.isfile(path) or not check_exists:
|
||||
return path
|
||||
else:
|
||||
@ -268,21 +267,20 @@ class PresentationDocument(object):
|
||||
return
|
||||
if not hide_mode:
|
||||
current = self.get_slide_number()
|
||||
if current == self.slidenumber:
|
||||
if current == self.slide_number:
|
||||
return
|
||||
self.slidenumber = current
|
||||
self.slide_number = current
|
||||
if is_live:
|
||||
prefix = 'live'
|
||||
else:
|
||||
prefix = 'preview'
|
||||
Registry().execute('slidecontroller_%s_change' % prefix, self.slidenumber - 1)
|
||||
Registry().execute('slidecontroller_%s_change' % prefix, self.slide_number - 1)
|
||||
|
||||
def get_slide_text(self, slide_no):
|
||||
"""
|
||||
Returns the text on the slide
|
||||
|
||||
``slide_no``
|
||||
The slide the text is required for, starting at 1
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
return ''
|
||||
|
||||
@ -290,8 +288,7 @@ class PresentationDocument(object):
|
||||
"""
|
||||
Returns the text on the slide
|
||||
|
||||
``slide_no``
|
||||
The slide the notes are required for, starting at 1
|
||||
:param slide_no: The slide the text is required for, starting at 1
|
||||
"""
|
||||
return ''
|
||||
|
||||
@ -350,6 +347,7 @@ class PresentationController(object):
|
||||
def __init__(self, plugin=None, name='PresentationController', document_class=PresentationDocument):
|
||||
"""
|
||||
This is the constructor for the presentationcontroller object. This provides an easy way for descendent plugins
|
||||
|
||||
to populate common data. This method *must* be overridden, like so::
|
||||
|
||||
class MyPresentationController(PresentationController):
|
||||
@ -357,11 +355,9 @@ class PresentationController(object):
|
||||
PresentationController.__init(
|
||||
self, plugin, u'My Presenter App')
|
||||
|
||||
``plugin``
|
||||
Defaults to *None*. The presentationplugin object
|
||||
|
||||
``name``
|
||||
Name of the application, to appear in the application
|
||||
:param plugin: Defaults to *None*. The presentationplugin object
|
||||
:param name: Name of the application, to appear in the application
|
||||
:param document_class:
|
||||
"""
|
||||
self.supports = []
|
||||
self.also_supports = []
|
||||
|
@ -118,7 +118,7 @@ class TestPptviewDocument(TestCase):
|
||||
self.mock_os.path.isdir.return_value = True
|
||||
self.mock_controller.process.OpenPPT.return_value = 0
|
||||
instance = PptviewDocument(self.mock_controller, self.mock_presentation)
|
||||
instance.filepath = 'test\path.ppt'
|
||||
instance.file_path = 'test\path.ppt'
|
||||
|
||||
if os.name == 'nt':
|
||||
result = instance.load_presentation()
|
||||
@ -138,7 +138,7 @@ class TestPptviewDocument(TestCase):
|
||||
self.mock_os.path.isdir.return_value = False
|
||||
self.mock_controller.process.OpenPPT.return_value = -1
|
||||
instance = PptviewDocument(self.mock_controller, self.mock_presentation)
|
||||
instance.filepath = 'test\path.ppt'
|
||||
instance.file_path = 'test\path.ppt'
|
||||
if os.name == 'nt':
|
||||
result = instance.load_presentation()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user