Fix up some stuff around the screen list

This commit is contained in:
Raoul Snyman 2017-12-01 17:35:21 -07:00
parent 64a245bef9
commit c7ea4c460e
10 changed files with 110 additions and 93 deletions

View File

@ -23,7 +23,6 @@
The :mod:`screen` module provides management functionality for a machines'
displays.
"""
import json
import logging
from PyQt5 import QtCore
@ -90,6 +89,30 @@ class ScreenList(object):
for screen in self.screens:
yield screen
def __len__(self):
"""
Make sure we can call "len" on this object
"""
return len(self.screens)
@property
def current(self):
"""
Return the first "current" desktop
NOTE: This is a HACK to ease the upgrade process
"""
# Get the first display screen
for screen in self.screens:
if screen.is_display:
return screen
# If there's no display screen, get the first primary screen
for screen in self.screens:
if screen.is_primary:
return screen
# Otherwise just return the first screen
return self.screens[0]
@classmethod
def create(cls, desktop):
"""
@ -100,7 +123,7 @@ class ScreenList(object):
screen_list = cls()
screen_list.desktop = desktop
screen_list.screens = []
screen_list.screen_count_changed()
screen_list.on_screen_count_changed()
screen_list.load_screen_settings()
screen_list.desktop.resized.connect(screen_list.on_screen_resolution_changed)
screen_list.desktop.screenCountChanged.connect(screen_list.on_screen_count_changed)
@ -138,7 +161,7 @@ class ScreenList(object):
# Add new screens.
for number in range(self.desktop.screenCount()):
if not self.has_screen(number):
self.screens.append(Screen(number, self.desktop.getGeometry(number),
self.screens.append(Screen(number, self.desktop.screenGeometry(number),
self.desktop.primaryScreen() == number))
# We do not want to send this message at start up.
if changed_screen is not None:
@ -201,7 +224,7 @@ class ScreenList(object):
'core/monitors': '{}'
}
Settings.extend_default_settings(screen_settings)
monitors = json.loads(Settings().value('core/monitors'))
monitors = Settings().value('core/monitors')
for screen in self.screens:
monitor = monitors.get(screen.number)
if monitor:

View File

@ -176,8 +176,8 @@ class ImageManager(QtCore.QObject):
super(ImageManager, self).__init__()
Registry().register('image_manager', self)
current_screen = ScreenList().current
self.width = current_screen['size'].width()
self.height = current_screen['size'].height()
self.width = current_screen.display_geometry.width()
self.height = current_screen.display_geometry.height()
self._cache = {}
self.image_thread = ImageThread(self)
self._conversion_queue = PriorityQueue()
@ -190,8 +190,8 @@ class ImageManager(QtCore.QObject):
"""
log.debug('update_display')
current_screen = ScreenList().current
self.width = current_screen['size'].width()
self.height = current_screen['size'].height()
self.width = current_screen.display_geometry.width()
self.height = current_screen.display_geometry.height()
# Mark the images as dirty for a rebuild by setting the image and byte stream to None.
for image in list(self._cache.values()):
self._reset_image(image)

View File

@ -48,7 +48,7 @@ class OpenLPDockWidget(QtWidgets.QDockWidget):
self.setWindowIcon(build_icon(icon))
# Sort out the minimum width.
screens = ScreenList()
main_window_docbars = screens.current['size'].width() // 5
main_window_docbars = screens.current.display_geometry.width() // 5
if main_window_docbars > 300:
self.setMinimumWidth(300)
else:

View File

@ -249,7 +249,7 @@ class PdfDocument(PresentationDocument):
self.image_files.append(image_path)
self.num_pages = len(self.image_files)
return True
size = ScreenList().current['size']
size = ScreenList().current.display_geometry
# Generate images from PDF that will fit the frame.
runlog = ''
try:

View File

@ -62,19 +62,26 @@ class TestScreenList(TestCase):
del self.screens
del self.application
def test_add_desktop(self):
def test_create_screen_list(self):
"""
Test the ScreenList.screen_count_changed method to check if new monitors are detected by OpenLP.
Create the screen list
"""
# GIVEN: The screen list at its current size
old_screen_count = len(self.screens.screen_list)
# GIVEN: Mocked desktop
mocked_desktop = MagicMock()
mocked_desktop.screenCount.return_value = 2
mocked_desktop.screenGeometry.side_effect = [
QtCore.QRect(0, 0, 1024, 768),
QtCore.QRect(1024, 0, 1024, 768)
]
mocked_desktop.primaryScreen.return_value = 0
# WHEN: We add a new screen
self.desktop.screenCount.return_value = SCREEN['number'] + 1
self.screens.screen_count_changed(old_screen_count)
# WHEN: create() is called
screen_list = ScreenList.create(mocked_desktop)
# THEN: The screen should have been added and the screens should be identical
new_screen_count = len(self.screens.screen_list)
self.assertEqual(old_screen_count + 1, new_screen_count, 'The new_screens list should be bigger')
self.assertEqual(SCREEN, self.screens.screen_list.pop(),
'The 2nd screen should be identical to the first screen')
# THEN: The correct screens have been set up
assert screen_list.screens[0].number == 0
assert screen_list.screens[0].geometry == QtCore.QRect(0, 0, 1024, 768)
assert screen_list.screens[0].is_primary is True
assert screen_list.screens[1].number == 1
assert screen_list.screens[1].geometry == QtCore.QRect(1024, 0, 1024, 768)
assert screen_list.screens[1].is_primary is False

View File

@ -24,7 +24,7 @@ Package to test the openlp.core.ui.exeptionform package.
"""
import os
import tempfile
from collections import OrderedDict
from unittest import TestCase
from unittest.mock import call, patch
@ -45,40 +45,44 @@ exceptionform.VLC_VERSION = 'VLC Test'
MAIL_ITEM_TEXT = ('**OpenLP Bug Report**\nVersion: Trunk Test\n\n--- Details of the Exception. ---\n\n'
'Description Test\n\n --- Exception Traceback ---\nopenlp: Traceback Test\n'
'--- System information ---\nPlatform: Nose Test\n\n--- Library Versions ---\n'
'Python: Python Test\nQt5: Qt5 test\nPyQt5: PyQt5 Test\nQtWebkit: Webkit Test\n'
'SQLAlchemy: SqlAlchemy Test\nSQLAlchemy Migrate: Migrate Test\nBeautifulSoup: BeautifulSoup Test\n'
'lxml: ETree Test\nChardet: CHARDET Test\nPyEnchant: Enchant Test\nMako: Mako Test\n'
'pyICU: ICU Test\npyUNO bridge: UNO Bridge Test\nVLC: VLC Test\n\n')
'Python: Python Test\nQt5: Qt5 Test\nPyQt5: PyQt5 Test\n'
'SQLAlchemy: SQLAlchemy Test\nAlembic: Alembic Test\nBeautifulSoup: BeautifulSoup Test\n'
'lxml: ETree Test\nChardet: Chardet Test\nPyEnchant: PyEnchant Test\nMako: Mako Test\n'
'pyICU: pyICU Test\nVLC: VLC Test\nPyUNO: UNO Bridge Test\n')
LIBRARY_VERSIONS = OrderedDict([
('Python', 'Python Test'),
('Qt5', 'Qt5 Test'),
('PyQt5', 'PyQt5 Test'),
('SQLAlchemy', 'SQLAlchemy Test'),
('Alembic', 'Alembic Test'),
('BeautifulSoup', 'BeautifulSoup Test'),
('lxml', 'ETree Test'),
('Chardet', 'Chardet Test'),
('PyEnchant', 'PyEnchant Test'),
('Mako', 'Mako Test'),
('pyICU', 'pyICU Test'),
('VLC', 'VLC Test')
])
@patch("openlp.core.ui.exceptionform.Qt.qVersion")
@patch("openlp.core.ui.exceptionform.QtGui.QDesktopServices.openUrl")
@patch("openlp.core.ui.exceptionform.get_version")
@patch("openlp.core.ui.exceptionform.sqlalchemy")
@patch("openlp.core.ui.exceptionform.bs4")
@patch("openlp.core.ui.exceptionform.etree")
@patch("openlp.core.ui.exceptionform.is_linux")
@patch("openlp.core.ui.exceptionform.platform.platform")
@patch("openlp.core.ui.exceptionform.platform.python_version")
@patch('openlp.core.ui.exceptionform.QtGui.QDesktopServices.openUrl')
@patch('openlp.core.ui.exceptionform.get_version')
@patch('openlp.core.ui.exceptionform.get_library_versions')
@patch('openlp.core.ui.exceptionform.is_linux')
@patch('openlp.core.ui.exceptionform.platform.platform')
class TestExceptionForm(TestMixin, TestCase):
"""
Test functionality of exception form functions
"""
def __method_template_for_class_patches(self, __PLACEHOLDER_FOR_LOCAL_METHOD_PATCH_DECORATORS_GO_HERE__,
mocked_python_version, mocked_platform, mocked_is_linux,
mocked_etree, mocked_bs4, mocked_sqlalchemy, mocked_get_version,
mocked_openlurl, mocked_qversion):
mocked_platform, mocked_is_linux, mocked_get_library_versions,
mocked_get_version, mocked_openlurl):
"""
Template so you don't have to remember the layout of class mock options for methods
"""
mocked_etree.__version__ = 'ETree Test'
mocked_bs4.__version__ = 'BeautifulSoup Test'
mocked_sqlalchemy.__version__ = 'SqlAlchemy Test'
mocked_python_version.return_value = 'Python Test'
mocked_platform.return_value = 'Nose Test'
mocked_qversion.return_value = 'Qt5 test'
mocked_is_linux.return_value = False
mocked_get_version.return_value = 'Trunk Test'
mocked_get_library_versions.return_value = LIBRARY_VERSIONS
def setUp(self):
self.setup_application()
@ -98,31 +102,21 @@ class TestExceptionForm(TestMixin, TestCase):
@patch("openlp.core.ui.exceptionform.FileDialog")
@patch("openlp.core.ui.exceptionform.QtCore.QUrl")
@patch("openlp.core.ui.exceptionform.QtCore.QUrlQuery.addQueryItem")
@patch("openlp.core.ui.exceptionform.Qt")
def test_on_send_report_button_clicked(self, mocked_qt, mocked_add_query_item, mocked_qurl, mocked_file_dialog,
mocked_ui_exception_dialog, mocked_python_version, mocked_platform,
mocked_is_linux, mocked_etree, mocked_bs4, mocked_sqlalchemy,
mocked_get_version, mocked_openlurl, mocked_qversion):
def test_on_send_report_button_clicked(self, mocked_add_query_item, mocked_qurl, mocked_file_dialog,
mocked_ui_exception_dialog, mocked_platform, mocked_is_linux,
mocked_get_library_versions, mocked_get_version, mocked_openlurl):
"""
Test send report creates the proper system information text
"""
# GIVEN: Test environment
mocked_etree.__version__ = 'ETree Test'
mocked_bs4.__version__ = 'BeautifulSoup Test'
mocked_sqlalchemy.__version__ = 'SqlAlchemy Test'
mocked_python_version.return_value = 'Python Test'
mocked_platform.return_value = 'Nose Test'
mocked_qversion.return_value = 'Qt5 test'
mocked_is_linux.return_value = False
mocked_get_version.return_value = 'Trunk Test'
mocked_qt.PYQT_VERSION_STR = 'PyQt5 Test'
mocked_is_linux.return_value = False
mocked_get_version.return_value = 'Trunk Test'
mocked_get_library_versions.return_value = LIBRARY_VERSIONS
test_form = exceptionform.ExceptionForm()
test_form.file_attachment = None
with patch.object(test_form, '_pyuno_import') as mock_pyuno, \
with patch.object(test_form, '_get_pyuno_version') as mock_pyuno, \
patch.object(test_form.exception_text_edit, 'toPlainText') as mock_traceback, \
patch.object(test_form.description_text_edit, 'toPlainText') as mock_description:
mock_pyuno.return_value = 'UNO Bridge Test'
@ -136,24 +130,15 @@ class TestExceptionForm(TestMixin, TestCase):
mocked_add_query_item.assert_called_with('body', MAIL_ITEM_TEXT)
@patch("openlp.core.ui.exceptionform.FileDialog.getSaveFileName")
@patch("openlp.core.ui.exceptionform.Qt")
def test_on_save_report_button_clicked(self, mocked_qt, mocked_save_filename, mocked_python_version,
mocked_platform, mocked_is_linux, mocked_etree, mocked_bs4,
mocked_sqlalchemy, mocked_get_version, mocked_openlurl,
mocked_qversion):
def test_on_save_report_button_clicked(self, mocked_save_filename, mocked_platform, mocked_is_linux,
mocked_get_library_versions, mocked_get_version, mocked_openlurl):
"""
Test save report saves the correct information to a file
"""
mocked_etree.__version__ = 'ETree Test'
mocked_bs4.__version__ = 'BeautifulSoup Test'
mocked_sqlalchemy.__version__ = 'SqlAlchemy Test'
mocked_python_version.return_value = 'Python Test'
mocked_platform.return_value = 'Nose Test'
mocked_qversion.return_value = 'Qt5 test'
mocked_qt.PYQT_VERSION_STR = 'PyQt5 Test'
mocked_is_linux.return_value = False
mocked_get_version.return_value = 'Trunk Test'
mocked_get_library_versions.return_value = LIBRARY_VERSIONS
with patch.object(Path, 'open') as mocked_path_open:
test_path = Path('testfile.txt')
mocked_save_filename.return_value = test_path, 'ext'
@ -161,7 +146,7 @@ class TestExceptionForm(TestMixin, TestCase):
test_form = exceptionform.ExceptionForm()
test_form.file_attachment = None
with patch.object(test_form, '_pyuno_import') as mock_pyuno, \
with patch.object(test_form, '_get_pyuno_version') as mock_pyuno, \
patch.object(test_form.exception_text_edit, 'toPlainText') as mock_traceback, \
patch.object(test_form.description_text_edit, 'toPlainText') as mock_description:
mock_pyuno.return_value = 'UNO Bridge Test'

View File

@ -67,8 +67,11 @@ class TestMainWindow(TestCase, TestMixin):
self.add_toolbar_action_patcher = patch('openlp.core.ui.mainwindow.create_action')
self.mocked_add_toolbar_action = self.add_toolbar_action_patcher.start()
self.mocked_add_toolbar_action.side_effect = self._create_mock_action
with patch('openlp.core.display.screens.ScreenList.__instance__', spec=ScreenList) as mocked_screen_list:
mocked_screen_list.current = {'number': 0, 'size': QtCore.QSize(600, 800), 'primary': True}
mocked_desktop = MagicMock()
mocked_desktop.screenCount.return_value = 1
mocked_desktop.screenGeometry.return_value = QtCore.QRect(0, 0, 1024, 768)
mocked_desktop.primaryScreen.return_value = 1
ScreenList.create(mocked_desktop)
self.main_window = MainWindow()
def tearDown(self):

View File

@ -23,7 +23,6 @@
This module contains tests for the PdfController
"""
import os
import shutil
from tempfile import mkdtemp
from unittest import TestCase, SkipTest
from unittest.mock import MagicMock, patch

View File

@ -108,7 +108,7 @@ class EasyWorshipSongImportLogger(EasyWorshipSongImport):
self._title_assignment_list.append(title)
class TestFieldDesc:
class FakeFieldDesc:
def __init__(self, name, field_type, size):
self.name = name
self.field_type = field_type
@ -120,11 +120,11 @@ CODE_PAGE_MAPPINGS = [
(852, 'cp1250'), (737, 'cp1253'), (775, 'cp1257'), (855, 'cp1251'), (857, 'cp1254'),
(866, 'cp1251'), (869, 'cp1253'), (862, 'cp1255'), (874, 'cp874')]
TEST_FIELD_DESCS = [
TestFieldDesc('Title', FieldType.String, 50),
TestFieldDesc('Text Percentage Bottom', FieldType.Int16, 2), TestFieldDesc('RecID', FieldType.Int32, 4),
TestFieldDesc('Default Background', FieldType.Logical, 1), TestFieldDesc('Words', FieldType.Memo, 250),
TestFieldDesc('Words', FieldType.Memo, 250), TestFieldDesc('BK Bitmap', FieldType.Blob, 10),
TestFieldDesc('Last Modified', FieldType.Timestamp, 10)]
FakeFieldDesc('Title', FieldType.String, 50),
FakeFieldDesc('Text Percentage Bottom', FieldType.Int16, 2), FakeFieldDesc('RecID', FieldType.Int32, 4),
FakeFieldDesc('Default Background', FieldType.Logical, 1), FakeFieldDesc('Words', FieldType.Memo, 250),
FakeFieldDesc('Words', FieldType.Memo, 250), FakeFieldDesc('BK Bitmap', FieldType.Blob, 10),
FakeFieldDesc('Last Modified', FieldType.Timestamp, 10)]
TEST_FIELDS = [
b'A Heart Like Thine\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', 32868, 2147483750,
129, b'{\\rtf1\\ansi\\deff0\\deftab254{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}{\\f1\\fnil\\fcharset0 Verdana;}}'

View File

@ -34,9 +34,9 @@ except ImportError:
CAN_RUN_TESTS = False
class TestRecord(object):
class FakeRecord(object):
"""
Microsoft Access Driver is not available on non Microsoft Systems for this reason the :class:`TestRecord` is used
Microsoft Access Driver is not available on non Microsoft Systems for this reason the :class:`FakeRecord` is used
to simulate a recordset that would be returned by pyobdc.
"""
def __init__(self, id_, field, value):
@ -66,12 +66,12 @@ if CAN_RUN_TESTS:
self._title_assignment_list.append(title)
RECORDSET_TEST_DATA = [TestRecord(1, 'TITLE', 'Amazing Grace'),
TestRecord(1, 'AUTHOR', 'John Newton'),
TestRecord(1, 'CCLISONGID', '12345'),
TestRecord(1, 'COMMENTS', 'The original version'),
TestRecord(1, 'COPY', 'Public Domain'),
TestRecord(
RECORDSET_TEST_DATA = [FakeRecord(1, 'TITLE', 'Amazing Grace'),
FakeRecord(1, 'AUTHOR', 'John Newton'),
FakeRecord(1, 'CCLISONGID', '12345'),
FakeRecord(1, 'COMMENTS', 'The original version'),
FakeRecord(1, 'COPY', 'Public Domain'),
FakeRecord(
1, 'LYRICS',
'Amazing grace! How&crlf;sweet the sound&crlf;That saved a wretch like me!&crlf;'
'I once was lost,&crlf;but now am found;&crlf;Was blind, but now I see.&crlf;&crlf;'
@ -88,8 +88,8 @@ RECORDSET_TEST_DATA = [TestRecord(1, 'TITLE', 'Amazing Grace'),
'Shall be forever mine.&crlf;&crlf;When we\'ve been there&crlf;ten thousand years,&crlf;'
'Bright shining as the sun,&crlf;We\'ve no less days to&crlf;sing God\'s praise&crlf;'
'Than when we\'d first begun.&crlf;&crlf;'),
TestRecord(2, 'TITLE', 'Beautiful Garden Of Prayer, The'),
TestRecord(
FakeRecord(2, 'TITLE', 'Beautiful Garden Of Prayer, The'),
FakeRecord(
2, 'LYRICS',
'There\'s a garden where&crlf;Jesus is waiting,&crlf;'
'There\'s a place that&crlf;is wondrously fair,&crlf;For it glows with the&crlf;'