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._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):
"""
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]
elif self.service_item_type == ServiceItemType.Command:
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}
def set_from_service(self, serviceitem, path=None):
@ -434,7 +458,10 @@ class ServiceItem(object):
self.title = text_image['title']
if path:
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:
self.add_from_command(text_image['path'], text_image['title'], text_image['image'])
self._new_item()

View File

@ -466,3 +466,10 @@ class ImpressDocument(PresentationDocument):
if shape.supportsService("com.sun.star.drawing.Text"):
text += shape.getString() + '\n'
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
controller = self.controllers[service_item.processor]
doc = controller.add_document(filename)
titles, notes = doc.get_titles_and_notes()
if doc.get_thumbnail_path(1, True) is None:
doc.load_presentation()
i = 1
img = doc.get_thumbnail_path(i, True)
if img:
while img:
service_item.add_from_command(path, name, img)
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
img = doc.get_thumbnail_path(i, True)
doc.close_presentation()

View File

@ -316,7 +316,7 @@ class MessageListener(object):
hide_mode = message[2]
file = item.get_frame_path()
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)
if not self.handler:
return

View File

@ -132,6 +132,7 @@ class PowerpointDocument(PresentationDocument):
return False
self.presentation = self.controller.process.Presentations(self.controller.process.Presentations.Count)
self.create_thumbnails()
self.create_titles_and_notes()
return True
def create_thumbnails(self):
@ -316,6 +317,39 @@ class PowerpointDocument(PresentationDocument):
"""
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):
"""
@ -325,8 +359,8 @@ def _get_text_from_shapes(shapes):
A set of shapes to search for text.
"""
text = ''
for index in range(shapes.Count):
shape = shapes(index + 1)
if shape.HasTextFrame:
for shape in shapes:
if shape.PlaceholderFormat.Type == 2 and shape.HasTextFrame and shape.TextFrame.HasText:
text += shape.TextFrame.TextRange.Text + '\n'
return text

View File

@ -29,6 +29,7 @@
import os
import logging
import zipfile
if os.name == 'nt':
from ctypes import cdll
@ -146,6 +147,80 @@ class PptviewDocument(PresentationDocument):
path = '%s\\slide%s.bmp' % (self.get_temp_folder(), str(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):
"""
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.
"""
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 zipfile
import re
from xml.etree import ElementTree
from PyQt4 import QtGui, QtCore
from ctypes import *
from ctypes.wintypes import RECT
@ -174,6 +177,50 @@ class PPTViewer(QtGui.QWidget):
int(self.widthEdit.text()), int(self.heightEdit.text()))
filename = str(self.pptEdit.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)
self.pptid = self.pptdll.OpenPPT(filename, None, rect, folder)
print('id: ' + str(self.pptid))

Binary file not shown.

View File

@ -289,6 +289,30 @@ class PresentationDocument(object):
"""
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):
"""

View File

@ -470,7 +470,10 @@ class HttpRouter(object):
item['html'] = str(frame['html'])
else:
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['selected'] = (self.live_controller.selected_row == index)
data.append(item)