This commit is contained in:
Chris Hill 2015-06-14 22:00:54 +01:00
commit 1e33b7c292
12 changed files with 80 additions and 38 deletions

View File

@ -33,7 +33,7 @@ import ntpath
from PyQt4 import QtGui
from openlp.core.common import RegistryProperties, Settings, translate, AppLocation
from openlp.core.common import RegistryProperties, Settings, translate, AppLocation, md5_hash
from openlp.core.lib import ImageSource, build_icon, clean_tags, expand_tags, create_thumb
log = logging.getLogger(__name__)
@ -326,6 +326,12 @@ class ServiceItem(RegistryProperties):
# If the item should have a display title but this frame doesn't have one, we make one up
if self.is_capable(ItemCapabilities.HasDisplayTitle) and not display_title:
display_title = translate('OpenLP.ServiceItem', '[slide %d]') % (len(self._raw_frames) + 1)
# Update image path to match servicemanager location if file was loaded from service
if image and not self.has_original_files and self.name == 'presentations':
file_location = os.path.join(path, file_name)
file_location_hash = md5_hash(file_location.encode('utf-8'))
image = os.path.join(AppLocation.get_section_data_path(self.name), 'thumbnails',
file_location_hash, ntpath.basename(image))
self._raw_frames.append({'title': file_name, 'image': image, 'path': path,
'display_title': display_title, 'notes': notes})
self._new_item()

View File

@ -1106,8 +1106,6 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
self.image_manager.stop_manager = True
while self.image_manager.image_thread.isRunning():
time.sleep(0.1)
# Clean temporary files used by services
self.service_manager_contents.clean_up()
if save_settings:
if Settings().value('advanced/save current plugin'):
Settings().setValue('advanced/current media plugin', self.media_tool_box.currentIndex())
@ -1124,6 +1122,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow, RegistryProperties):
if self.live_controller.display:
self.live_controller.display.close()
self.live_controller.display = None
# Clean temporary files used by services
self.service_manager_contents.clean_up()
if is_win():
# Needed for Windows to stop crashes on exit
Registry().remove('application')

View File

@ -24,6 +24,7 @@ The :mod:`openlp.core.utils` module provides the utility libraries for OpenLP.
"""
from datetime import datetime
from distutils.version import LooseVersion
from http.client import HTTPException
import logging
import locale
import os
@ -414,6 +415,11 @@ def get_web_page(url, header=None, update_openlp=False):
page = None
if retries > CONNECTION_RETRIES:
raise
except socket.gaierror:
log.exception('Socket gaierror: {}'.format(url))
page = None
if retries > CONNECTION_RETRIES:
raise
except ConnectionRefusedError:
log.exception('ConnectionRefused: {}'.format(url))
page = None
@ -425,6 +431,11 @@ def get_web_page(url, header=None, update_openlp=False):
page = None
if retries > CONNECTION_RETRIES:
raise
except HTTPException:
log.exception('HTTPException error: {}'.format(url))
page = None
if retries > CONNECTION_RETRIES:
raise
except:
# Don't know what's happening, so reraise the original
raise

View File

@ -748,7 +748,10 @@ def get_soup_for_bible_ref(reference_url, header=None, pre_parse_regex=None, pre
"""
if not reference_url:
return None
page = get_web_page(reference_url, header, True)
try:
page = get_web_page(reference_url, header, True)
except:
page = None
if not page:
send_error_message('download')
return None

View File

@ -35,7 +35,7 @@ import logging
import os
import time
from openlp.core.common import is_win
from openlp.core.common import is_win, Registry
if is_win():
from win32com.client import Dispatch
@ -231,21 +231,13 @@ class ImpressDocument(PresentationDocument):
return False
self.desktop = desktop
properties = []
if not is_win():
# Recent versions of Impress on Windows won't start the presentation if it starts as minimized. It seems OK
# on Linux though.
properties.append(self.create_property('Minimized', True))
properties.append(self.create_property('Hidden', True))
properties = tuple(properties)
try:
self.document = desktop.loadComponentFromURL(url, '_blank', 0, properties)
except:
log.warning('Failed to load presentation %s' % url)
return False
if is_win():
# As we can't start minimized the Impress window gets in the way.
# Either window.setPosSize(0, 0, 200, 400, 12) or .setVisible(False)
window = self.document.getCurrentController().getFrame().getContainerWindow()
window.setVisible(False)
self.presentation = self.document.getPresentation()
self.presentation.Display = ScreenList().current['number'] + 1
self.control = None
@ -382,6 +374,8 @@ class ImpressDocument(PresentationDocument):
"""
log.debug('start presentation OpenOffice')
if self.control is None or not self.control.isRunning():
window = self.document.getCurrentController().getFrame().getContainerWindow()
window.setVisible(True)
self.presentation.start()
self.control = self.presentation.getController()
# start() returns before the Component is ready. Try for 15 seconds.
@ -390,9 +384,13 @@ class ImpressDocument(PresentationDocument):
time.sleep(0.1)
sleep_count += 1
self.control = self.presentation.getController()
window.setVisible(False)
else:
self.control.activate()
self.goto_slide(1)
# Make sure impress doesn't steal focus, unless we're on a single screen setup
if len(ScreenList().screen_list) > 1:
Registry().get('main_window').activateWindow()
def get_slide_number(self):
"""

View File

@ -281,6 +281,7 @@ class PresentationMediaItem(MediaManagerItem):
service_item.add_capability(ItemCapabilities.CanPreview)
service_item.add_capability(ItemCapabilities.CanLoop)
service_item.add_capability(ItemCapabilities.CanAppend)
service_item.name = 'images'
# force a nonexistent theme
service_item.theme = -1
for bitem in items:

View File

@ -243,6 +243,10 @@ class Controller(object):
Instruct the controller to stop and hide the presentation.
"""
log.debug('Live = %s, stop' % self.is_live)
# The document has not been loaded yet, so don't do anything. This can happen when going live with a
# presentation while blanked to desktop.
if not self.doc:
return
# Save the current slide number to be able to return to this slide if the presentation is activated again.
if self.doc.is_active():
self.doc.slidenumber = self.doc.get_slide_number()
@ -352,6 +356,7 @@ class MessageListener(object):
self.controller = controller
else:
controller.add_handler(self.controllers[self.handler], file, hide_mode, message[3])
self.timer.start()
def slide(self, message):
"""
@ -423,6 +428,7 @@ class MessageListener(object):
is_live = message[1]
if is_live:
self.live_handler.shutdown()
self.timer.stop()
else:
self.preview_handler.shutdown()

View File

@ -89,11 +89,11 @@ class PdfController(PresentationController):
# Analyse the output to see it the program is mudraw, ghostscript or neither
for line in runlog.splitlines():
decoded_line = line.decode()
found_mudraw = re.search('usage: mudraw.*', decoded_line)
found_mudraw = re.search('usage: mudraw.*', decoded_line, re.IGNORECASE)
if found_mudraw:
program_type = 'mudraw'
break
found_gs = re.search('GPL Ghostscript.*', decoded_line)
found_gs = re.search('GPL Ghostscript.*', decoded_line, re.IGNORECASE)
if found_gs:
program_type = 'gs'
break
@ -222,8 +222,8 @@ class PdfDocument(PresentationDocument):
continue
# Calculate the ratio from pdf to screen
if width > 0 and height > 0:
width_ratio = size.right() / width
height_ratio = size.bottom() / height
width_ratio = size.width() / width
height_ratio = size.height() / height
# return the resolution that should be used. 72 is default.
if width_ratio > height_ratio:
return int(height_ratio * 72)
@ -254,7 +254,7 @@ class PdfDocument(PresentationDocument):
if not os.path.isdir(self.get_temp_folder()):
os.makedirs(self.get_temp_folder())
if self.controller.mudrawbin:
runlog = check_output([self.controller.mudrawbin, '-w', str(size.right()), '-h', str(size.bottom()),
runlog = check_output([self.controller.mudrawbin, '-w', str(size.width()), '-h', str(size.height()),
'-o', os.path.join(self.get_temp_folder(), 'mainslide%03d.png'), self.file_path],
startupinfo=self.startupinfo)
elif self.controller.gsbin:

View File

@ -32,7 +32,7 @@ import time
from openlp.core.common import is_win, Settings
if is_win():
from win32com.client import DispatchWithEvents
from win32com.client import Dispatch
import win32com
import win32con
import winreg
@ -93,22 +93,9 @@ class PowerpointController(PresentationController):
"""
Loads PowerPoint process.
"""
class PowerPointEvents:
"""
Class to catch events from PowerPoint.
"""
def OnSlideShowNextClick(self, slideshow_window, effect):
"""
Occurs on the next click of the slide.
If the main OpenLP window is not in focus force update of the slidecontroller.
"""
if not Registry().get('main_window').isActiveWindow():
log.debug('main window is not in focus - should update slidecontroller')
Registry().execute('slidecontroller_live_change', slideshow_window.View.CurrentShowPosition)
log.debug('start_process')
if not self.process:
self.process = DispatchWithEvents('PowerPoint.Application', PowerPointEvents)
self.process = Dispatch('PowerPoint.Application')
def kill(self):
"""
@ -330,6 +317,7 @@ class PowerpointDocument(PresentationDocument):
"""
log.debug('start_presentation')
# SlideShowWindow measures its size/position by points, not pixels
# https://technet.microsoft.com/en-us/library/dn528846.aspx
try:
dpi = win32ui.GetActiveWindow().GetDC().GetDeviceCaps(88)
except win32ui.error:
@ -378,8 +366,9 @@ class PowerpointDocument(PresentationDocument):
log.debug('compare size: %d and %d, %d and %d, %d and %d, %d and %d'
% (size.y(), top, size.height(), (bottom - top), size.x(), left, size.width(), (right - left)))
log.debug('window title: %s' % window_title)
filename_root, filename_ext = os.path.splitext(os.path.basename(self.file_path))
if size.y() == top and size.height() == (bottom - top) and size.x() == left and \
size.width() == (right - left) and os.path.basename(self.file_path) in window_title:
size.width() == (right - left) and filename_root in window_title:
log.debug('Found a match and will save the handle')
self.presentation_hwnd = hwnd
# Stop powerpoint from flashing in the taskbar

View File

@ -128,7 +128,8 @@ class PresentationTab(SettingsTab):
'Clicking on a selected slide in the slidecontroller advances to next effect.'))
self.ppt_window_check_box.setText(
translate('PresentationPlugin.PresentationTab',
'Let PowerPoint control the size and position of the presentation window.'))
'Let PowerPoint control the size and position of the presentation window '
'(workaround for Windows 8 scaling issue).'))
self.pdf_program_check_box.setText(
translate('PresentationPlugin.PresentationTab', 'Use given full path for mudraw or ghostscript binary:'))

View File

@ -28,7 +28,7 @@ from unittest import TestCase
from tests.functional import MagicMock, patch
from tests.utils import assert_length, convert_file_service_item
from openlp.core.common import Registry
from openlp.core.common import Registry, md5_hash
from openlp.core.lib import ItemCapabilities, ServiceItem, ServiceItemType
VERSE = 'The Lord said to {r}Noah{/r}: \n'\
@ -244,6 +244,33 @@ class TestServiceItem(TestCase):
self.assertEqual(service_item.service_item_type, ServiceItemType.Command, 'It should be a Command')
self.assertEqual(service_item.get_frames()[0], frame, 'Frames should match')
@patch('openlp.core.lib.serviceitem.AppLocation.get_section_data_path')
def add_from_command_for_a_presentation_thumb_test(self, mocked_get_section_data_path):
"""
Test the Service Item - adding a presentation, and updating the thumb path
"""
# GIVEN: A service item, a mocked AppLocation and presentation data
mocked_get_section_data_path.return_value = os.path.join('mocked', 'section', 'path')
service_item = ServiceItem(None)
service_item.has_original_files = False
service_item.name = 'presentations'
presentation_name = 'test.pptx'
thumb = os.path.join('tmp', 'test', 'thumb.png')
display_title = 'DisplayTitle'
notes = 'Note1\nNote2\n'
expected_thumb_path = os.path.join('mocked', 'section', 'path', 'thumbnails',
md5_hash(os.path.join(TEST_PATH, presentation_name).encode('utf-8')),
'thumb.png')
frame = {'title': presentation_name, 'image': expected_thumb_path, 'path': TEST_PATH,
'display_title': display_title, 'notes': notes}
# WHEN: adding presentation to service_item
service_item.add_from_command(TEST_PATH, presentation_name, thumb, display_title, notes)
# THEN: verify that it is setup as a Command and that the frame data matches
self.assertEqual(service_item.service_item_type, ServiceItemType.Command, 'It should be a Command')
self.assertEqual(service_item.get_frames()[0], frame, 'Frames should match')
def service_item_load_optical_media_from_service_test(self):
"""
Test the Service Item - load an optical media item

View File

@ -135,5 +135,5 @@ class TestPdfController(TestCase, TestMixin):
self.assertEqual(760, image.height(), 'The height should be 760')
self.assertEqual(537, image.width(), 'The width should be 537')
else:
self.assertEqual(767, image.height(), 'The height should be 767')
self.assertEqual(768, image.height(), 'The height should be 768')
self.assertEqual(543, image.width(), 'The width should be 543')