openlp-core team mailing list archive
-
openlp-core team
-
Mailing list archive
-
Message #27053
[Merge] lp:~tomasgroth/openlp/bugfixes21 into lp:openlp
Tomas Groth has proposed merging lp:~tomasgroth/openlp/bugfixes21 into lp:openlp.
Requested reviews:
Tim Bentley (trb143)
Related bugs:
Bug #1201293 in OpenLP: "Unexpected Power Point dialogues triggers exception"
https://bugs.launchpad.net/openlp/+bug/1201293
Bug #1420356 in OpenLP: "sending presentation live with libreoffice initially is minimized to taskbar"
https://bugs.launchpad.net/openlp/+bug/1420356
Bug #1463703 in OpenLP: "When diplaying a presentation from a loaded service the slidecontroller is blank"
https://bugs.launchpad.net/openlp/+bug/1463703
For more details, see:
https://code.launchpad.net/~tomasgroth/openlp/bugfixes21/+merge/261900
Fix path of presentation thumbnail when loading from service files. Fixes bug 1463703.
Fix PDF reader using wrong maindisplay size.
Fix log-traceback when trying to remove servicemanager files before eg. powerpoint has closed the files.
Improve network exception handling.
Fix timer that checks for presentation slide change, remove powerpoint event handler that did the same.
Hide the main impress window when loading a presentation, but make it visible for a moment when starting presentation. Fixes bug 1420356.
Improve the detection of powerpoints presentation window by only looking at the filename root.
Fix traceback when going live with presentation while blanked to desktop.
Set service_item.name to "images" for pdfs.
--
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/serviceitem.py'
--- openlp/core/lib/serviceitem.py 2015-01-18 13:39:21 +0000
+++ openlp/core/lib/serviceitem.py 2015-06-13 14:53:45 +0000
@@ -33,7 +33,7 @@
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 @@
# 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()
=== modified file 'openlp/core/ui/mainwindow.py'
--- openlp/core/ui/mainwindow.py 2015-05-25 20:43:37 +0000
+++ openlp/core/ui/mainwindow.py 2015-06-13 14:53:45 +0000
@@ -1106,8 +1106,6 @@
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 @@
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')
=== modified file 'openlp/core/utils/__init__.py'
--- openlp/core/utils/__init__.py 2015-02-19 17:17:04 +0000
+++ openlp/core/utils/__init__.py 2015-06-13 14:53:45 +0000
@@ -24,6 +24,7 @@
"""
from datetime import datetime
from distutils.version import LooseVersion
+from http.client import HTTPException
import logging
import locale
import os
@@ -414,6 +415,11 @@
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 @@
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
=== modified file 'openlp/plugins/bibles/lib/http.py'
--- openlp/plugins/bibles/lib/http.py 2015-02-26 21:02:26 +0000
+++ openlp/plugins/bibles/lib/http.py 2015-06-13 14:53:45 +0000
@@ -748,7 +748,10 @@
"""
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
=== modified file 'openlp/plugins/presentations/lib/impresscontroller.py'
--- openlp/plugins/presentations/lib/impresscontroller.py 2015-04-01 20:38:42 +0000
+++ openlp/plugins/presentations/lib/impresscontroller.py 2015-06-13 14:53:45 +0000
@@ -35,7 +35,7 @@
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 @@
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 @@
"""
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 @@
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):
"""
=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
--- openlp/plugins/presentations/lib/mediaitem.py 2015-03-18 22:04:30 +0000
+++ openlp/plugins/presentations/lib/mediaitem.py 2015-06-13 14:53:45 +0000
@@ -281,6 +281,7 @@
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:
=== modified file 'openlp/plugins/presentations/lib/messagelistener.py'
--- openlp/plugins/presentations/lib/messagelistener.py 2015-04-30 12:38:55 +0000
+++ openlp/plugins/presentations/lib/messagelistener.py 2015-06-13 14:53:45 +0000
@@ -243,6 +243,10 @@
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 @@
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 @@
is_live = message[1]
if is_live:
self.live_handler.shutdown()
+ self.timer.stop()
else:
self.preview_handler.shutdown()
=== modified file 'openlp/plugins/presentations/lib/pdfcontroller.py'
--- openlp/plugins/presentations/lib/pdfcontroller.py 2015-01-18 13:39:21 +0000
+++ openlp/plugins/presentations/lib/pdfcontroller.py 2015-06-13 14:53:45 +0000
@@ -89,11 +89,11 @@
# 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 @@
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 @@
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:
=== modified file 'openlp/plugins/presentations/lib/powerpointcontroller.py'
--- openlp/plugins/presentations/lib/powerpointcontroller.py 2015-05-27 08:45:52 +0000
+++ openlp/plugins/presentations/lib/powerpointcontroller.py 2015-06-13 14:53:45 +0000
@@ -32,7 +32,7 @@
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 @@
"""
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 @@
"""
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 @@
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
=== modified file 'openlp/plugins/presentations/lib/presentationtab.py'
--- openlp/plugins/presentations/lib/presentationtab.py 2015-05-26 21:26:59 +0000
+++ openlp/plugins/presentations/lib/presentationtab.py 2015-06-13 14:53:45 +0000
@@ -128,7 +128,8 @@
'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:'))
=== modified file 'tests/functional/openlp_core_lib/test_serviceitem.py'
--- tests/functional/openlp_core_lib/test_serviceitem.py 2015-01-18 13:39:21 +0000
+++ tests/functional/openlp_core_lib/test_serviceitem.py 2015-06-13 14:53:45 +0000
@@ -28,7 +28,7 @@
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 @@
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
=== modified file 'tests/functional/openlp_plugins/presentations/test_pdfcontroller.py'
--- tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2015-01-22 17:31:00 +0000
+++ tests/functional/openlp_plugins/presentations/test_pdfcontroller.py 2015-06-13 14:53:45 +0000
@@ -135,5 +135,5 @@
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')
Follow ups