Read titles and notes from the presentation files and display them on the remote

This commit is contained in:
Felipe Polo-Wood 2013-10-17 15:31:17 -04:00
parent e75ef1f261
commit 348ebee661
10 changed files with 240 additions and 8 deletions

View File

@ -320,6 +320,26 @@ class ServiceItem(object):
self._raw_frames.append({'title': file_name, 'image': image, 'path': path}) self._raw_frames.append({'title': file_name, 'image': image, 'path': path})
self._new_item() self._new_item()
def add_from_presentation(self, path, file_name, image, displaytitle, notes):
"""
Add a slide from a presentation.
``path``
The path of the presentation
``file_name``
The filename of the presentation
``image``
Full path (including file name) to the thumbnail
``displaytitle``
The title to display on the list and remote
"""
self.service_item_type = ServiceItemType.Command
self._raw_frames.append({'title': file_name, 'image': image, 'path': path, 'displaytitle': displaytitle, 'notes': notes})
self._new_item()
def get_service_repr(self, lite_save): def get_service_repr(self, lite_save):
""" """
This method returns some text which can be saved into the service This method returns some text which can be saved into the service
@ -362,7 +382,11 @@ class ServiceItem(object):
service_data = [slide['title'] for slide in self._raw_frames] service_data = [slide['title'] for slide in self._raw_frames]
elif self.service_item_type == ServiceItemType.Command: elif self.service_item_type == ServiceItemType.Command:
for slide in self._raw_frames: for slide in self._raw_frames:
service_data.append({'title': slide['title'], 'image': slide['image'], 'path': slide['path']}) #if len(slide['displaytitle'])>0:
service_data.append({'title': slide['title'], 'image': slide['image'], 'path': slide['path'],
'displaytitle': slide['displaytitle'], 'notes': slide['notes']})
#else:
# service_data.append({'title': slide['title'], 'image': slide['image'], 'path': slide['path']})
return {'header': service_header, 'data': service_data} return {'header': service_header, 'data': service_data}
def set_from_service(self, serviceitem, path=None): def set_from_service(self, serviceitem, path=None):
@ -434,7 +458,10 @@ class ServiceItem(object):
self.title = text_image['title'] self.title = text_image['title']
if path: if path:
self.has_original_files = False self.has_original_files = False
self.add_from_command(path, text_image['title'], text_image['image']) if serviceitem['serviceitem']['header']['plugin']=='presentations':
self.add_from_presentation(path, text_image['title'], text_image['image'], text_image['displaytitle'], text_image['notes'])
else:
self.add_from_command(path, text_image['title'], text_image['image'])
else: else:
self.add_from_command(text_image['path'], text_image['title'], text_image['image']) self.add_from_command(text_image['path'], text_image['title'], text_image['image'])
self._new_item() self._new_item()

View File

@ -466,3 +466,10 @@ class ImpressDocument(PresentationDocument):
if shape.supportsService("com.sun.star.drawing.Text"): if shape.supportsService("com.sun.star.drawing.Text"):
text += shape.getString() + '\n' text += shape.getString() + '\n'
return text return text
def get_titles_and_notes(self):
"""
Returns a list of titles and a list of notes for the current presentation
"""
# FIXME: somebody with impress expertise
return [],[]

View File

@ -263,13 +263,20 @@ class PresentationMediaItem(MediaManagerItem):
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(filename)
titles, notes = doc.get_titles_and_notes()
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) img = doc.get_thumbnail_path(i, True)
if img: if img:
while img: while img:
service_item.add_from_command(path, name, img) title = name
if i <= len(titles):
title = titles[i-1]
note = ''
if i <= len(notes):
note = notes[i-1]
service_item.add_from_presentation(path, name, img, title, note)
i += 1 i += 1
img = doc.get_thumbnail_path(i, True) img = doc.get_thumbnail_path(i, True)
doc.close_presentation() doc.close_presentation()

View File

@ -316,7 +316,7 @@ class MessageListener(object):
hide_mode = message[2] hide_mode = message[2]
file = item.get_frame_path() file = item.get_frame_path()
self.handler = item.processor self.handler = item.processor
if self.handler == self.media_item.Automatic: if self.handler == self.media_item.automatic:
self.handler = self.media_item.findControllerByType(file) self.handler = self.media_item.findControllerByType(file)
if not self.handler: if not self.handler:
return return

View File

@ -132,6 +132,7 @@ class PowerpointDocument(PresentationDocument):
return False return 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()
return True return True
def create_thumbnails(self): def create_thumbnails(self):
@ -316,6 +317,39 @@ class PowerpointDocument(PresentationDocument):
""" """
return _get_text_from_shapes(self.presentation.Slides(slide_no).NotesPage.Shapes) return _get_text_from_shapes(self.presentation.Slides(slide_no).NotesPage.Shapes)
def create_titles_and_notes(self):
"""
Writes the list of titles (one per slide)
to 'titles.txt'
and the notes to 'slideNotes[x].txt'
in the thumbnails directory
"""
titles = []
num = 0
for slide in self.presentation.Slides:
try:
titles.append(slide.Shapes.Title.TextFrame.TextRange.Text + '\n')
num += 1
notes = _get_text_from_shapes(slide.NotesPage.Shapes)
if len(notes) > 0:
notesfile = os.path.join(self.get_thumbnail_folder(), 'slideNotes%d.txt' % (num))
with open(notesfile, mode='w') as fn:
fn.write(notes)
except Exception as e:
log.exception(e)
titles.append('\n')
titlesfile = os.path.join(self.get_thumbnail_folder(), 'titles.txt')
with open(titlesfile, mode='w') as fo:
fo.writelines(titles)
return
def get_titles_and_notes(self):
"""
Reads the titles from the titles file and
the notes files and returns the contents
in a two lists
"""
return super().get_titles_and_notes()
def _get_text_from_shapes(shapes): def _get_text_from_shapes(shapes):
""" """
@ -325,8 +359,8 @@ def _get_text_from_shapes(shapes):
A set of shapes to search for text. A set of shapes to search for text.
""" """
text = '' text = ''
for index in range(shapes.Count): for shape in shapes:
shape = shapes(index + 1) if shape.PlaceholderFormat.Type == 2 and shape.HasTextFrame and shape.TextFrame.HasText:
if shape.HasTextFrame:
text += shape.TextFrame.TextRange.Text + '\n' text += shape.TextFrame.TextRange.Text + '\n'
return text return text

View File

@ -29,6 +29,7 @@
import os import os
import logging import logging
import zipfile
if os.name == 'nt': if os.name == 'nt':
from ctypes import cdll from ctypes import cdll
@ -146,6 +147,80 @@ class PptviewDocument(PresentationDocument):
path = '%s\\slide%s.bmp' % (self.get_temp_folder(), str(idx + 1)) path = '%s\\slide%s.bmp' % (self.get_temp_folder(), str(idx + 1))
self.convert_thumbnail(path, idx + 1) self.convert_thumbnail(path, idx + 1)
def create_titles_and_notes(self):
"""
Extracts the titles and notes from the zipped file
and writes the list of titles (one per slide)
to 'titles.txt'
and the notes to 'slideNotes[x].txt'
in the thumbnails directory
"""
# let's make sure we have a valid zipped presentation
if zipfile.is_zipfile(filename):
namespaces = {"p": "http://schemas.openxmlformats.org/presentationml/2006/main",
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"}
# open the file
with zipfile.ZipFile(filename) as zip_file:
# find the presentation.xml to get the slide count
with zip_file.open('ppt/presentation.xml') as pres:
tree = ElementTree.parse(pres)
nodes = tree.getroot().findall(".//p:sldIdLst/p:sldId", namespaces=namespaces)
print ("slide count: " + str(len(nodes)))
# initialize the lists
titles = ['' for i in range(len(nodes))]
notes = ['' for i in range(len(nodes))]
# loop thru the file list to find slides and notes
for zip_info in zip_file.infolist():
nodeType = ''
index = -1
listToAdd = None
match = re.search("slides/slide(.+)\.xml", zip_info.filename)
if match:
index = int(match.group(1))-1
nodeType = 'ctrTitle'
listToAdd = titles
match = re.search("notesSlides/notesSlide(.+)\.xml", zip_info.filename)
if match:
index = int(match.group(1))-1
nodeType = 'body'
listToAdd = notes
# if it is one of our files, index shouldn't be -1
if index >= 0:
with zip_file.open(zip_info) as zipped_file:
tree = ElementTree.parse(zipped_file)
text = ''
nodes = tree.getroot().findall(".//p:ph[@type='" + nodeType + "']../../..//p:txBody//a:t", namespaces=namespaces)
if nodes and len(nodes)>0:
for node in nodes:
if len(text) > 0:
text += '\n'
text += node.text
print( 'slide file: ' + zip_info.filename + ' ' + text )
listToAdd[index] = text
print( titles )
print( notes )
# now let's write the files
titlesfile = os.path.join(self.get_thumbnail_folder(), 'titles.txt')
with open(titlesfile, mode='w') as fo:
fo.writelines(titles)
for num in range(len(notes)):
notesfile = os.path.join(self.get_thumbnail_folder(), 'slideNotes%d.txt' % (num+1))
with open(notesfile, mode='w') as fn:
fn.write(notes)
return
def close_presentation(self): def close_presentation(self):
""" """
Close presentation and clean up objects. Triggered by new object being added to SlideController or OpenLP being Close presentation and clean up objects. Triggered by new object being added to SlideController or OpenLP being
@ -240,3 +315,11 @@ class PptviewDocument(PresentationDocument):
Triggers the previous slide on the running presentation. Triggers the previous slide on the running presentation.
""" """
self.controller.process.PrevStep(self.ppt_id) self.controller.process.PrevStep(self.ppt_id)
def get_titles_and_notes(self):
"""
Reads the titles from the titles file and
the notes files and returns the contents
in a two lists
"""
return super().get_titles_and_notes()

View File

@ -28,6 +28,9 @@
############################################################################### ###############################################################################
import sys import sys
import zipfile
import re
from xml.etree import ElementTree
from PyQt4 import QtGui, QtCore from PyQt4 import QtGui, QtCore
from ctypes import * from ctypes import *
from ctypes.wintypes import RECT from ctypes.wintypes import RECT
@ -174,6 +177,50 @@ class PPTViewer(QtGui.QWidget):
int(self.widthEdit.text()), int(self.heightEdit.text())) int(self.widthEdit.text()), int(self.heightEdit.text()))
filename = str(self.pptEdit.text().replace('/', '\\')) filename = str(self.pptEdit.text().replace('/', '\\'))
folder = str(self.folderEdit.text().replace('/', '\\')) folder = str(self.folderEdit.text().replace('/', '\\'))
if zipfile.is_zipfile(filename):
namespaces = {"p": "http://schemas.openxmlformats.org/presentationml/2006/main",
"a": "http://schemas.openxmlformats.org/drawingml/2006/main"}
with zipfile.ZipFile(filename) as zip_file:
with zip_file.open('ppt/presentation.xml') as pres:
tree = ElementTree.parse(pres)
nodes = tree.getroot().findall(".//p:sldIdLst/p:sldId", namespaces=namespaces)
print ("slide count: " + str(len(nodes)))
titles = [None for i in range(len(nodes))]
notes = [None for i in range(len(nodes))]
for zip_info in zip_file.infolist():
nodeType = ''
index = -1
listToAdd = None
match = re.search("slides/slide(.+)\.xml", zip_info.filename)
if match:
index = int(match.group(1))-1
nodeType = 'ctrTitle'
listToAdd = titles
match = re.search("notesSlides/notesSlide(.+)\.xml", zip_info.filename)
if match:
index = int(match.group(1))-1
nodeType = 'body'
listToAdd = notes
if len(nodeType)>0:
with zip_file.open(zip_info) as zipped_file:
tree = ElementTree.parse(zipped_file)
text = ''
nodes = tree.getroot().findall(".//p:ph[@type='" + nodeType + "']../../..//p:txBody//a:t", namespaces=namespaces)
if nodes and len(nodes)>0:
for node in nodes:
if len(text) > 0:
text += '\n'
text += node.text
print( 'slide file: ' + zip_info.filename + ' ' + text )
listToAdd[index] = text
print( titles )
print( notes )
print(filename, folder) print(filename, folder)
self.pptid = self.pptdll.OpenPPT(filename, None, rect, folder) self.pptid = self.pptdll.OpenPPT(filename, None, rect, folder)
print('id: ' + str(self.pptid)) print('id: ' + str(self.pptid))

Binary file not shown.

View File

@ -289,6 +289,30 @@ class PresentationDocument(object):
""" """
return '' return ''
def get_titles_and_notes(self):
"""
Reads the titles from the titles file and
the notes files and returns the contents
in a two lists
"""
titles = []
notes = []
titlesfile = os.path.join(self.get_thumbnail_folder(), 'titles.txt')
with open(titlesfile) as fi:
titles = fi.readlines()
for index in range(len(titles)):
notesfile = os.path.join(self.get_thumbnail_folder(), 'slideNotes%d.txt' % (index + 1))
note = ''
try:
if os.path.exists(notesfile):
with open(notesfile) as fn:
note = fn.read()
except:
note = ''
notes.append(note)
return titles, notes
class PresentationController(object): class PresentationController(object):
""" """

View File

@ -470,7 +470,10 @@ class HttpRouter(object):
item['html'] = str(frame['html']) item['html'] = str(frame['html'])
else: else:
item['tag'] = str(index + 1) item['tag'] = str(index + 1)
item['text'] = str(frame['title']) if current_item.name == 'presentations':
item['text'] = str(frame['displaytitle']) + '\n' + str(frame['notes'])
else:
item['text'] = str(frame['title'])
item['html'] = str(frame['title']) item['html'] = str(frame['title'])
item['selected'] = (self.live_controller.selected_row == index) item['selected'] = (self.live_controller.selected_row == index)
data.append(item) data.append(item)