Make screen selection reusable

This commit is contained in:
Philip Ridout 2019-01-26 08:17:07 +00:00
commit af41798128
4 changed files with 461 additions and 230 deletions

View File

@ -84,7 +84,7 @@ def upgrade_screens(number, x_position, y_position, height, width, can_override,
"""
geometry_key = 'geometry'
if can_override:
geometry_key = 'display_geometry'
geometry_key = 'custom_geometry'
return {
number: {
'number': number,

View File

@ -22,49 +22,15 @@
"""
The screen settings tab in the configuration dialog
"""
import logging
from PyQt5 import QtCore, QtWidgets
from PyQt5 import QtWidgets
from openlp.core.common.i18n import translate
from openlp.core.common.settings import Settings
from openlp.core.display.screens import ScreenList
from openlp.core.lib.settingstab import SettingsTab
from openlp.core.common.registry import Registry
from openlp.core.ui.icons import UiIcons
SCREENS_LAYOUT_STYLE = """
#screen_frame {
background-color: palette(base);
}
#screen_frame QPushButton {
background-color: palette(window);
border: 3px solid palette(text);
border-radius: 3px;
height: 100px;
outline: 0;
width: 150px;
}
#screen_frame QPushButton:checked {
border-color: palette(highlight);
}
"""
log = logging.getLogger(__name__)
class ScreenButton(QtWidgets.QPushButton):
"""
A special button class that holds the screen information about it
"""
def __init__(self, parent, screen):
"""
Initialise this button
"""
super(ScreenButton, self).__init__(parent)
self.setObjectName('screen{number}_button'.format(number=screen.number))
self.setText(str(screen))
self.setCheckable(True)
self.screen = screen
from openlp.core.widgets.widgets import ScreenSelectionWidget
class ScreensTab(SettingsTab):
@ -75,88 +41,21 @@ class ScreensTab(SettingsTab):
"""
Initialise the screen settings tab
"""
self.screens = ScreenList()
self.icon_path = UiIcons().settings
screens_translated = translate('OpenLP.ScreensTab', 'Screens')
super(ScreensTab, self).__init__(parent, 'Screens', screens_translated)
self.settings_section = 'core'
self.current_screen = None
self.identify_labels = []
def setup_ui(self):
"""
Set up the user interface elements
"""
self.setObjectName('self')
self.setStyleSheet(SCREENS_LAYOUT_STYLE)
self.tab_layout = QtWidgets.QVBoxLayout(self)
self.tab_layout.setObjectName('tab_layout')
self.screen_frame = QtWidgets.QFrame(self)
self.screen_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.screen_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.screen_frame.setObjectName('screen_frame')
self.screen_frame_layout = QtWidgets.QHBoxLayout(self.screen_frame)
self.screen_frame_layout.setContentsMargins(16, 16, 16, 16)
self.screen_frame_layout.setSpacing(8)
self.screen_frame_layout.setObjectName('screen_frame_layout')
self.tab_layout.addWidget(self.screen_frame)
self.screen_details_widget = QtWidgets.QWidget(self)
self.screen_details_widget.setObjectName('screen_details_widget')
self.screen_details_layout = QtWidgets.QGridLayout(self.screen_details_widget)
self.screen_details_layout.setSpacing(8)
self.screen_details_layout.setObjectName('screen_details_layout')
self.screen_number_label = QtWidgets.QLabel(self.screen_details_widget)
self.screen_number_label.setObjectName('screen_number_label')
self.screen_details_layout.addWidget(self.screen_number_label, 0, 0, 1, 4)
self.is_display_check_box = QtWidgets.QCheckBox(self.screen_details_widget)
self.is_display_check_box.setObjectName('is_display_check_box')
self.screen_details_layout.addWidget(self.is_display_check_box, 1, 0, 1, 4)
self.full_screen_radio_button = QtWidgets.QRadioButton(self.screen_details_widget)
self.full_screen_radio_button.setObjectName('full_screen_radio_button')
self.screen_details_layout.addWidget(self.full_screen_radio_button, 2, 0, 1, 4)
self.custom_geometry_button = QtWidgets.QRadioButton(self.screen_details_widget)
self.custom_geometry_button.setObjectName('custom_geometry_button')
self.screen_details_layout.addWidget(self.custom_geometry_button, 3, 0, 1, 4)
self.left_label = QtWidgets.QLabel(self.screen_details_widget)
self.left_label.setObjectName('left_label')
self.screen_details_layout.addWidget(self.left_label, 4, 1, 1, 1)
self.top_label = QtWidgets.QLabel(self.screen_details_widget)
self.top_label.setObjectName('top_label')
self.screen_details_layout.addWidget(self.top_label, 4, 2, 1, 1)
self.width_label = QtWidgets.QLabel(self.screen_details_widget)
self.width_label.setObjectName('width_label')
self.screen_details_layout.addWidget(self.width_label, 4, 3, 1, 1)
self.height_label = QtWidgets.QLabel(self.screen_details_widget)
self.height_label.setObjectName('height_label')
self.screen_details_layout.addWidget(self.height_label, 4, 4, 1, 1)
self.left_spin_box = QtWidgets.QSpinBox(self.screen_details_widget)
self.left_spin_box.setObjectName('left_spin_box')
self.screen_details_layout.addWidget(self.left_spin_box, 5, 1, 1, 1)
self.top_spin_box = QtWidgets.QSpinBox(self.screen_details_widget)
self.top_spin_box.setObjectName('top_spin_box')
self.screen_details_layout.addWidget(self.top_spin_box, 5, 2, 1, 1)
self.width_spin_box = QtWidgets.QSpinBox(self.screen_details_widget)
self.width_spin_box.setObjectName('width_spin_box')
self.screen_details_layout.addWidget(self.width_spin_box, 5, 3, 1, 1)
self.height_spin_box = QtWidgets.QSpinBox(self.screen_details_widget)
self.height_spin_box.setObjectName('height_spin_box')
self.screen_details_layout.addWidget(self.height_spin_box, 5, 4, 1, 1)
self.screen_details_layout.setColumnStretch(5, 1)
self.tab_layout.addWidget(self.screen_details_widget)
self.tab_layout.addStretch()
self.identify_button = QtWidgets.QPushButton(self)
self.identify_button.setGeometry(QtCore.QRect(596, 98, 124, 32))
self.identify_button.setObjectName('identify_button')
self.screen_button_group = QtWidgets.QButtonGroup(self.screen_frame)
self.screen_button_group.setExclusive(True)
self.screen_button_group.setObjectName('screen_button_group')
self.identify_button.clicked.connect(self.on_identify_button_clicked)
self._setup_spin_box(self.left_spin_box, 0, 9999, 0)
self._setup_spin_box(self.top_spin_box, 0, 9999, 0)
self._setup_spin_box(self.width_spin_box, 0, 9999, 0)
self._setup_spin_box(self.height_spin_box, 0, 9999, 0)
self.screen_selection_widget = ScreenSelectionWidget(self, ScreenList())
self.tab_layout.addWidget(self.screen_selection_widget)
self.generic_group_box = QtWidgets.QGroupBox(self)
self.generic_group_box.setObjectName('generic_group_box')
self.generic_group_layout = QtWidgets.QVBoxLayout(self.generic_group_box)
@ -165,19 +64,12 @@ class ScreensTab(SettingsTab):
self.generic_group_layout.addWidget(self.display_on_monitor_check)
self.tab_layout.addWidget(self.generic_group_box)
Registry().register_function('config_screen_changed', self.screen_selection_widget.load)
self.retranslate_ui()
def retranslate_ui(self):
self.setWindowTitle(translate('self', 'self'))
self.full_screen_radio_button.setText(translate('OpenLP.ScreensTab', 'F&ull screen'))
self.width_label.setText(translate('OpenLP.ScreensTab', 'Width:'))
self.is_display_check_box.setText(translate('OpenLP.ScreensTab', 'Use this screen as a display'))
self.left_label.setText(translate('OpenLP.ScreensTab', 'Left:'))
self.custom_geometry_button.setText(translate('OpenLP.ScreensTab', 'Custom &geometry'))
self.top_label.setText(translate('OpenLP.ScreensTab', 'Top:'))
self.height_label.setText(translate('OpenLP.ScreensTab', 'Height'))
self.screen_number_label.setText(translate('OpenLP.ScreensTab', '<strong>Screen 1</strong>'))
self.identify_button.setText(translate('OpenLP.ScreensTab', 'Identify Screens'))
self.setWindowTitle(translate('self', 'self')) # TODO: ???
self.generic_group_box.setTitle(translate('OpenLP.ScreensTab', 'Generic screen settings'))
self.display_on_monitor_check.setText(translate('OpenLP.ScreensTab', 'Display if a single screen'))
@ -187,130 +79,20 @@ class ScreensTab(SettingsTab):
NB: Don't call SettingsTab's resizeEvent() because we're not using its widgets.
"""
button_geometry = self.identify_button.geometry()
frame_geometry = self.screen_frame.geometry()
button_geometry.moveTop(frame_geometry.bottom() + 8)
button_geometry.moveRight(frame_geometry.right())
self.identify_button.setGeometry(button_geometry)
QtWidgets.QWidget.resizeEvent(self, event)
def show(self):
"""
Override show just to do some initialisation
"""
super(ScreensTab, self).show()
if self.screen_frame_layout.count() > 2:
self.screen_frame_layout.itemAt(1).widget().click()
def _setup_spin_box(self, spin_box, mininum, maximum, value):
"""
Set up the spin box
"""
spin_box.setMinimum(mininum)
spin_box.setMaximum(maximum)
spin_box.setValue(value)
def _save_screen(self, screen):
"""
Save the details in the UI to the screen
"""
if not screen:
return
screen.is_display = self.is_display_check_box.isChecked()
if self.custom_geometry_button.isChecked():
custom_geometry = QtCore.QRect()
custom_geometry.setTop(self.top_spin_box.value())
custom_geometry.setLeft(self.left_spin_box.value())
custom_geometry.setWidth(self.width_spin_box.value())
custom_geometry.setHeight(self.height_spin_box.value())
screen.custom_geometry = custom_geometry
else:
screen.custom_geometry = None
def load(self):
"""
Load the settings to populate the tab
"""
settings = Settings()
settings.beginGroup(self.settings_section)
# Remove all the existing items in the layout
while self.screen_frame_layout.count() > 0:
item = self.screen_frame_layout.takeAt(0)
if item.widget() is not None:
widget = item.widget()
if widget in self.screen_button_group.buttons():
self.screen_button_group.removeButton(widget)
widget.setParent(None)
widget.deleteLater()
del item
# Add the existing screens into the frame
self.screen_frame_layout.addStretch()
for screen in self.screens:
screen_button = ScreenButton(self.screen_frame, screen)
screen_button.clicked.connect(self.on_screen_button_clicked)
self.screen_frame_layout.addWidget(screen_button)
self.screen_button_group.addButton(screen_button)
self.screen_frame_layout.addStretch()
self.screen_selection_widget.load()
# Load generic settings
self.display_on_monitor_check.setChecked(Settings().value('core/display on monitor'))
def save(self):
"""
Save the screen settings
"""
self._save_screen(self.current_screen)
settings = Settings()
screen_settings = {}
for screen in self.screens:
screen_settings[screen.number] = screen.to_dict()
settings.setValue('core/screens', screen_settings)
self.screen_selection_widget.save()
settings.setValue('core/display on monitor', self.display_on_monitor_check.isChecked())
# On save update the screens as well
self.settings_form.register_post_process('config_screen_changed')
@QtCore.pyqtSlot()
def _on_identify_timer_shot(self):
for label in self.identify_labels:
label.hide()
label.setParent(None)
label.deleteLater()
self.identify_labels = []
def on_identify_button_clicked(self):
"""
Display a widget on every screen for 5 seconds
"""
for screen in self.screens:
label = QtWidgets.QLabel(None)
label.setAlignment(QtCore.Qt.AlignCenter)
label.font().setBold(True)
label.font().setPointSize(24)
label.setText('<font size="24">Screen {number}</font>'.format(number=screen.number + 1))
label.setStyleSheet('background-color: #0c0; color: #000; border: 5px solid #000;')
label.setGeometry(QtCore.QRect(screen.geometry.x(), screen.geometry.y(), 200, 100))
label.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint |
QtCore.Qt.WindowDoesNotAcceptFocus)
label.show()
self.identify_labels.append(label)
QtCore.QTimer.singleShot(3000, self._on_identify_timer_shot)
def on_screen_button_clicked(self):
"""
Respond to a screen button being clicked
"""
screen = self.sender().screen
if self.current_screen is not screen:
self._save_screen(self.current_screen)
self.screen_number_label.setText(str(screen))
self.is_display_check_box.setChecked(screen.is_display)
self.full_screen_radio_button.setChecked(screen.custom_geometry is None)
self.custom_geometry_button.setChecked(screen.custom_geometry is not None)
self._setup_spin_box(self.left_spin_box, screen.display_geometry.y(), screen.display_geometry.right(),
screen.display_geometry.x())
self._setup_spin_box(self.top_spin_box, screen.display_geometry.y(), screen.display_geometry.bottom(),
screen.display_geometry.y())
self._setup_spin_box(self.width_spin_box, 0, screen.display_geometry.width(), screen.display_geometry.width())
self._setup_spin_box(self.height_spin_box, 0, screen.display_geometry.height(),
screen.display_geometry.height())
self.current_screen = screen

View File

@ -22,12 +22,30 @@
"""
The :mod:`~openlp.core.widgets.widgets` module contains custom widgets used in OpenLP
"""
from PyQt5 import QtWidgets
from PyQt5 import QtCore, QtWidgets
from openlp.core.common.i18n import translate
from openlp.core.common.settings import ProxyMode, Settings
SCREENS_LAYOUT_STYLE = """
#screen_frame {
background-color: palette(base);
}
#screen_frame QPushButton {
background-color: palette(window);
border: 3px solid palette(text);
border-radius: 3px;
height: 100px;
outline: 0;
width: 150px;
}
#screen_frame QPushButton:checked {
border-color: palette(highlight);
}
"""
class ProxyWidget(QtWidgets.QGroupBox):
"""
A proxy settings widget that implements loading and saving its settings.
@ -130,3 +148,235 @@ class ProxyWidget(QtWidgets.QGroupBox):
settings.setValue('advanced/proxy https', self.https_edit.text())
settings.setValue('advanced/proxy username', self.username_edit.text())
settings.setValue('advanced/proxy password', self.password_edit.text())
class ScreenButton(QtWidgets.QPushButton):
"""
A special button class that holds the screen information about it
"""
def __init__(self, parent, screen):
"""
Initialise this button
"""
super().__init__(parent)
self.setObjectName('screen_{number}_button'.format(number=screen.number))
self.setCheckable(True)
self.setText(str(screen))
self.screen = screen
class ScreenSelectionWidget(QtWidgets.QWidget):
def __init__(self, parent=None, screens=[]):
super().__init__(parent)
self.current_screen = None
self.identify_labels = []
self.screens = screens
self.timer = QtCore.QTimer()
self.timer.setSingleShot(True)
self.timer.setInterval(3000)
self.timer.timeout.connect(self._on_identify_timer_shot)
self.setup_ui()
def setup_ui(self):
self.setStyleSheet(SCREENS_LAYOUT_STYLE)
self.layout = QtWidgets.QVBoxLayout(self)
self.screen_frame = QtWidgets.QFrame(self)
self.screen_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.screen_frame.setFrameShadow(QtWidgets.QFrame.Sunken)
self.screen_frame.setObjectName('screen_frame')
self.screen_frame_layout = QtWidgets.QHBoxLayout(self.screen_frame)
self.screen_frame_layout.setContentsMargins(16, 16, 16, 16)
self.screen_frame_layout.setSpacing(8)
self.screen_frame_layout.setObjectName('screen_frame_layout')
self.layout.addWidget(self.screen_frame)
self.identify_layout = QtWidgets.QHBoxLayout(self)
self.screen_details_layout = QtWidgets.QVBoxLayout(self)
self.screen_details_layout.setObjectName('screen_details_layout')
self.screen_number_label = QtWidgets.QLabel(self)
self.screen_number_label.setObjectName('screen_number_label')
self.screen_details_layout.addWidget(self.screen_number_label)
self.display_group_box = QtWidgets.QGroupBox(self)
self.display_group_box.setObjectName('display_group_box')
self.display_group_box.setCheckable(True)
self.display_group_box_layout = QtWidgets.QGridLayout(self.display_group_box)
self.display_group_box_layout.setSpacing(8)
self.display_group_box_layout.setObjectName('display_group_box_layout')
self.full_screen_radio_button = QtWidgets.QRadioButton(self.display_group_box)
self.full_screen_radio_button.setObjectName('full_screen_radio_button')
self.display_group_box_layout.addWidget(self.full_screen_radio_button, 0, 0, 1, 4)
self.custom_geometry_button = QtWidgets.QRadioButton(self.display_group_box)
self.custom_geometry_button.setObjectName('custom_geometry_button')
self.display_group_box_layout.addWidget(self.custom_geometry_button, 1, 0, 1, 4)
self.left_label = QtWidgets.QLabel(self.display_group_box)
self.left_label.setObjectName('left_label')
self.display_group_box_layout.addWidget(self.left_label, 2, 1, 1, 1)
self.top_label = QtWidgets.QLabel(self.display_group_box)
self.top_label.setObjectName('top_label')
self.display_group_box_layout.addWidget(self.top_label, 2, 2, 1, 1)
self.width_label = QtWidgets.QLabel(self.display_group_box)
self.width_label.setObjectName('width_label')
self.display_group_box_layout.addWidget(self.width_label, 2, 3, 1, 1)
self.height_label = QtWidgets.QLabel(self.display_group_box)
self.height_label.setObjectName('height_label')
self.display_group_box_layout.addWidget(self.height_label, 2, 4, 1, 1)
self.left_spin_box = QtWidgets.QSpinBox(self.display_group_box)
self.left_spin_box.setObjectName('left_spin_box')
self.left_spin_box.setEnabled(False)
self.display_group_box_layout.addWidget(self.left_spin_box, 3, 1, 1, 1)
self.top_spin_box = QtWidgets.QSpinBox(self.display_group_box)
self.top_spin_box.setObjectName('top_spin_box')
self.top_spin_box.setEnabled(False)
self.display_group_box_layout.addWidget(self.top_spin_box, 3, 2, 1, 1)
self.width_spin_box = QtWidgets.QSpinBox(self.display_group_box)
self.width_spin_box.setObjectName('width_spin_box')
self.width_spin_box.setEnabled(False)
self.display_group_box_layout.addWidget(self.width_spin_box, 3, 3, 1, 1)
self.height_spin_box = QtWidgets.QSpinBox(self.display_group_box)
self.height_spin_box.setObjectName('height_spin_box')
self.height_spin_box.setEnabled(False)
self.display_group_box_layout.addWidget(self.height_spin_box, 3, 4, 1, 1)
self.display_group_box_layout.setColumnStretch(3, 1)
self.display_group_box.setLayout(self.display_group_box_layout)
self.screen_details_layout.addWidget(self.display_group_box)
self.identify_layout.addLayout(self.screen_details_layout)
self.identify_button = QtWidgets.QPushButton(self)
self.identify_button.setObjectName('identify_button')
self.identify_layout.addWidget(
self.identify_button, stretch=1, alignment=QtCore.Qt.AlignRight | QtCore.Qt.AlignTop)
self.screen_button_group = QtWidgets.QButtonGroup(self.screen_frame)
self.screen_button_group.setExclusive(True)
self.screen_button_group.setObjectName('screen_button_group')
self.layout.addLayout(self.identify_layout)
self.layout.addStretch()
# Signals and slots
self.custom_geometry_button.toggled.connect(self.height_spin_box.setEnabled)
self.custom_geometry_button.toggled.connect(self.left_spin_box.setEnabled)
self.custom_geometry_button.toggled.connect(self.top_spin_box.setEnabled)
self.custom_geometry_button.toggled.connect(self.width_spin_box.setEnabled)
self.identify_button.clicked.connect(self.on_identify_button_clicked)
self._setup_spin_box(self.left_spin_box, 0, 9999, 0)
self._setup_spin_box(self.top_spin_box, 0, 9999, 0)
self._setup_spin_box(self.width_spin_box, 0, 9999, 0)
self._setup_spin_box(self.height_spin_box, 0, 9999, 0)
self.retranslate_ui()
def retranslate_ui(self):
self.full_screen_radio_button.setText(translate('OpenLP.ScreensTab', 'F&ull screen'))
self.width_label.setText(translate('OpenLP.ScreensTab', 'Width:'))
self.display_group_box.setTitle(translate('OpenLP.ScreensTab', 'Use this screen as a display'))
self.left_label.setText(translate('OpenLP.ScreensTab', 'Left:'))
self.custom_geometry_button.setText(translate('OpenLP.ScreensTab', 'Custom &geometry'))
self.top_label.setText(translate('OpenLP.ScreensTab', 'Top:'))
self.height_label.setText(translate('OpenLP.ScreensTab', 'Height:'))
self.identify_button.setText(translate('OpenLP.ScreensTab', 'Identify Screens'))
def _save_screen(self, screen):
"""
Save the details in the UI to the screen
:param openlp.core.display.screens.Screen screen:
:return: None
"""
if not screen:
return
screen.is_display = self.display_group_box.isChecked()
if self.custom_geometry_button.isChecked():
screen.custom_geometry = QtCore.QRect(self.left_spin_box.value(), self.top_spin_box.value(),
self.width_spin_box.value(), self.height_spin_box.value())
else:
screen.custom_geometry = None
def _setup_spin_box(self, spin_box, mininum, maximum, value):
"""
Set up the spin box
:param QtWidgets.QSpinBox spin_box:
:param int minimun:
:param int maximum:
:param int value:
:return: None
"""
spin_box.setMinimum(mininum)
spin_box.setMaximum(maximum)
spin_box.setValue(value)
def load(self):
# Remove all the existing items in the layout
while self.screen_frame_layout.count() > 0:
item = self.screen_frame_layout.takeAt(0)
if item.widget() is not None:
widget = item.widget()
if widget in self.screen_button_group.buttons():
self.screen_button_group.removeButton(widget)
widget.setParent(None)
widget.deleteLater()
del item
# Add the existing screens into the frame
self.screen_frame_layout.addStretch()
for screen in self.screens:
screen_button = ScreenButton(self.screen_frame, screen)
screen_button.clicked.connect(self.on_screen_button_clicked)
if not self.current_screen or screen.is_display:
screen_button.click()
self.screen_frame_layout.addWidget(screen_button)
self.screen_button_group.addButton(screen_button)
self.screen_frame_layout.addStretch()
def save(self):
"""
Save the screen settings
"""
self._save_screen(self.current_screen)
settings = Settings()
screen_settings = {}
for screen in self.screens:
screen_settings[screen.number] = screen.to_dict()
settings.setValue('core/screens', screen_settings)
# On save update the screens as well
@QtCore.pyqtSlot()
def _on_identify_timer_shot(self):
for label in self.identify_labels:
label.hide()
label.setParent(None)
label.deleteLater()
self.identify_labels = []
def on_identify_button_clicked(self):
"""
Display a widget on every screen for 5 seconds
"""
for screen in self.screens:
label = QtWidgets.QLabel(None)
label.setAlignment(QtCore.Qt.AlignCenter)
label.setText(str(screen))
label.setStyleSheet('font-size: 24pt; font-weight: bold;'
'background-color: #0C0; color: #000; border: 5px solid #000;')
label.setGeometry(QtCore.QRect(screen.geometry.x(), screen.geometry.y(), screen.geometry.width(), 100))
label.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Tool | QtCore.Qt.WindowStaysOnTopHint |
QtCore.Qt.WindowDoesNotAcceptFocus)
label.show()
self.identify_labels.append(label)
self.timer.start()
def on_screen_button_clicked(self):
"""
Respond to a screen button being clicked
"""
screen = self.sender().screen
if self.current_screen is not screen:
self._save_screen(self.current_screen)
self.screen_number_label.setText(str(screen))
self.display_group_box.setChecked(screen.is_display)
self.full_screen_radio_button.setChecked(screen.custom_geometry is None)
self.custom_geometry_button.setChecked(screen.custom_geometry is not None)
self._setup_spin_box(self.left_spin_box, screen.display_geometry.y(), screen.display_geometry.right(),
screen.display_geometry.x())
self._setup_spin_box(self.top_spin_box, screen.display_geometry.y(), screen.display_geometry.bottom(),
screen.display_geometry.y())
self._setup_spin_box(self.width_spin_box, 0, screen.display_geometry.width(), screen.display_geometry.width())
self._setup_spin_box(self.height_spin_box, 0, screen.display_geometry.height(),
screen.display_geometry.height())
self.current_screen = screen

View File

@ -0,0 +1,199 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2018 OpenLP Developers #
# --------------------------------------------------------------------------- #
# 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 #
###############################################################################
"""
Package to test the openlp.core.widgets.widgets package.
"""
from unittest import TestCase
from unittest.mock import MagicMock, patch
from PyQt5 import QtCore, QtWidgets
from openlp.core.display.screens import Screen
from openlp.core.widgets.widgets import ScreenButton, ScreenSelectionWidget
class TestSceenButton(TestCase):
def test_screen_button_initialisation(self):
"""
Test the initialisation of the ScreenButton object
"""
# GIVEN: A mocked screen object
screen_mock = MagicMock(spec=Screen)
screen_mock.number = 0
screen_mock.__str__.return_value = 'Mocked Screen Object'
# WHEN: initialising the ScreenButton object
instance = ScreenButton(None, screen_mock)
# THEN: The ScreenButton should have been initalised correctly with the data from the mocked screen object
assert isinstance(instance, QtWidgets.QPushButton)
assert instance.objectName() == 'screen_0_button'
assert instance.isCheckable() is True
assert instance.text() == 'Mocked Screen Object'
class TestScreenSelectionWidget(TestCase):
def setUp(self):
patched_qtimer = patch('openlp.core.widgets.widgets.QtCore.QTimer')
self.addCleanup(patched_qtimer.stop)
self.timer_mock = MagicMock(spec=QtCore.QTimer)
qtimer_mock = patched_qtimer.start()
qtimer_mock.return_value = self.timer_mock
patched_screen_selection_widget_setup_ui = patch.object(ScreenSelectionWidget, 'setup_ui')
self.addCleanup(patched_screen_selection_widget_setup_ui.stop)
patched_screen_selection_widget_setup_ui.start()
def test_init_default_args(self):
"""
Test the initialisation of ScreenSelectionWidget, when initialised with default arguments
"""
# GIVEN: The ScreenSelectionWidget class
# WHEN: Initialising ScreenSelectionWidget with default arguments
instance = ScreenSelectionWidget()
# THEN: ScreenSelectionWidget should be an instance of QWidget and the screens attribute should be an empty list
assert isinstance(instance, QtWidgets.QWidget)
assert instance.screens == []
self.timer_mock.setSingleShot.assert_called_once_with(True)
self.timer_mock.setInterval.assert_called_once_with(3000)
def test_init_with_args(self):
"""
Test the initialisation of ScreenSelectionWidget, when initialised with the screens keyword arg set
"""
# GIVEN: The ScreenSelectionWidget class
screens_object_mock = MagicMock()
# WHEN: Initialising ScreenSelectionWidget with the screens keyword arg set
instance = ScreenSelectionWidget(screens=screens_object_mock)
# THEN: ScreenSelectionWidget should be an instance of QWidget and the screens attribute should the mock used
assert isinstance(instance, QtWidgets.QWidget)
assert instance.screens is screens_object_mock
self.timer_mock.setSingleShot.assert_called_once_with(True)
self.timer_mock.setInterval.assert_called_once_with(3000)
def test_save_screen_none(self):
"""
Test ScreenSelectionWidget._save_screen when called with the screen arg set as None
"""
# GIVEN: An instance of the ScreenSelectionWidget
instance = ScreenSelectionWidget()
instance.display_group_box = MagicMock(spec=QtWidgets.QGroupBox)
# WHEN: Calling _save_screen and no screen is selected
instance._save_screen(None)
# THEN: _save_screen should return without attempting to write to the screen object
instance.display_group_box.isChecked.assert_not_called()
def test_save_screen_not_display(self):
"""
Test ScreenSelectionWidget._save_screen when the display_group_box is not checked.
"""
# GIVEN: An instance of the ScreenSelectionWidget, and a mocked group_box
instance = ScreenSelectionWidget()
instance.display_group_box = MagicMock(spec=QtWidgets.QGroupBox)
instance.custom_geometry_button = MagicMock(spec=QtWidgets.QRadioButton, **{'isChecked.return_value': False})
mocked_screen_object = MagicMock(spec=Screen)
mocked_screen_object.is_dislpay = True
# WHEN: display_group_box isn't checked and _save_screen is called with a mocked Screen object.
instance.display_group_box.isChecked.return_value = False
instance._save_screen(mocked_screen_object)
# THEN: _save_screen should should be set to False
assert mocked_screen_object.is_display is False
def test_save_screen_display(self):
"""
Test ScreenSelectionWidget._save_screen when the display_group_box is checked.
"""
# GIVEN: An instance of the ScreenSelectionWidget, and a mocked group_box
instance = ScreenSelectionWidget()
instance.display_group_box = MagicMock(spec=QtWidgets.QGroupBox)
instance.custom_geometry_button = MagicMock(spec=QtWidgets.QRadioButton, **{'isChecked.return_value': False})
mocked_screen_object = MagicMock(spec=Screen)
# WHEN: display_group_box is checked and _save_screen is called with a mocked Screen object.
instance.display_group_box.isChecked.return_value = True
instance._save_screen(mocked_screen_object)
# THEN: _save_screen should should be set to True
assert mocked_screen_object.is_display is True
@patch('openlp.core.widgets.widgets.QtCore.QRect')
def test_save_screen_full_screen(self, mocked_q_rect):
"""
Test ScreenSelectionWidget._save_screen when the display is set to full screen
"""
# GIVEN: An instance of the ScreenSelectionWidget, and a mocked custom_geometry_button
instance = ScreenSelectionWidget()
instance.display_group_box = MagicMock(spec=QtWidgets.QGroupBox)
instance.custom_geometry_button = MagicMock(spec=QtWidgets.QRadioButton)
mocked_screen_object = MagicMock(spec=Screen)
# WHEN: custom_geometry_button isn't checked and _save_screen is called with a mocked Screen object.
instance.custom_geometry_button.isChecked.return_value = False
instance._save_screen(mocked_screen_object)
# THEN: _save_screen should not attempt to save a custom geometry
mocked_q_rect.assert_not_called()
@patch('openlp.core.widgets.widgets.QtCore.QRect')
def test_save_screen_custom_geometry(self, mocked_q_rect):
"""
Test ScreenSelectionWidget._save_screen when a custom geometry is set
"""
# GIVEN: An instance of the ScreenSelectionWidget, and a mocked custom_geometry_button
instance = ScreenSelectionWidget()
instance.display_group_box = MagicMock(spec=QtWidgets.QGroupBox)
instance.custom_geometry_button = MagicMock(spec=QtWidgets.QRadioButton)
instance.left_spin_box = MagicMock(spec=QtWidgets.QSpinBox, **{'value.return_value': 100})
instance.top_spin_box = MagicMock(spec=QtWidgets.QSpinBox, **{'value.return_value': 200})
instance.width_spin_box = MagicMock(spec=QtWidgets.QSpinBox, **{'value.return_value': 300})
instance.height_spin_box = MagicMock(spec=QtWidgets.QSpinBox, **{'value.return_value': 400})
mocked_screen_object = MagicMock(spec=Screen)
# WHEN: custom_geometry_button is checked and _save_screen is called with a mocked Screen object.
instance.custom_geometry_button.isChecked.return_value = True
instance._save_screen(mocked_screen_object)
# THEN: _save_screen should save the custom geometry
mocked_q_rect.assert_called_once_with(100, 200, 300, 400)
def test_setup_spin_box(self):
"""
Test that ScreenSelectionWidget._setup_spin_box sets up the given spinbox correctly
"""
# GIVEN: An instance of the ScreenSelectionWidget class and a mocked spin box object
instance = ScreenSelectionWidget()
spin_box_mock = MagicMock(spec=QtWidgets.QSpinBox)
# WHEN: Calling _setup_spin_box with the mocked spin box object and some sample values
instance._setup_spin_box(spin_box_mock, 0, 100, 50)
# THEN: The mocked spin box object should have been set up with the specified values
spin_box_mock.setMinimum.assert_called_once_with(0)
spin_box_mock.setMaximum.assert_called_once_with(100)
spin_box_mock.setValue.assert_called_once_with(50)