From 288a02344d7f3ae4bbedeccd913044fc040927dc Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Fri, 22 Nov 2019 16:40:10 +0000 Subject: [PATCH] Font selection widget - Create a font selection widget - Embed widget in the Theme wizard - Add tests for the FontSelectWidget --- openlp/core/ui/icons.py | 2 + openlp/core/ui/themeform.py | 98 ++-- openlp/core/ui/themewizard.py | 109 +--- openlp/core/widgets/widgets.py | 353 ++++++++++++- openlp/plugins/bibles/lib/upgrade.py | 2 +- tests/openlp_core/widgets/test_widgets.py | 604 +++++++++++++++++++++- 6 files changed, 995 insertions(+), 173 deletions(-) diff --git a/openlp/core/ui/icons.py b/openlp/core/ui/icons.py index 8a565b4bc..09dd78a0f 100644 --- a/openlp/core/ui/icons.py +++ b/openlp/core/ui/icons.py @@ -66,6 +66,7 @@ class UiIcons(metaclass=Singleton): 'bible': {'icon': 'fa.book'}, 'blank': {'icon': 'fa.times-circle'}, 'blank_theme': {'icon': 'fa.file-image-o'}, + 'bold': {'icon': 'fa.bold'}, 'book': {'icon': 'fa.book'}, 'bottom': {'icon': 'fa.angle-double-down'}, 'box': {'icon': 'fa.briefcase'}, @@ -88,6 +89,7 @@ class UiIcons(metaclass=Singleton): 'group': {'icon': 'fa.object-group'}, 'inactive': {'icon': 'fa.child', 'attr': 'lightGray'}, 'info': {'icon': 'fa.info'}, + 'italic': {'icon': 'fa.italic'}, 'light_bulb': {'icon': 'fa.lightbulb-o'}, 'live': {'icon': 'fa.eye'}, 'manual': {'icon': 'fa.graduation-cap'}, diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index c769c64d6..edb7e5359 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -80,22 +80,19 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): visible=visible_formats, actual=actual_formats) self.video_path_edit.filters = '{video};;{ui} (*)'.format(video=video_filter, ui=UiStrings().AllFiles) self.video_path_edit.pathChanged.connect(self.on_video_path_edit_path_changed) - self.main_color_button.colorChanged.connect(self.on_main_color_changed) - self.outline_color_button.colorChanged.connect(self.on_outline_color_changed) - self.shadow_color_button.colorChanged.connect(self.on_shadow_color_changed) - self.outline_check_box.stateChanged.connect(self.on_outline_check_check_box_state_changed) - self.shadow_check_box.stateChanged.connect(self.on_shadow_check_check_box_state_changed) self.footer_color_button.colorChanged.connect(self.on_footer_color_changed) self.customButtonClicked.connect(self.on_custom_1_button_clicked) self.main_position_check_box.stateChanged.connect(self.on_main_position_check_box_state_changed) self.footer_position_check_box.stateChanged.connect(self.on_footer_position_check_box_state_changed) self.currentIdChanged.connect(self.on_current_id_changed) Registry().register_function('theme_line_count', self.update_lines_text) - self.main_size_spin_box.valueChanged.connect(self.calculate_lines) - self.line_spacing_spin_box.valueChanged.connect(self.calculate_lines) - self.outline_size_spin_box.valueChanged.connect(self.calculate_lines) - self.shadow_size_spin_box.valueChanged.connect(self.calculate_lines) - self.main_font_combo_box.activated.connect(self.calculate_lines) + self.main_font.font_name_changed.connect(self.calculate_lines) + self.main_font.font_size_changed.connect(self.calculate_lines) + self.main_font.line_spacing_changed.connect(self.calculate_lines) + self.main_font.is_outline_enabled_changed.connect(self.on_outline_toggled) + self.main_font.outline_size_changed.connect(self.calculate_lines) + self.main_font.is_shadow_enabled_changed.connect(self.on_shadow_toggled) + self.main_font.shadow_size_changed.connect(self.calculate_lines) self.footer_font_combo_box.activated.connect(self.update_theme) self.footer_size_spin_box.valueChanged.connect(self.update_theme) self.transitions_check_box.stateChanged.connect(self.on_transitions_check_box_state_changed) @@ -123,17 +120,6 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): self.background_page.registerField('background_image', self.image_path_edit, 'path', self.image_path_edit.pathChanged) self.background_page.registerField('gradient', self.gradient_combo_box) - self.main_area_page.registerField('main_color_button', self.main_color_button) - self.main_area_page.registerField('main_size_spin_box', self.main_size_spin_box) - self.main_area_page.registerField('line_spacing_spin_box', self.line_spacing_spin_box) - self.main_area_page.registerField('outline_check_box', self.outline_check_box) - self.main_area_page.registerField('outline_color_button', self.outline_color_button) - self.main_area_page.registerField('outline_size_spin_box', self.outline_size_spin_box) - self.main_area_page.registerField('shadow_check_box', self.shadow_check_box) - self.main_area_page.registerField('main_bold_check_box', self.main_bold_check_box) - self.main_area_page.registerField('main_italics_check_box', self.main_italics_check_box) - self.main_area_page.registerField('shadow_color_button', self.shadow_color_button) - self.main_area_page.registerField('shadow_size_spin_box', self.shadow_size_spin_box) self.main_area_page.registerField('footer_size_spin_box', self.footer_size_spin_box) self.area_position_page.registerField('main_position_x', self.main_x_spin_box) self.area_position_page.registerField('main_position_y', self.main_y_spin_box) @@ -150,7 +136,7 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): self.background_page.registerField('slide_transition_speed', self.transition_speed_combo_box) self.background_page.registerField('name', self.theme_name_edit) - def calculate_lines(self): + def calculate_lines(self, *args): """ Calculate the number of lines on a page by rendering text """ @@ -239,24 +225,20 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): paint.end() self.theme_layout_form.exec(pixmap) - def on_outline_check_check_box_state_changed(self, state): + def on_outline_toggled(self, is_enabled): """ Change state as Outline check box changed """ if self.update_theme_allowed: - self.theme.font_main_outline = state == QtCore.Qt.Checked - self.outline_color_button.setEnabled(self.theme.font_main_outline) - self.outline_size_spin_box.setEnabled(self.theme.font_main_outline) + self.theme.font_main_outline = is_enabled self.calculate_lines() - def on_shadow_check_check_box_state_changed(self, state): + def on_shadow_toggled(self, is_enabled): """ Change state as Shadow check box changed """ if self.update_theme_allowed: - self.theme.font_main_shadow = state == QtCore.Qt.Checked - self.shadow_color_button.setEnabled(self.theme.font_main_shadow) - self.shadow_size_spin_box.setEnabled(self.theme.font_main_shadow) + self.theme.font_main_shadow = is_enabled self.calculate_lines() def on_main_position_check_box_state_changed(self, value): @@ -360,18 +342,18 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): """ Handle the display and state of the Main Area page. """ - self.main_font_combo_box.setCurrentFont(QtGui.QFont(self.theme.font_main_name)) - self.main_color_button.color = self.theme.font_main_color - self.setField('main_size_spin_box', self.theme.font_main_size) - self.setField('line_spacing_spin_box', self.theme.font_main_line_adjustment) - self.setField('outline_check_box', self.theme.font_main_outline) - self.outline_color_button.color = self.theme.font_main_outline_color - self.setField('outline_size_spin_box', self.theme.font_main_outline_size) - self.setField('shadow_check_box', self.theme.font_main_shadow) - self.shadow_color_button.color = self.theme.font_main_shadow_color - self.setField('shadow_size_spin_box', self.theme.font_main_shadow_size) - self.setField('main_bold_check_box', self.theme.font_main_bold) - self.setField('main_italics_check_box', self.theme.font_main_italics) + self.main_font.font_name = self.theme.font_main_name + self.main_font.font_color = self.theme.font_main_color + self.main_font.font_size = self.theme.font_main_size + self.main_font.line_spacing = self.theme.font_main_line_adjustment + self.main_font.is_outline_enabled = self.theme.font_main_outline + self.main_font.outline_color = self.theme.font_main_outline_color + self.main_font.outline_size = self.theme.font_main_outline_size + self.main_font.is_shadow_enabled = self.theme.font_main_shadow + self.main_font.shadow_color = self.theme.font_main_shadow_color + self.main_font.shadow_size = self.theme.font_main_shadow_size + self.main_font.is_bold = self.theme.font_main_bold + self.main_font.is_italic = self.theme.font_main_italics def set_footer_area_page_values(self): """ @@ -494,24 +476,6 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): self.theme.background_filename = new_path self.set_background_page_values() - def on_main_color_changed(self, color): - """ - Set the main colour value - """ - self.theme.font_main_color = color - - def on_outline_color_changed(self, color): - """ - Set the outline colour value - """ - self.theme.font_main_outline_color = color - - def on_shadow_color_changed(self, color): - """ - Set the shadow colour value - """ - self.theme.font_main_shadow_color = color - def on_footer_color_changed(self, color): """ Set the footer colour value @@ -527,13 +491,13 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): return log.debug('update_theme') # main page - self.theme.font_main_name = self.main_font_combo_box.currentFont().family() - self.theme.font_main_size = self.field('main_size_spin_box') - self.theme.font_main_line_adjustment = self.field('line_spacing_spin_box') - self.theme.font_main_outline_size = self.field('outline_size_spin_box') - self.theme.font_main_shadow_size = self.field('shadow_size_spin_box') - self.theme.font_main_bold = self.field('main_bold_check_box') - self.theme.font_main_italics = self.field('main_italics_check_box') + self.theme.font_main_name = self.main_font.font_name + self.theme.font_main_size = self.main_font.font_size + self.theme.font_main_line_adjustment = self.main_font.line_spacing + self.theme.font_main_outline_size = self.main_font.outline_size + self.theme.font_main_shadow_size = self.main_font.shadow_size + self.theme.font_main_bold = self.main_font.is_bold + self.theme.font_main_italics = self.main_font.is_italic # footer page self.theme.font_footer_name = self.footer_font_combo_box.currentFont().family() self.theme.font_footer_size = self.field('footer_size_spin_box') diff --git a/openlp/core/ui/themewizard.py b/openlp/core/ui/themewizard.py index b1fcc578b..9b902b7fc 100644 --- a/openlp/core/ui/themewizard.py +++ b/openlp/core/ui/themewizard.py @@ -25,19 +25,15 @@ from PyQt5 import QtCore, QtGui, QtWidgets from openlp.core.common import is_macosx from openlp.core.common.i18n import UiStrings, translate -from openlp.core.lib.theme import ( - BackgroundGradientType, - BackgroundType, - HorizontalType, - TransitionType, +from openlp.core.display.render import ThemePreviewRenderer +from openlp.core.lib.theme import BackgroundGradientType, BackgroundType, HorizontalType, TransitionType, \ TransitionSpeed -) from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets from openlp.core.ui.icons import UiIcons from openlp.core.widgets.buttons import ColorButton from openlp.core.widgets.edits import PathEdit from openlp.core.widgets.layouts import AspectRatioLayout -from openlp.core.display.render import ThemePreviewRenderer +from openlp.core.widgets.widgets import FontSelectWidget class Ui_ThemeWizard(object): @@ -54,7 +50,7 @@ class Ui_ThemeWizard(object): theme_wizard.setOptions(QtWidgets.QWizard.IndependentPages | QtWidgets.QWizard.NoBackButtonOnStartPage | QtWidgets.QWizard.HaveCustomButton1) theme_wizard.setFixedWidth(640) - if is_macosx(): + if is_macosx(): # pragma: no cover theme_wizard.setPixmap(QtWidgets.QWizard.BackgroundPixmap, QtGui.QPixmap(':/wizards/openlp-osx-wizard.png')) else: theme_wizard.setWizardStyle(QtWidgets.QWizard.ModernStyle) @@ -160,83 +156,10 @@ class Ui_ThemeWizard(object): # Main Area Page self.main_area_page = QtWidgets.QWizardPage() self.main_area_page.setObjectName('main_area_page') - self.main_area_layout = QtWidgets.QFormLayout(self.main_area_page) + self.main_area_layout = QtWidgets.QVBoxLayout(self.main_area_page) self.main_area_layout.setObjectName('main_area_layout') - self.main_font_label = QtWidgets.QLabel(self.main_area_page) - self.main_font_label.setObjectName('main_font_label') - self.main_font_combo_box = QtWidgets.QFontComboBox(self.main_area_page) - self.main_font_combo_box.setObjectName('main_font_combo_box') - self.main_area_layout.addRow(self.main_font_label, self.main_font_combo_box) - self.main_color_label = QtWidgets.QLabel(self.main_area_page) - self.main_color_label.setObjectName('main_color_label') - self.main_properties_layout = QtWidgets.QHBoxLayout() - self.main_properties_layout.setObjectName('main_properties_layout') - self.main_color_button = ColorButton(self.main_area_page) - self.main_color_button.setObjectName('main_color_button') - self.main_properties_layout.addWidget(self.main_color_button) - self.main_properties_layout.addSpacing(20) - self.main_bold_check_box = QtWidgets.QCheckBox(self.main_area_page) - self.main_bold_check_box.setObjectName('main_bold_check_box') - self.main_properties_layout.addWidget(self.main_bold_check_box) - self.main_properties_layout.addSpacing(20) - self.main_italics_check_box = QtWidgets.QCheckBox(self.main_area_page) - self.main_italics_check_box.setObjectName('MainItalicsCheckBox') - self.main_properties_layout.addWidget(self.main_italics_check_box) - self.main_area_layout.addRow(self.main_color_label, self.main_properties_layout) - self.main_size_label = QtWidgets.QLabel(self.main_area_page) - self.main_size_label.setObjectName('main_size_label') - self.main_size_layout = QtWidgets.QHBoxLayout() - self.main_size_layout.setObjectName('main_size_layout') - self.main_size_spin_box = QtWidgets.QSpinBox(self.main_area_page) - self.main_size_spin_box.setMaximum(999) - self.main_size_spin_box.setValue(16) - self.main_size_spin_box.setObjectName('main_size_spin_box') - self.main_size_layout.addWidget(self.main_size_spin_box) - self.main_line_count_label = QtWidgets.QLabel(self.main_area_page) - self.main_line_count_label.setObjectName('main_line_count_label') - self.main_size_layout.addWidget(self.main_line_count_label) - self.main_area_layout.addRow(self.main_size_label, self.main_size_layout) - self.line_spacing_label = QtWidgets.QLabel(self.main_area_page) - self.line_spacing_label.setObjectName('line_spacing_label') - self.line_spacing_spin_box = QtWidgets.QSpinBox(self.main_area_page) - self.line_spacing_spin_box.setMinimum(-250) - self.line_spacing_spin_box.setMaximum(250) - self.line_spacing_spin_box.setObjectName('line_spacing_spin_box') - self.main_area_layout.addRow(self.line_spacing_label, self.line_spacing_spin_box) - self.outline_check_box = QtWidgets.QCheckBox(self.main_area_page) - self.outline_check_box.setObjectName('outline_check_box') - self.outline_layout = QtWidgets.QHBoxLayout() - self.outline_layout.setObjectName('outline_layout') - self.outline_color_button = ColorButton(self.main_area_page) - self.outline_color_button.setEnabled(False) - self.outline_color_button.setObjectName('Outline_color_button') - self.outline_layout.addWidget(self.outline_color_button) - self.outline_layout.addSpacing(20) - self.outline_size_label = QtWidgets.QLabel(self.main_area_page) - self.outline_size_label.setObjectName('outline_size_label') - self.outline_layout.addWidget(self.outline_size_label) - self.outline_size_spin_box = QtWidgets.QSpinBox(self.main_area_page) - self.outline_size_spin_box.setEnabled(False) - self.outline_size_spin_box.setObjectName('outline_size_spin_box') - self.outline_layout.addWidget(self.outline_size_spin_box) - self.main_area_layout.addRow(self.outline_check_box, self.outline_layout) - self.shadow_check_box = QtWidgets.QCheckBox(self.main_area_page) - self.shadow_check_box.setObjectName('shadow_check_box') - self.shadow_layout = QtWidgets.QHBoxLayout() - self.shadow_layout.setObjectName('shadow_layout') - self.shadow_color_button = ColorButton(self.main_area_page) - self.shadow_color_button.setEnabled(False) - self.shadow_color_button.setObjectName('shadow_color_button') - self.shadow_layout.addWidget(self.shadow_color_button) - self.shadow_layout.addSpacing(20) - self.shadow_size_label = QtWidgets.QLabel(self.main_area_page) - self.shadow_size_label.setObjectName('shadow_size_label') - self.shadow_layout.addWidget(self.shadow_size_label) - self.shadow_size_spin_box = QtWidgets.QSpinBox(self.main_area_page) - self.shadow_size_spin_box.setEnabled(False) - self.shadow_size_spin_box.setObjectName('shadow_size_spin_box') - self.shadow_layout.addWidget(self.shadow_size_spin_box) - self.main_area_layout.addRow(self.shadow_check_box, self.shadow_layout) + self.main_font = FontSelectWidget(self.main_area_page) + self.main_area_layout.addWidget(self.main_font) theme_wizard.addPage(self.main_area_page) # Footer Area Page self.footer_area_page = QtWidgets.QWizardPage() @@ -391,10 +314,6 @@ class Ui_ThemeWizard(object): theme_wizard.addPage(self.preview_page) self.retranslate_ui(theme_wizard) self.background_combo_box.currentIndexChanged.connect(self.background_stack.setCurrentIndex) - self.outline_check_box.toggled.connect(self.outline_color_button.setEnabled) - self.outline_check_box.toggled.connect(self.outline_size_spin_box.setEnabled) - self.shadow_check_box.toggled.connect(self.shadow_color_button.setEnabled) - self.shadow_check_box.toggled.connect(self.shadow_size_spin_box.setEnabled) self.main_position_check_box.toggled.connect(self.main_x_spin_box.setDisabled) self.main_position_check_box.toggled.connect(self.main_y_spin_box.setDisabled) self.main_position_check_box.toggled.connect(self.main_width_spin_box.setDisabled) @@ -444,20 +363,6 @@ class Ui_ThemeWizard(object): self.main_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Main Area Font Details')) self.main_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display ' 'characteristics for the Display text')) - self.main_font_label.setText(translate('OpenLP.ThemeWizard', 'Font:')) - self.main_color_label.setText(translate('OpenLP.ThemeWizard', 'color:')) - self.main_size_label.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.main_size_spin_box.setSuffix(' {unit}'.format(unit=UiStrings().FontSizePtUnit)) - self.line_spacing_label.setText(translate('OpenLP.ThemeWizard', 'Line Spacing:')) - self.line_spacing_spin_box.setSuffix(' {unit}'.format(unit=UiStrings().FontSizePtUnit)) - self.outline_check_box.setText(translate('OpenLP.ThemeWizard', '&Outline:')) - self.outline_size_label.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.outline_size_spin_box.setSuffix(' {unit}'.format(unit=UiStrings().FontSizePtUnit)) - self.shadow_check_box.setText(translate('OpenLP.ThemeWizard', '&Shadow:')) - self.shadow_size_label.setText(translate('OpenLP.ThemeWizard', 'Size:')) - self.shadow_size_spin_box.setSuffix(' {unit}'.format(unit=UiStrings().FontSizePtUnit)) - self.main_bold_check_box.setText(translate('OpenLP.ThemeWizard', 'Bold')) - self.main_italics_check_box.setText(translate('OpenLP.ThemeWizard', 'Italic')) self.footer_area_page.setTitle(translate('OpenLP.ThemeWizard', 'Footer Area Font Details')) self.footer_area_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Define the font and display ' 'characteristics for the Footer text')) diff --git a/openlp/core/widgets/widgets.py b/openlp/core/widgets/widgets.py index acb280aae..b3ef54ea8 100644 --- a/openlp/core/widgets/widgets.py +++ b/openlp/core/widgets/widgets.py @@ -21,11 +21,13 @@ """ The :mod:`~openlp.core.widgets.widgets` module contains custom widgets used in OpenLP """ -from PyQt5 import QtCore, QtWidgets +from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common.i18n import translate +from openlp.core.common.i18n import UiStrings, translate from openlp.core.common.settings import ProxyMode, Settings from openlp.core.lib.ui import critical_error_message_box +from openlp.core.ui.icons import UiIcons +from openlp.core.widgets.buttons import ColorButton SCREENS_LAYOUT_STYLE = """ @@ -441,3 +443,350 @@ class ScreenSelectionWidget(QtWidgets.QWidget): self._setup_spin_box(self.height_spin_box, 0, screen.display_geometry.height(), screen.display_geometry.height()) self.current_screen = screen + + +class FontSelectWidget(QtWidgets.QWidget): + """ + A font selection widget + """ + Outline = 'outline' + Shadow = 'shadow' + LineSpacing = 'line_spacing' + + font_name_changed = QtCore.pyqtSignal(str) + font_size_changed = QtCore.pyqtSignal(int) + font_color_changed = QtCore.pyqtSignal(str) + is_bold_changed = QtCore.pyqtSignal(bool) + is_italic_changed = QtCore.pyqtSignal(bool) + line_spacing_changed = QtCore.pyqtSignal(int) + is_outline_enabled_changed = QtCore.pyqtSignal(bool) + outline_color_changed = QtCore.pyqtSignal(str) + outline_size_changed = QtCore.pyqtSignal(int) + is_shadow_enabled_changed = QtCore.pyqtSignal(bool) + shadow_color_changed = QtCore.pyqtSignal(str) + shadow_size_changed = QtCore.pyqtSignal(int) + + def __init__(self, parent=None): + super().__init__(parent) + self._column_width = 0 + self.setup_ui() + self.feature_widgets = { + FontSelectWidget.Outline: [self.outline_groupbox], + FontSelectWidget.Shadow: [self.shadow_groupbox], + FontSelectWidget.LineSpacing: [self.line_spacing_label, self.line_spacing_spinbox] + } + + def setup_ui(self): + self.layout = QtWidgets.QGridLayout(self) + # Font name + self.font_name_label = QtWidgets.QLabel(self) + self.font_name_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.font_name_label.setObjectName('font_name_label') + self.layout.addWidget(self.font_name_label, 0, 0) + self.font_name_combobox = QtWidgets.QFontComboBox(self) + self.font_name_combobox.setObjectName('font_name_combobox') + self.layout.addWidget(self.font_name_combobox, 0, 1, 1, 3) + # Font color + self.font_color_label = QtWidgets.QLabel(self) + self.font_color_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.font_color_label.setObjectName('font_color_label') + self.layout.addWidget(self.font_color_label, 1, 0) + self.font_color_button = ColorButton(self) + self.font_color_button.setObjectName('font_color_button') + self.layout.addWidget(self.font_color_button, 1, 1) + # Font style + self.font_style_label = QtWidgets.QLabel(self) + self.font_style_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.font_style_label.setObjectName('font_style_label') + self.layout.addWidget(self.font_style_label, 1, 2) + self.style_layout = QtWidgets.QHBoxLayout() + self.style_bold_button = QtWidgets.QToolButton(self) + self.style_bold_button.setIcon(UiIcons().bold) + self.style_bold_button.setShortcut(QtGui.QKeySequence(QtGui.QKeySequence.Bold)) + self.style_bold_button.setObjectName('style_bold_button') + self.style_layout.addWidget(self.style_bold_button) + self.style_italic_button = QtWidgets.QToolButton(self) + self.style_italic_button.setIcon(UiIcons().italic) + self.style_italic_button.setShortcut(QtGui.QKeySequence(QtGui.QKeySequence.Italic)) + self.style_italic_button.setObjectName('style_italic_button') + self.style_layout.addWidget(self.style_italic_button) + self.style_layout.addStretch(1) + self.layout.addLayout(self.style_layout, 1, 3) + # Font size + self.font_size_label = QtWidgets.QLabel(self) + self.font_size_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.font_size_label.setObjectName('font_size_label') + self.layout.addWidget(self.font_size_label, 2, 0) + self.font_size_spinbox = QtWidgets.QSpinBox(self) + self.font_size_spinbox.setMaximum(999) + self.font_size_spinbox.setValue(16) + self.font_size_spinbox.setObjectName('font_size_spinbox') + self.layout.addWidget(self.font_size_spinbox, 2, 1) + # Line spacing + self.line_spacing_label = QtWidgets.QLabel(self) + self.line_spacing_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.line_spacing_label.setObjectName('line_spacing_label') + self.layout.addWidget(self.line_spacing_label, 2, 2) + self.line_spacing_spinbox = QtWidgets.QSpinBox(self) + self.line_spacing_spinbox.setMinimum(-250) + self.line_spacing_spinbox.setMaximum(250) + self.line_spacing_spinbox.setObjectName('line_spacing_spinbox') + self.layout.addWidget(self.line_spacing_spinbox, 2, 3) + # Outline + self.outline_groupbox = QtWidgets.QGroupBox(self) + self.outline_groupbox.setCheckable(True) + self.outline_groupbox.setChecked(False) + self.outline_groupbox.setObjectName('outline_groupbox') + self.outline_layout = QtWidgets.QGridLayout(self.outline_groupbox) + self.layout.addWidget(self.outline_groupbox, 3, 0, 1, 2) + # Outline colour + self.outline_color_label = QtWidgets.QLabel(self.outline_groupbox) + self.outline_color_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.outline_color_label.setObjectName('outline_color_label') + self.outline_layout.addWidget(self.outline_color_label, 0, 0) + self.outline_color_button = ColorButton(self.outline_groupbox) + self.outline_color_button.setObjectName('outline_color_button') + self.outline_layout.addWidget(self.outline_color_button, 0, 1) + # Outline size + self.outline_size_label = QtWidgets.QLabel(self.outline_groupbox) + self.outline_size_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.outline_size_label.setObjectName('outline_size_label') + self.outline_layout.addWidget(self.outline_size_label, 1, 0) + self.outline_size_spinbox = QtWidgets.QSpinBox(self.outline_groupbox) + self.outline_size_spinbox.setMaximum(9999) + self.outline_size_spinbox.setObjectName('outline_size_spinbox') + self.outline_layout.addWidget(self.outline_size_spinbox, 1, 1) + # Shadow + self.shadow_groupbox = QtWidgets.QGroupBox(self) + self.shadow_groupbox.setCheckable(True) + self.shadow_groupbox.setChecked(False) + self.shadow_groupbox.setObjectName('shadow_groupbox') + self.shadow_layout = QtWidgets.QGridLayout(self.shadow_groupbox) + self.layout.addWidget(self.shadow_groupbox, 3, 2, 1, 2) + # Shadow color + self.shadow_color_label = QtWidgets.QLabel(self.shadow_groupbox) + self.shadow_color_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.shadow_color_label.setObjectName('shadow_color_label') + self.shadow_layout.addWidget(self.shadow_color_label, 0, 0) + self.shadow_color_button = ColorButton(self.shadow_groupbox) + self.shadow_color_button.setObjectName('shadow_color_button') + self.shadow_layout.addWidget(self.shadow_color_button, 0, 1) + # Shadow size + self.shadow_size_label = QtWidgets.QLabel(self.shadow_groupbox) + self.shadow_size_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) + self.shadow_size_label.setObjectName('shadow_size_label') + self.shadow_layout.addWidget(self.shadow_size_label, 1, 0) + self.shadow_size_spinbox = QtWidgets.QSpinBox(self.shadow_groupbox) + self.shadow_size_spinbox.setMaximum(9999) + self.shadow_size_spinbox.setObjectName('shadow_size_spinbox') + self.shadow_layout.addWidget(self.shadow_size_spinbox, 1, 1) + # Fix the size + self.resize_widgets() + # Connect all the signals + self.font_name_combobox.activated.connect(self._on_font_name_changed) + self.font_color_button.colorChanged.connect(self._on_font_color_changed) + self.style_bold_button.toggled.connect(self._on_style_bold_toggled) + self.style_italic_button.toggled.connect(self._on_style_italic_toggled) + self.font_size_spinbox.valueChanged.connect(self._on_font_size_changed) + self.line_spacing_spinbox.valueChanged.connect(self._on_line_spacing_changed) + self.outline_groupbox.toggled.connect(self._on_outline_toggled) + self.outline_color_button.colorChanged.connect(self._on_outline_color_changed) + self.outline_size_spinbox.valueChanged.connect(self._on_outline_size_changed) + self.shadow_groupbox.toggled.connect(self._on_shadow_toggled) + self.shadow_color_button.colorChanged.connect(self._on_shadow_color_changed) + self.shadow_size_spinbox.valueChanged.connect(self._on_shadow_size_changed) + # Translate everything + self.retranslate_ui() + + def retranslate_ui(self): + self.font_name_label.setText(translate('OpenLP.FontSelectWidget', 'Font:')) + self.font_color_label.setText(translate('OpenLP.FontSelectWidget', 'Color:')) + self.font_style_label.setText(translate('OpenLP.FontSelectWidget', 'Style:')) + self.style_bold_button.setToolTip('{name} ({shortcut})'.format( + name=translate('OpenLP.FontSelectWidget', 'Bold'), + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Bold).toString() + )) + self.style_italic_button.setToolTip('{name} ({shortcut})'.format( + name=translate('OpenLP.FontSelectWidget', 'Italic'), + shortcut=QtGui.QKeySequence(QtGui.QKeySequence.Italic).toString() + )) + self.font_size_label.setText(translate('OpenLP.FontSelectWidget', 'Size:')) + self.font_size_spinbox.setSuffix(' {unit}'.format(unit=UiStrings().FontSizePtUnit)) + self.line_spacing_label.setText(translate('OpenLP.FontSelectWidget', 'Line Spacing:')) + self.outline_groupbox.setTitle(translate('OpenLP.FontSelectWidget', 'Outline')) + self.outline_color_label.setText(translate('OpenLP.FontSelectWidget', 'Color:')) + self.outline_size_label.setText(translate('OpenLP.FontSelectWidget', 'Size:')) + self.shadow_groupbox.setTitle(translate('OpenLP.FontSelectWidget', 'Shadow')) + self.shadow_color_label.setText(translate('OpenLP.FontSelectWidget', 'Color:')) + self.shadow_size_label.setText(translate('OpenLP.FontSelectWidget', 'Size:')) + + def resizeEvent(self, event): + """ + Override inherited resize method + """ + super().resizeEvent(event) + self.resize_widgets() + + def _on_font_name_changed(self, name): + if isinstance(name, str): + self.font_name_changed.emit(name) + + def _on_font_color_changed(self, color): + self.font_color_changed.emit(color) + + def _on_style_bold_toggled(self, is_bold): + self.is_bold_changed.emit(is_bold) + + def _on_style_italic_toggled(self, is_italic): + self.is_italic_changed.emit(is_italic) + + def _on_font_size_changed(self, size): + self.font_size_changed.emit(size) + + def _on_line_spacing_changed(self, spacing): + self.line_spacing_changed.emit(spacing) + + def _on_outline_toggled(self, is_enabled): + self.is_outline_enabled_changed.emit(is_enabled) + + def _on_outline_color_changed(self, color): + self.outline_color_changed.emit(color) + + def _on_outline_size_changed(self, size): + self.outline_size_changed.emit(size) + + def _on_shadow_toggled(self, is_enabled): + self.is_shadow_enabled_changed.emit(is_enabled) + + def _on_shadow_color_changed(self, color): + self.shadow_color_changed.emit(color) + + def _on_shadow_size_changed(self, size): + self.shadow_size_changed.emit(size) + + def resize_widgets(self): + """ + Resize all the widgets and set the column widths + """ + width = self.geometry().width() + margins = self.layout.contentsMargins() + spacing = self.layout.horizontalSpacing() + self._column_width = (width - margins.left() - margins.right() - (spacing * 3)) // 4 + for column_number in range(4): + self.layout.setColumnMinimumWidth(column_number, self._column_width) + + def enable_features(self, *features): + """ + Enable a feature + """ + for feature_name in features: + if feature_name not in self.feature_widgets.keys(): + raise KeyError('No such feature: {feature_name}'.format(feature_name=feature_name)) + for widget in self.feature_widgets[feature_name]: + widget.show() + + def disable_features(self, *features): + """ + Disable a feature + """ + for feature_name in features: + if feature_name not in self.feature_widgets.keys(): + raise KeyError('No such feature: {feature_name}'.format(feature_name=feature_name)) + for widget in self.feature_widgets[feature_name]: + widget.hide() + + @property + def font_name(self): + return self.font_name_combobox.currentFont().family() + + @font_name.setter + def font_name(self, font): + self.font_name_combobox.setCurrentFont(QtGui.QFont(font)) + + @property + def font_color(self): + return self.font_color_button.color + + @font_color.setter + def font_color(self, color): + self.font_color_button.color = color + + @property + def is_bold(self): + return self.style_bold_button.isChecked() + + @is_bold.setter + def is_bold(self, is_bold): + self.style_bold_button.setChecked(is_bold) + + @property + def is_italic(self): + return self.style_italic_button.isChecked() + + @is_italic.setter + def is_italic(self, is_italic): + self.style_italic_button.setChecked(is_italic) + + @property + def font_size(self): + return self.font_size_spinbox.value() + + @font_size.setter + def font_size(self, size): + self.font_size_spinbox.setValue(size) + + @property + def line_spacing(self): + return self.line_spacing_spinbox.value() + + @line_spacing.setter + def line_spacing(self, line_spacing): + self.line_spacing_spinbox.setValue(line_spacing) + + @property + def is_outline_enabled(self): + return self.outline_groupbox.isChecked() + + @is_outline_enabled.setter + def is_outline_enabled(self, is_enabled): + self.outline_groupbox.setChecked(is_enabled) + + @property + def outline_color(self): + return self.outline_color_button.color + + @outline_color.setter + def outline_color(self, color): + self.outline_color_button.color = color + + @property + def outline_size(self): + return self.outline_size_spinbox.value() + + @outline_size.setter + def outline_size(self, size): + self.outline_size_spinbox.setValue(size) + + @property + def is_shadow_enabled(self): + return self.shadow_groupbox.isChecked() + + @is_shadow_enabled.setter + def is_shadow_enabled(self, is_enabled): + self.shadow_groupbox.setChecked(is_enabled) + + @property + def shadow_color(self): + return self.shadow_color_button.color + + @shadow_color.setter + def shadow_color(self, color): + self.shadow_color_button.color = color + + @property + def shadow_size(self): + return self.shadow_size_spinbox.value() + + @shadow_size.setter + def shadow_size(self, size): + self.shadow_size_spinbox.setValue(size) diff --git a/openlp/plugins/bibles/lib/upgrade.py b/openlp/plugins/bibles/lib/upgrade.py index 50326a890..ae83d36c2 100644 --- a/openlp/plugins/bibles/lib/upgrade.py +++ b/openlp/plugins/bibles/lib/upgrade.py @@ -43,7 +43,7 @@ def upgrade_1(session, metadata): This upgrade renamed a number of keys to a single naming convention. """ - log.info('No upgrades to perform') + log.info('No upgrades to perform') # pragma: no cover def upgrade_2(session, metadata): diff --git a/tests/openlp_core/widgets/test_widgets.py b/tests/openlp_core/widgets/test_widgets.py index 5754e4346..796021807 100644 --- a/tests/openlp_core/widgets/test_widgets.py +++ b/tests/openlp_core/widgets/test_widgets.py @@ -24,11 +24,12 @@ Package to test the openlp.core.widgets.widgets package. from unittest import TestCase from unittest.mock import MagicMock, call, patch +import pytest from PyQt5 import QtCore, QtWidgets from openlp.core.common.settings import ProxyMode from openlp.core.display.screens import Screen -from openlp.core.widgets.widgets import ProxyWidget, ProxyDialog, ScreenButton, ScreenSelectionWidget +from openlp.core.widgets.widgets import ProxyWidget, ProxyDialog, ScreenButton, ScreenSelectionWidget, FontSelectWidget from tests.helpers.testmixin import TestMixin @@ -525,3 +526,604 @@ class TestScreenSelectionWidget(TestCase, TestMixin): 'checkbox for that screen.', parent=instance, question=False) assert instance.use_screen_check_box.isChecked() is True assert instance.display_group_box.isChecked() is True + + +class TestFontSelectWidget(TestCase, TestMixin): + + def setUp(self): + """Test setup""" + self.setup_application() + self.build_settings() + + def tearDown(self): + """Tear down tests""" + del self.app + + def test_init_(self): + """ + Test the initialisation of FontSelectWidget + """ + # GIVEN: The FontSelectWidget class + # WHEN: Initialising FontSelectWidget + # THEN: We should have an instance of the widget with no errors + FontSelectWidget() + + def test_resize_event(self): + """ + Test that the `resizeEvent()` method called the `resize_widgets()` method. + """ + # GIVEN: An instance of FontSelectWidget with a mocked out "resize_widgets" method + instance = FontSelectWidget() + instance.resize_widgets = MagicMock() + + # WHEN: resizeEvent is called + instance.resizeEvent(None) + + # THEN: resize_widgets should have been called + instance.resize_widgets.assert_called_once() + + def test_font_name_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "font_name_changed" signal + instance = FontSelectWidget() + instance.font_name_changed = MagicMock() + + # WHEN: The font name changes + instance._on_font_name_changed('Sans serif') + + # THEN: The signal should be emitted with the correct value + instance.font_name_changed.emit.assert_called_once_with('Sans serif') + + def test_font_name_changed_int(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "font_name_changed" signal + instance = FontSelectWidget() + instance.font_name_changed = MagicMock() + + # WHEN: The font name changes + instance._on_font_name_changed(5) + + # THEN: The signal should be emitted with the correct value + assert instance.font_name_changed.emit.call_count == 0 + + def test_font_color_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "font_color_changed" signal + instance = FontSelectWidget() + instance.font_color_changed = MagicMock() + + # WHEN: The font color changes + instance._on_font_color_changed('#fff') + + # THEN: The signal should be emitted with the correct value + instance.font_color_changed.emit.assert_called_once_with('#fff') + + def test_is_bold_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "is_bold_changed" signal + instance = FontSelectWidget() + instance.is_bold_changed = MagicMock() + + # WHEN: The font name changes + instance._on_style_bold_toggled(True) + + # THEN: The signal should be emitted with the correct value + instance.is_bold_changed.emit.assert_called_once_with(True) + + def test_is_italic_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "style_italic_changed" signal + instance = FontSelectWidget() + instance.is_italic_changed = MagicMock() + + # WHEN: The font name changes + instance._on_style_italic_toggled(False) + + # THEN: The signal should be emitted with the correct value + instance.is_italic_changed.emit.assert_called_once_with(False) + + def test_font_size_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "font_size_changed" signal + instance = FontSelectWidget() + instance.font_size_changed = MagicMock() + + # WHEN: The font size changes + instance._on_font_size_changed(14) + + # THEN: The signal should be emitted with the correct value + instance.font_size_changed.emit.assert_called_once_with(14) + + def test_line_spacing_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "line_spacing_changed" signal + instance = FontSelectWidget() + instance.line_spacing_changed = MagicMock() + + # WHEN: The font name changes + instance._on_line_spacing_changed(1) + + # THEN: The signal should be emitted with the correct value + instance.line_spacing_changed.emit.assert_called_once_with(1) + + def test_is_outline_enabled_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "outline_enabled_changed" signal + instance = FontSelectWidget() + instance.is_outline_enabled_changed = MagicMock() + + # WHEN: The font name changes + instance._on_outline_toggled(True) + + # THEN: The signal should be emitted with the correct value + instance.is_outline_enabled_changed.emit.assert_called_once_with(True) + + def test_outline_color_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "outline_color_changed" signal + instance = FontSelectWidget() + instance.outline_color_changed = MagicMock() + + # WHEN: The font name changes + instance._on_outline_color_changed('#000') + + # THEN: The signal should be emitted with the correct value + instance.outline_color_changed.emit.assert_called_once_with('#000') + + def test_outline_size_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "outline_size_changed" signal + instance = FontSelectWidget() + instance.outline_size_changed = MagicMock() + + # WHEN: The font name changes + instance._on_outline_size_changed(2) + + # THEN: The signal should be emitted with the correct value + instance.outline_size_changed.emit.assert_called_once_with(2) + + def test_is_shadow_enabled_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "is_shadow_enabled_changed" signal + instance = FontSelectWidget() + instance.is_shadow_enabled_changed = MagicMock() + + # WHEN: The font name changes + instance._on_shadow_toggled(False) + + # THEN: The signal should be emitted with the correct value + instance.is_shadow_enabled_changed.emit.assert_called_once_with(False) + + def test_shadow_color_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "shadow_color_changed" signal + instance = FontSelectWidget() + instance.shadow_color_changed = MagicMock() + + # WHEN: The font name changes + instance._on_shadow_color_changed('#000') + + # THEN: The signal should be emitted with the correct value + instance.shadow_color_changed.emit.assert_called_once_with('#000') + + def test_shadow_size_changed(self): + # GIVEN: An instance of FontSelectWidget with a mocked out "shadow_size_changed" signal + instance = FontSelectWidget() + instance.shadow_size_changed = MagicMock() + + # WHEN: The font name changes + instance._on_shadow_size_changed(5) + + # THEN: The signal should be emitted with the correct value + instance.shadow_size_changed.emit.assert_called_once_with(5) + + def test_resize_widgets(self): + """ + Test the `resize_widgets()` method + """ + # GIVEN: An instance of FontSelectWidget and various mocked out methods + instance = FontSelectWidget() + instance.geometry = MagicMock(return_value=MagicMock(**{'width.return_value': 100})) + instance.layout.contentsMargins = MagicMock(return_value=MagicMock(**{'left.return_value': 8, + 'right.return_value': 8})) + instance.layout.horizontalSpacing = MagicMock(return_value=6) + instance.layout.setColumnMinimumWidth = MagicMock() + + # WHEN: `resize_widgets()` is called + instance.resize_widgets() + + # THEN: The column widths should be set to 16 + instance.geometry.assert_called_once() + instance.layout.contentsMargins.assert_called_once() + instance.layout.horizontalSpacing.assert_called_once() + assert instance._column_width == 16 + assert instance.layout.setColumnMinimumWidth.call_args_list == [call(0, 16), call(1, 16), + call(2, 16), call(3, 16)] + + def test_enable_features(self): + """ + Test that the `enable_features` method correctly enables widgets based on features + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + mock_label = MagicMock() + mock_control = MagicMock() + instance.feature_widgets = {'test': [mock_label, mock_control]} + + # WHEN: The "test" feature is enabled + instance.enable_features('test') + + # THEN: "show()" is called on all the widgets + mock_label.show.assert_called_once() + mock_control.show.assert_called_once() + + def test_enable_missing_features(self): + """ + Test that the `enable_features` method correctly raises an error on a non-existent feature + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + mock_label = MagicMock() + mock_control = MagicMock() + instance.feature_widgets = {'test1': [mock_label, mock_control]} + + # WHEN: The "test" feature is enabled + with pytest.raises(KeyError, match='No such feature'): + instance.enable_features('test2') + + def test_disable_features(self): + """ + Test that the `disable_features` method correctly disables widgets based on features + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + mock_label = MagicMock() + mock_control = MagicMock() + instance.feature_widgets = {'test': [mock_label, mock_control]} + + # WHEN: The "test" feature is disabled + instance.disable_features('test') + + # THEN: "show()" is called on all the widgets + mock_label.hide.assert_called_once() + mock_control.hide.assert_called_once() + + def test_disable_missing_features(self): + """ + Test that the `disable_features` method correctly raises an error on a non-existent feature + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + mock_label = MagicMock() + mock_control = MagicMock() + instance.feature_widgets = {'test1': [mock_label, mock_control]} + + # WHEN: The "test" feature is disabled + with pytest.raises(KeyError, match='No such feature'): + instance.disable_features('test2') + + def test_get_font_name_property(self): + """ + Test the `font_name` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.font_name_combobox.currentFont = MagicMock( + return_value=MagicMock(**{'family.return_value': 'Sans serif'})) + + # WHEN: The `font_name` propert is accessed + result = instance.font_name + + # THEN: The value should be correct + assert result == 'Sans serif' + + def test_set_font_name_property(self): + """ + Test setting the `font_name` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.font_name_combobox.setCurrentFont = MagicMock() + + # WHEN: The `font_name` property is set + with patch('openlp.core.widgets.widgets.QtGui.QFont') as MockFont: + mocked_font = MagicMock() + MockFont.return_value = mocked_font + instance.font_name = 'Serif' + + # THEN: The correct value should be set + MockFont.assert_called_once_with('Serif') + instance.font_name_combobox.setCurrentFont.assert_called_once_with(mocked_font) + + def test_get_font_color_property(self): + """ + Test the `font_color` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.font_color_button.color = '#000' + + # WHEN: The `font_color` propert is accessed + result = instance.font_color + + # THEN: The value should be correct + assert result == '#000' + + def test_set_font_color_property(self): + """ + Test setting the `font_color` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + + # WHEN: The `font_color` property is set + instance.font_color = '#fff' + + # THEN: The correct value should be set + assert instance.font_color_button.color == '#fff' + + def test_get_is_bold_property(self): + """ + Test the `is_bold` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.style_bold_button.isChecked = MagicMock(return_value=False) + + # WHEN: The `is_bold` propert is accessed + result = instance.is_bold + + # THEN: The value should be correct + assert result is False + + def test_set_is_bold_property(self): + """ + Test setting the `is_bold` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.style_bold_button.setChecked = MagicMock() + + # WHEN: The `is_bold` property is set + instance.is_bold = True + + # THEN: The correct value should be set + instance.style_bold_button.setChecked.assert_called_once_with(True) + + def test_get_is_italic_property(self): + """ + Test the `is_italic` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.style_italic_button.isChecked = MagicMock(return_value=True) + + # WHEN: The `is_italic` propert is accessed + result = instance.is_italic + + # THEN: The value should be correct + assert result is True + + def test_set_is_italic_property(self): + """ + Test setting the `is_italic` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.style_italic_button.setChecked = MagicMock() + + # WHEN: The `is_italic` property is set + instance.is_italic = False + + # THEN: The correct value should be set + instance.style_italic_button.setChecked.assert_called_once_with(False) + + def test_get_font_size_property(self): + """ + Test the `font_size` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.font_size_spinbox.value = MagicMock(return_value=16) + + # WHEN: The `font_size` propert is accessed + result = instance.font_size + + # THEN: The value should be correct + assert result == 16 + + def test_set_font_size_property(self): + """ + Test setting the `font_size` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.font_size_spinbox.setValue = MagicMock() + + # WHEN: The `font_size` property is set + instance.font_size = 18 + + # THEN: The correct value should be set + instance.font_size_spinbox.setValue.assert_called_once_with(18) + + def test_get_line_spacing_property(self): + """ + Test the `line_spacing` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.line_spacing_spinbox.value = MagicMock(return_value=1) + + # WHEN: The `line_spacing` propert is accessed + result = instance.line_spacing + + # THEN: The value should be correct + assert result == 1 + + def test_set_line_spacing_property(self): + """ + Test setting the `line_spacing` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.line_spacing_spinbox.setValue = MagicMock() + + # WHEN: The `line_spacing` property is set + instance.line_spacing = 2 + + # THEN: The correct value should be set + instance.line_spacing_spinbox.setValue.assert_called_once_with(2) + + def test_get_is_outline_enabled_property(self): + """ + Test the `is_outline_enabled` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.outline_groupbox.isChecked = MagicMock(return_value=True) + + # WHEN: The `is_outline_enabled` propert is accessed + result = instance.is_outline_enabled + + # THEN: The value should be correct + assert result is True + + def test_set_is_outline_enabled_property(self): + """ + Test setting the `is_outline_enabled` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.outline_groupbox.setChecked = MagicMock() + + # WHEN: The `is_outline_enabled` property is set + instance.is_outline_enabled = False + + # THEN: The correct value should be set + instance.outline_groupbox.setChecked.assert_called_once_with(False) + + def test_get_outline_color_property(self): + """ + Test the `outline_color` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.outline_color_button.color = '#fff' + + # WHEN: The `outline_color` propert is accessed + result = instance.outline_color + + # THEN: The value should be correct + assert result == '#fff' + + def test_set_outline_color_property(self): + """ + Test setting the `outline_color` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + + # WHEN: The `outline_color` property is set + instance.outline_color = '#000' + + # THEN: The correct value should be set + assert instance.outline_color_button.color == '#000' + + def test_get_outline_size_property(self): + """ + Test the `outline_size` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.outline_size_spinbox.value = MagicMock(return_value=2) + + # WHEN: The `outline_size` propert is accessed + result = instance.outline_size + + # THEN: The value should be correct + assert result == 2 + + def test_set_outline_size_property(self): + """ + Test setting the `outline_size` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.outline_size_spinbox.setValue = MagicMock() + + # WHEN: The `outline_size` property is set + instance.outline_size = 1 + + # THEN: The correct value should be set + instance.outline_size_spinbox.setValue.assert_called_once_with(1) + + def test_get_is_shadow_enabled_property(self): + """ + Test the `is_shadow_enabled` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.shadow_groupbox.isChecked = MagicMock(return_value=False) + + # WHEN: The `is_shadow_enabled` propert is accessed + result = instance.is_shadow_enabled + + # THEN: The value should be correct + assert result is False + + def test_set_is_shadow_enabled_property(self): + """ + Test setting the `is_shadow_enabled` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.shadow_groupbox.setChecked = MagicMock() + + # WHEN: The `is_shadow_enabled` property is set + instance.is_shadow_enabled = True + + # THEN: The correct value should be set + instance.shadow_groupbox.setChecked.assert_called_once_with(True) + + def test_get_shadow_color_property(self): + """ + Test the `shadow_color` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.shadow_color_button.color = '#000' + + # WHEN: The `shadow_color` propert is accessed + result = instance.shadow_color + + # THEN: The value should be correct + assert result == '#000' + + def test_set_shadow_color_property(self): + """ + Test setting the `shadow_color` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + + # WHEN: The `shadow_color` property is set + instance.shadow_color = '#fff' + + # THEN: The correct value should be set + instance.shadow_color_button.color == '#fff' + + def test_get_shadow_size_property(self): + """ + Test the `shadow_size` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.shadow_size_spinbox.value = MagicMock(return_value=5) + + # WHEN: The `shadow_size` propert is accessed + result = instance.shadow_size + + # THEN: The value should be correct + assert result == 5 + + def test_set_shadow_size_property(self): + """ + Test setting the `shadow_size` property + """ + # GIVEN: An instance of FontSelectWidget with some mocks + instance = FontSelectWidget() + instance.shadow_size_spinbox.setValue = MagicMock() + + # WHEN: The `shadow_size` property is set + instance.shadow_size = 10 + + # THEN: The correct value should be set + instance.shadow_size_spinbox.setValue.assert_called_once_with(10)