openlp/openlp/plugins/songs/lib/oooimport.py

226 lines
8.9 KiB
Python

# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2011 Raoul Snyman #
# Portions copyright (c) 2008-2011 Tim Bentley, Jonathan Corwin, Michael #
# Gorven, Scott Guerrieri, Matthias Hub, Meinert Jordan, Armin Köhler, #
# Andreas Preikschat, Mattias Põldaru, Christian Richter, Philip Ridout, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Frode Woldsund #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################
import logging
import os
from PyQt4 import QtCore
from openlp.core.utils import get_uno_command, get_uno_instance
from songimport import SongImport
log = logging.getLogger(__name__)
if os.name == u'nt':
from win32com.client import Dispatch
PAGE_BEFORE = 4
PAGE_AFTER = 5
PAGE_BOTH = 6
else:
import uno
from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER, PAGE_BOTH
class OooImport(SongImport):
"""
Import songs from Impress/Powerpoint docs using Impress
"""
def __init__(self, manager, **kwargs):
"""
Initialise the class. Requires a songmanager class which is passed
to SongImport for writing song to disk
"""
SongImport.__init__(self, manager, **kwargs)
self.document = None
self.process_started = False
def do_import(self):
self.stop_import_flag = False
self.import_wizard.progressBar.setMaximum(0)
self.start_ooo()
for filename in self.import_source:
if self.stop_import_flag:
self.import_wizard.incrementProgressBar(u'Import cancelled', 0)
return
filename = unicode(filename)
if os.path.isfile(filename):
self.open_ooo_file(filename)
if self.document:
self.process_ooo_document()
self.close_ooo_file()
self.close_ooo()
self.import_wizard.progressBar.setMaximum(1)
self.import_wizard.incrementProgressBar(u'', 1)
return True
def process_ooo_document(self):
"""
Handle the import process for OpenOffice files. This method facilitates
allowing subclasses to handle specific types of OpenOffice files.
"""
if self.document.supportsService(
"com.sun.star.presentation.PresentationDocument"):
self.process_pres()
if self.document.supportsService("com.sun.star.text.TextDocument"):
self.process_doc()
def start_ooo(self):
"""
Start OpenOffice.org process
TODO: The presentation/Impress plugin may already have it running
"""
if os.name == u'nt':
self.start_ooo_process()
self.desktop = self.ooo_manager.createInstance(
u'com.sun.star.frame.Desktop')
else:
context = uno.getComponentContext()
resolver = context.ServiceManager.createInstanceWithContext(
u'com.sun.star.bridge.UnoUrlResolver', context)
uno_instance = None
loop = 0
while uno_instance is None and loop < 5:
try:
uno_instance = get_uno_instance(resolver)
except:
log.exception("Failed to resolve uno connection")
self.start_ooo_process()
loop += 1
manager = uno_instance.ServiceManager
self.desktop = manager.createInstanceWithContext(
"com.sun.star.frame.Desktop", uno_instance)
def start_ooo_process(self):
try:
if os.name == u'nt':
self.ooo_manager = Dispatch(u'com.sun.star.ServiceManager')
self.ooo_manager._FlagAsMethod(u'Bridge_GetStruct')
self.ooo_manager._FlagAsMethod(u'Bridge_GetValueObject')
else:
cmd = get_uno_command()
process = QtCore.QProcess()
process.startDetached(cmd)
process.waitForStarted()
self.process_started = True
except:
log.exception("start_ooo_process failed")
def open_ooo_file(self, filepath):
"""
Open the passed file in OpenOffice.org Impress
"""
self.filepath = filepath
if os.name == u'nt':
url = filepath.replace(u'\\', u'/')
url = url.replace(u':', u'|').replace(u' ', u'%20')
url = u'file:///' + url
else:
url = uno.systemPathToFileUrl(filepath)
properties = []
properties = tuple(properties)
try:
self.document = self.desktop.loadComponentFromURL(url, u'_blank',
0, properties)
if not self.document.supportsService(
"com.sun.star.presentation.PresentationDocument") and not \
self.document.supportsService("com.sun.star.text.TextDocument"):
self.close_ooo_file()
else:
self.import_wizard.incrementProgressBar(
u'Processing file ' + filepath, 0)
except:
log.exception("open_ooo_file failed")
return
def close_ooo_file(self):
"""
Close file.
"""
self.document.close(True)
self.document = None
def close_ooo(self):
"""
Close OOo. But only if we started it and not on windows
"""
if self.process_started:
self.desktop.terminate()
def process_pres(self):
"""
Process the file
"""
doc = self.document
slides = doc.getDrawPages()
text = u''
for slide_no in range(slides.getCount()):
if self.stop_import_flag:
self.import_wizard.incrementProgressBar(u'Import cancelled', 0)
return
slide = slides.getByIndex(slide_no)
slidetext = u''
for idx in range(slide.getCount()):
shape = slide.getByIndex(idx)
if shape.supportsService("com.sun.star.drawing.Text"):
if shape.getString().strip() != u'':
slidetext += shape.getString().strip() + u'\n\n'
if slidetext.strip() == u'':
slidetext = u'\f'
text += slidetext
self.process_songs_text(text)
return
def process_doc(self):
"""
Process the doc file, a paragraph at a time
"""
text = u''
paragraphs = self.document.getText().createEnumeration()
while paragraphs.hasMoreElements():
paratext = u''
paragraph = paragraphs.nextElement()
if paragraph.supportsService("com.sun.star.text.Paragraph"):
textportions = paragraph.createEnumeration()
while textportions.hasMoreElements():
textportion = textportions.nextElement()
if textportion.BreakType in (PAGE_BEFORE, PAGE_BOTH):
paratext += u'\f'
paratext += textportion.getString()
if textportion.BreakType in (PAGE_AFTER, PAGE_BOTH):
paratext += u'\f'
text += paratext + u'\n'
self.process_songs_text(text)
def process_songs_text(self, text):
songtexts = self.tidy_text(text).split(u'\f')
self.set_defaults()
for songtext in songtexts:
if songtext.strip():
self.process_song_text(songtext.strip())
if self.check_complete():
self.finish()
self.set_defaults()
if self.check_complete():
self.finish()