forked from openlp/openlp
Read titles and notes from the presentation files and display them on the remote
This commit is contained in:
parent
e75ef1f261
commit
348ebee661
@ -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()
|
||||
|
@ -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 [],[]
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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))
|
||||
|
BIN
openlp/plugins/presentations/lib/pptviewlib/test.pptx
Normal file
BIN
openlp/plugins/presentations/lib/pptviewlib/test.pptx
Normal file
Binary file not shown.
@ -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):
|
||||
"""
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user