From cbf37ce8b36bc5ca84cc58f04790c700f81fd22c Mon Sep 17 00:00:00 2001 From: Raoul Snyman Date: Wed, 16 Dec 2020 23:58:22 -0700 Subject: [PATCH] Refactor the settings somewhat - Created a new Service tab - Moved service-specific items to service tab - Moved UI settings to general tab - Did some general UI cleanup Update/add tests --- openlp/core/ui/advancedtab.py | 361 +----------------- openlp/core/ui/generaltab.py | 266 +++++++++---- openlp/core/ui/media/mediatab.py | 10 +- openlp/core/ui/servicetab.py | 326 ++++++++++++++++ openlp/core/ui/settingsdialog.py | 2 +- openlp/core/ui/settingsform.py | 4 + .../openlp_core/ui/test_advancedtab.py | 17 - tests/openlp_core/ui/test_generaltab.py | 56 +++ tests/openlp_core/ui/test_servicetab.py | 39 ++ 9 files changed, 620 insertions(+), 461 deletions(-) create mode 100644 openlp/core/ui/servicetab.py create mode 100644 tests/openlp_core/ui/test_generaltab.py create mode 100644 tests/openlp_core/ui/test_servicetab.py diff --git a/openlp/core/ui/advancedtab.py b/openlp/core/ui/advancedtab.py index 108a8376c..36e663952 100644 --- a/openlp/core/ui/advancedtab.py +++ b/openlp/core/ui/advancedtab.py @@ -22,16 +22,13 @@ The :mod:`advancedtab` provides an advanced settings facility. """ import logging -from datetime import datetime, timedelta -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt5 import QtWidgets -from openlp.core.common import SlideLimits, is_win from openlp.core.common.applocation import AppLocation -from openlp.core.common.i18n import UiStrings, format_time, translate +from openlp.core.common.i18n import UiStrings, translate from openlp.core.lib.settingstab import SettingsTab from openlp.core.ui.icons import UiIcons -from openlp.core.ui.style import HAS_DARK_STYLE from openlp.core.widgets.edits import PathEdit from openlp.core.widgets.enums import PathEditType from openlp.core.widgets.widgets import ProxyWidget @@ -51,10 +48,6 @@ class AdvancedTab(SettingsTab): """ self.data_exists = False self.icon_path = UiIcons().settings - self.autoscroll_map = [None, {'dist': -1, 'pos': 0}, {'dist': -1, 'pos': 1}, {'dist': -1, 'pos': 2}, - {'dist': 0, 'pos': 0}, {'dist': 0, 'pos': 1}, {'dist': 0, 'pos': 2}, - {'dist': 0, 'pos': 3}, {'dist': 1, 'pos': 0}, {'dist': 1, 'pos': 1}, - {'dist': 1, 'pos': 2}, {'dist': 1, 'pos': 3}] advanced_translated = translate('OpenLP.AdvancedTab', 'Advanced') super(AdvancedTab, self).__init__(parent, 'Advanced', advanced_translated) @@ -64,80 +57,6 @@ class AdvancedTab(SettingsTab): """ self.setObjectName('AdvancedTab') super(AdvancedTab, self).setup_ui() - self.ui_group_box = QtWidgets.QGroupBox(self.left_column) - self.ui_group_box.setObjectName('ui_group_box') - self.ui_layout = QtWidgets.QFormLayout(self.ui_group_box) - self.ui_layout.setObjectName('ui_layout') - self.recent_label = QtWidgets.QLabel(self.ui_group_box) - self.recent_label.setObjectName('recent_label') - self.recent_spin_box = QtWidgets.QSpinBox(self.ui_group_box) - self.recent_spin_box.setObjectName('recent_spin_box') - self.recent_spin_box.setMinimum(0) - self.ui_layout.addRow(self.recent_label, self.recent_spin_box) - self.media_plugin_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.media_plugin_check_box.setObjectName('media_plugin_check_box') - self.ui_layout.addRow(self.media_plugin_check_box) - self.hide_mouse_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.hide_mouse_check_box.setObjectName('hide_mouse_check_box') - self.ui_layout.addRow(self.hide_mouse_check_box) - self.double_click_live_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.double_click_live_check_box.setObjectName('double_click_live_check_box') - self.ui_layout.addRow(self.double_click_live_check_box) - self.single_click_preview_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.single_click_preview_check_box.setObjectName('single_click_preview_check_box') - self.ui_layout.addRow(self.single_click_preview_check_box) - self.single_click_service_preview_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.single_click_service_preview_check_box.setObjectName('single_click_service_preview_check_box') - self.ui_layout.addRow(self.single_click_service_preview_check_box) - self.expand_service_item_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.expand_service_item_check_box.setObjectName('expand_service_item_check_box') - self.ui_layout.addRow(self.expand_service_item_check_box) - self.slide_max_height_label = QtWidgets.QLabel(self.ui_group_box) - self.slide_max_height_label.setObjectName('slide_max_height_label') - self.slide_max_height_combo_box = QtWidgets.QComboBox(self.ui_group_box) - self.slide_max_height_combo_box.addItem('', userData=0) - self.slide_max_height_combo_box.addItem('', userData=-4) - # Generate numeric values for combo box dynamically - for px in range(60, 801, 5): - self.slide_max_height_combo_box.addItem(str(px) + 'px', userData=px) - self.slide_max_height_combo_box.setObjectName('slide_max_height_combo_box') - self.ui_layout.addRow(self.slide_max_height_label, self.slide_max_height_combo_box) - self.autoscroll_label = QtWidgets.QLabel(self.ui_group_box) - self.autoscroll_label.setObjectName('autoscroll_label') - self.autoscroll_combo_box = QtWidgets.QComboBox(self.ui_group_box) - self.autoscroll_combo_box.addItems(['', '', '', '', '', '', '', '', '', '', '', '']) - self.autoscroll_combo_box.setObjectName('autoscroll_combo_box') - self.ui_layout.addRow(self.autoscroll_label) - self.ui_layout.addRow(self.autoscroll_combo_box) - self.search_as_type_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.search_as_type_check_box.setObjectName('SearchAsType_check_box') - self.ui_layout.addRow(self.search_as_type_check_box) - self.enable_auto_close_check_box = QtWidgets.QCheckBox(self.ui_group_box) - self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box') - self.ui_layout.addRow(self.enable_auto_close_check_box) - self.left_layout.addWidget(self.ui_group_box) - if not is_win() and HAS_DARK_STYLE: - self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box) - self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox') - self.ui_layout.addRow(self.use_dark_style_checkbox) - # Service Item Slide Limits - self.slide_group_box = QtWidgets.QGroupBox(self.left_column) - self.slide_group_box.setObjectName('slide_group_box') - self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box) - self.slide_layout.setObjectName('slide_layout') - self.slide_label = QtWidgets.QLabel(self.slide_group_box) - self.slide_label.setWordWrap(True) - self.slide_layout.addWidget(self.slide_label) - self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) - self.end_slide_radio_button.setObjectName('end_slide_radio_button') - self.slide_layout.addWidget(self.end_slide_radio_button) - self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) - self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button') - self.slide_layout.addWidget(self.wrap_slide_radio_button) - self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box) - self.next_item_radio_button.setObjectName('next_item_radio_button') - self.slide_layout.addWidget(self.next_item_radio_button) - self.left_layout.addWidget(self.slide_group_box) # Data Directory self.data_directory_group_box = QtWidgets.QGroupBox(self.left_column) self.data_directory_group_box.setObjectName('data_directory_group_box') @@ -165,7 +84,7 @@ class AdvancedTab(SettingsTab): self.data_directory_layout.addRow(self.new_data_directory_has_files_label) self.left_layout.addWidget(self.data_directory_group_box) # Display Workarounds - self.display_workaround_group_box = QtWidgets.QGroupBox(self.right_column) + self.display_workaround_group_box = QtWidgets.QGroupBox(self.left_column) self.display_workaround_group_box.setObjectName('display_workaround_group_box') self.display_workaround_layout = QtWidgets.QVBoxLayout(self.display_workaround_group_box) self.display_workaround_layout.setObjectName('display_workaround_layout') @@ -181,46 +100,7 @@ class AdvancedTab(SettingsTab): self.allow_transparent_display_check_box = QtWidgets.QCheckBox(self.display_workaround_group_box) self.allow_transparent_display_check_box.setObjectName('allow_transparent_display_check_box') self.display_workaround_layout.addWidget(self.allow_transparent_display_check_box) - self.right_layout.addWidget(self.display_workaround_group_box) - # Default service name - self.service_name_group_box = QtWidgets.QGroupBox(self.right_column) - self.service_name_group_box.setObjectName('service_name_group_box') - self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box) - self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box) - self.service_name_check_box.setObjectName('service_name_check_box') - self.service_name_layout.setObjectName('service_name_layout') - self.service_name_layout.addRow(self.service_name_check_box) - self.service_name_time_label = QtWidgets.QLabel(self.service_name_group_box) - self.service_name_time_label.setObjectName('service_name_time_label') - self.service_name_day = QtWidgets.QComboBox(self.service_name_group_box) - self.service_name_day.addItems(['', '', '', '', '', '', '', '']) - self.service_name_day.setObjectName('service_name_day') - self.service_name_time = QtWidgets.QTimeEdit(self.service_name_group_box) - self.service_name_time.setObjectName('service_name_time') - self.service_name_time_layout = QtWidgets.QHBoxLayout() - self.service_name_time_layout.setObjectName('service_name_time_layout') - self.service_name_time_layout.addWidget(self.service_name_day) - self.service_name_time_layout.addWidget(self.service_name_time) - self.service_name_layout.addRow(self.service_name_time_label, self.service_name_time_layout) - self.service_name_label = QtWidgets.QLabel(self.service_name_group_box) - self.service_name_label.setObjectName('service_name_label') - self.service_name_edit = QtWidgets.QLineEdit(self.service_name_group_box) - self.service_name_edit.setObjectName('service_name_edit') - self.service_name_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self)) - self.service_name_revert_button = QtWidgets.QToolButton(self.service_name_group_box) - self.service_name_revert_button.setObjectName('service_name_revert_button') - self.service_name_revert_button.setIcon(UiIcons().undo) - self.service_name_button_layout = QtWidgets.QHBoxLayout() - self.service_name_button_layout.setObjectName('service_name_button_layout') - self.service_name_button_layout.addWidget(self.service_name_edit) - self.service_name_button_layout.addWidget(self.service_name_revert_button) - self.service_name_layout.addRow(self.service_name_label, self.service_name_button_layout) - self.service_name_example_label = QtWidgets.QLabel(self.service_name_group_box) - self.service_name_example_label.setObjectName('service_name_example_label') - self.service_name_example = QtWidgets.QLabel(self.service_name_group_box) - self.service_name_example.setObjectName('service_name_example') - self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example) - self.right_layout.addWidget(self.service_name_group_box) + self.left_layout.addWidget(self.display_workaround_group_box) # Proxies self.proxy_widget = ProxyWidget(self.right_column) self.right_layout.addWidget(self.proxy_widget) @@ -228,91 +108,17 @@ class AdvancedTab(SettingsTab): self.left_layout.addStretch() self.right_layout.addStretch() # Set up all the connections and things - self.should_update_service_name_example = False - self.service_name_check_box.toggled.connect(self.service_name_check_box_toggled) - self.service_name_day.currentIndexChanged.connect(self.on_service_name_day_changed) - self.service_name_time.timeChanged.connect(self.update_service_name_example) - self.service_name_edit.textChanged.connect(self.update_service_name_example) - self.service_name_revert_button.clicked.connect(self.on_service_name_revert_button_clicked) self.alternate_rows_check_box.toggled.connect(self.on_alternate_rows_check_box_toggled) self.data_directory_path_edit.pathChanged.connect(self.on_data_directory_path_edit_path_changed) self.data_directory_cancel_button.clicked.connect(self.on_data_directory_cancel_button_clicked) self.data_directory_copy_check_box.toggled.connect(self.on_data_directory_copy_check_box_toggled) - self.end_slide_radio_button.clicked.connect(self.on_end_slide_button_clicked) - self.wrap_slide_radio_button.clicked.connect(self.on_wrap_slide_button_clicked) - self.next_item_radio_button.clicked.connect(self.on_next_item_button_clicked) - self.search_as_type_check_box.stateChanged.connect(self.on_search_as_type_check_box_changed) def retranslate_ui(self): """ Setup the interface translation strings. """ self.tab_title_visible = UiStrings().Advanced - self.ui_group_box.setTitle(translate('OpenLP.AdvancedTab', 'UI Settings')) self.data_directory_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Data Location')) - self.recent_label.setText(translate('OpenLP.AdvancedTab', 'Number of recent service files to display:')) - self.media_plugin_check_box.setText(translate('OpenLP.AdvancedTab', - 'Open the last used Library tab on startup')) - self.double_click_live_check_box.setText(translate('OpenLP.AdvancedTab', - 'Double-click to send items straight to Live')) - self.single_click_preview_check_box.setText(translate('OpenLP.AdvancedTab', - 'Preview items when clicked in Library')) - self.single_click_service_preview_check_box.setText(translate('OpenLP.AdvancedTab', - 'Preview items when clicked in Service')) - self.expand_service_item_check_box.setText(translate('OpenLP.AdvancedTab', - 'Expand new service items on creation')) - self.slide_max_height_label.setText(translate('OpenLP.AdvancedTab', - 'Max height for non-text slides\nin slide controller:')) - self.slide_max_height_combo_box.setItemText(0, translate('OpenLP.AdvancedTab', 'Disabled')) - self.slide_max_height_combo_box.setItemText(1, translate('OpenLP.AdvancedTab', 'Automatic')) - self.autoscroll_label.setText(translate('OpenLP.AdvancedTab', - 'When changing slides:')) - self.autoscroll_combo_box.setItemText(0, translate('OpenLP.AdvancedTab', 'Do not auto-scroll')) - self.autoscroll_combo_box.setItemText(1, translate('OpenLP.AdvancedTab', - 'Auto-scroll the previous slide into view')) - self.autoscroll_combo_box.setItemText(2, translate('OpenLP.AdvancedTab', - 'Auto-scroll the previous slide to top')) - self.autoscroll_combo_box.setItemText(3, translate('OpenLP.AdvancedTab', - 'Auto-scroll the previous slide to middle')) - self.autoscroll_combo_box.setItemText(4, translate('OpenLP.AdvancedTab', - 'Auto-scroll the current slide into view')) - self.autoscroll_combo_box.setItemText(5, translate('OpenLP.AdvancedTab', - 'Auto-scroll the current slide to top')) - self.autoscroll_combo_box.setItemText(6, translate('OpenLP.AdvancedTab', - 'Auto-scroll the current slide to middle')) - self.autoscroll_combo_box.setItemText(7, translate('OpenLP.AdvancedTab', - 'Auto-scroll the current slide to bottom')) - self.autoscroll_combo_box.setItemText(8, translate('OpenLP.AdvancedTab', - 'Auto-scroll the next slide into view')) - self.autoscroll_combo_box.setItemText(9, translate('OpenLP.AdvancedTab', - 'Auto-scroll the next slide to top')) - self.autoscroll_combo_box.setItemText(10, translate('OpenLP.AdvancedTab', - 'Auto-scroll the next slide to middle')) - self.autoscroll_combo_box.setItemText(11, translate('OpenLP.AdvancedTab', - 'Auto-scroll the next slide to bottom')) - self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab', - 'Enable application exit confirmation')) - if not is_win() and HAS_DARK_STYLE: - self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)')) - self.service_name_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Default Service Name')) - self.service_name_check_box.setText(translate('OpenLP.AdvancedTab', 'Enable default service name')) - self.service_name_time_label.setText(translate('OpenLP.AdvancedTab', 'Date and Time:')) - self.service_name_day.setItemText(0, translate('OpenLP.AdvancedTab', 'Monday')) - self.service_name_day.setItemText(1, translate('OpenLP.AdvancedTab', 'Tuesday')) - self.service_name_day.setItemText(2, translate('OpenLP.AdvancedTab', 'Wednesday')) - self.service_name_day.setItemText(3, translate('OpenLP.AdvancedTab', 'Thursday')) - self.service_name_day.setItemText(4, translate('OpenLP.AdvancedTab', 'Friday')) - self.service_name_day.setItemText(5, translate('OpenLP.AdvancedTab', 'Saturday')) - self.service_name_day.setItemText(6, translate('OpenLP.AdvancedTab', 'Sunday')) - self.service_name_day.setItemText(7, translate('OpenLP.AdvancedTab', 'Now')) - self.service_name_time.setToolTip(translate('OpenLP.AdvancedTab', 'Time when usual service starts.')) - self.service_name_label.setText(translate('OpenLP.AdvancedTab', 'Name:')) - self.service_name_edit.setToolTip(translate('OpenLP.AdvancedTab', 'Consult the OpenLP manual for usage.')) - self.service_name_revert_button.setToolTip( - translate('OpenLP.AdvancedTab', - 'Revert to the default service name "{name}".').format(name=UiStrings().DefaultServiceName)) - self.service_name_example_label.setText(translate('OpenLP.AdvancedTab', 'Example:')) - self.hide_mouse_check_box.setText(translate('OpenLP.AdvancedTab', 'Hide mouse cursor when over display window')) self.data_directory_new_label.setText(translate('OpenLP.AdvancedTab', 'Path:')) self.data_directory_cancel_button.setText(translate('OpenLP.AdvancedTab', 'Cancel')) self.data_directory_cancel_button.setToolTip( @@ -329,67 +135,19 @@ class AdvancedTab(SettingsTab): self.alternate_rows_check_box.setText(translate('OpenLP.AdvancedTab', 'Use alternating row colours in lists')) self.allow_transparent_display_check_box.setText( translate('OpenLP.AdvancedTab', 'Disable display transparency')) - # Slide Limits - self.slide_group_box.setTitle(translate('OpenLP.GeneralTab', 'Service Item Slide Limits')) - self.slide_label.setText(translate('OpenLP.GeneralTab', 'Behavior of next/previous on the last/first slide:')) - self.end_slide_radio_button.setText(translate('OpenLP.GeneralTab', '&Remain on Slide')) - self.wrap_slide_radio_button.setText(translate('OpenLP.GeneralTab', '&Wrap around')) - self.next_item_radio_button.setText(translate('OpenLP.GeneralTab', '&Move to next/previous service item')) - self.search_as_type_check_box.setText(translate('SongsPlugin.GeneralTab', 'Enable search as you type')) self.proxy_widget.retranslate_ui() def load(self): """ Load settings from disk. """ - - # The max recent files value does not have an interface and so never - # gets actually stored in the settings therefore the default value of - # 20 will always be used. - self.recent_spin_box.setMaximum(self.settings.value('advanced/max recent files')) - self.recent_spin_box.setValue(self.settings.value('advanced/recent file count')) - self.media_plugin_check_box.setChecked(self.settings.value('advanced/save current plugin')) - self.double_click_live_check_box.setChecked(self.settings.value('advanced/double click live')) - self.single_click_preview_check_box.setChecked(self.settings.value('advanced/single click preview')) - self.single_click_service_preview_check_box.setChecked( - self.settings.value('advanced/single click service preview')) - self.expand_service_item_check_box.setChecked(self.settings.value('advanced/expand service item')) - slide_max_height_value = self.settings.value('advanced/slide max height') - for i in range(0, self.slide_max_height_combo_box.count()): - if self.slide_max_height_combo_box.itemData(i) == slide_max_height_value: - self.slide_max_height_combo_box.setCurrentIndex(i) - autoscroll_value = self.settings.value('advanced/autoscrolling') - for i in range(0, len(self.autoscroll_map)): - if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count(): - self.autoscroll_combo_box.setCurrentIndex(i) - self.enable_auto_close_check_box.setChecked(self.settings.value('advanced/enable exit confirmation')) - if not is_win() and HAS_DARK_STYLE: - self.use_dark_style_checkbox.setChecked(self.settings.value('advanced/use_dark_style')) - self.hide_mouse_check_box.setChecked(self.settings.value('advanced/hide mouse')) - self.service_name_day.setCurrentIndex(self.settings.value('advanced/default service day')) - self.service_name_time.setTime(QtCore.QTime(self.settings.value('advanced/default service hour'), - self.settings.value('advanced/default service minute'))) - self.should_update_service_name_example = True - self.service_name_edit.setText(self.settings.value('advanced/default service name')) - default_service_enabled = self.settings.value('advanced/default service enabled') - self.service_name_check_box.setChecked(default_service_enabled) - self.service_name_check_box_toggled(default_service_enabled) self.ignore_aspect_ratio_check_box.setChecked(self.settings.value('advanced/ignore aspect ratio')) self.x11_bypass_check_box.setChecked(self.settings.value('advanced/x11 bypass wm')) - self.slide_limits = self.settings.value('advanced/slide limits') - self.is_search_as_you_type_enabled = self.settings.value('advanced/search as type') - self.search_as_type_check_box.setChecked(self.is_search_as_you_type_enabled) # Prevent the dialog displayed by the alternate_rows_check_box to display. self.alternate_rows_check_box.blockSignals(True) self.alternate_rows_check_box.setChecked(self.settings.value('advanced/alternate rows')) self.alternate_rows_check_box.blockSignals(False) self.allow_transparent_display_check_box.setChecked(self.settings.value('advanced/disable transparent display')) - if self.slide_limits == SlideLimits.End: - self.end_slide_radio_button.setChecked(True) - elif self.slide_limits == SlideLimits.Wrap: - self.wrap_slide_radio_button.setChecked(True) - else: - self.next_item_radio_button.setChecked(True) self.data_directory_copy_check_box.hide() self.new_data_directory_has_files_label.hide() self.data_directory_cancel_button.hide() @@ -403,49 +161,15 @@ class AdvancedTab(SettingsTab): """ Save settings to disk. """ - self.settings.setValue('advanced/default service enabled', self.service_name_check_box.isChecked()) - service_name = self.service_name_edit.text() - preset_is_valid = self.generate_service_name_example()[0] - if service_name == UiStrings().DefaultServiceName or not preset_is_valid: - self.settings.remove('advanced/default service name') - self.service_name_edit.setText(service_name) - else: - self.settings.setValue('advanced/default service name', service_name) - self.settings.setValue('advanced/default service day', self.service_name_day.currentIndex()) - self.settings.setValue('advanced/default service hour', self.service_name_time.time().hour()) - self.settings.setValue('advanced/default service minute', self.service_name_time.time().minute()) - self.settings.setValue('advanced/recent file count', self.recent_spin_box.value()) - self.settings.setValue('advanced/save current plugin', self.media_plugin_check_box.isChecked()) - self.settings.setValue('advanced/double click live', self.double_click_live_check_box.isChecked()) - self.settings.setValue('advanced/single click preview', self.single_click_preview_check_box.isChecked()) - self.settings.setValue('advanced/single click service preview', - self.single_click_service_preview_check_box.isChecked()) - self.settings.setValue('advanced/expand service item', self.expand_service_item_check_box.isChecked()) - slide_max_height_index = self.slide_max_height_combo_box.currentIndex() - slide_max_height_value = self.slide_max_height_combo_box.itemData(slide_max_height_index) - self.settings.setValue('advanced/slide max height', slide_max_height_value) - self.settings.setValue('advanced/autoscrolling', self.autoscroll_map[self.autoscroll_combo_box.currentIndex()]) - self.settings.setValue('advanced/enable exit confirmation', self.enable_auto_close_check_box.isChecked()) - self.settings.setValue('advanced/hide mouse', self.hide_mouse_check_box.isChecked()) - self.settings.setValue('advanced/alternate rows', self.alternate_rows_check_box.isChecked()) self.settings.setValue('advanced/disable transparent display', self.allow_transparent_display_check_box.isChecked()) - self.settings.setValue('advanced/slide limits', self.slide_limits) self.settings.setValue('advanced/ignore aspect ratio', self.ignore_aspect_ratio_check_box.isChecked()) if self.x11_bypass_check_box.isChecked() != self.settings.value('advanced/x11 bypass wm'): self.settings.setValue('advanced/x11 bypass wm', self.x11_bypass_check_box.isChecked()) self.settings_form.register_post_process('config_screen_changed') - self.settings_form.register_post_process('slidecontroller_update_slide_limits') - self.settings.setValue('advanced/search as type', self.is_search_as_you_type_enabled) - if not is_win() and HAS_DARK_STYLE: - self.settings.setValue('advanced/use_dark_style', self.use_dark_style_checkbox.isChecked()) + self.settings.setValue('advanced/alternate rows', self.alternate_rows_check_box.isChecked()) self.proxy_widget.save() - def on_search_as_type_check_box_changed(self, check_state): - self.is_search_as_you_type_enabled = (check_state == QtCore.Qt.Checked) - self.settings_form.register_post_process('songs_config_updated') - self.settings_form.register_post_process('custom_config_updated') - def cancel(self): """ Dialogue was cancelled, remove any pending data path change. @@ -453,63 +177,6 @@ class AdvancedTab(SettingsTab): self.on_data_directory_cancel_button_clicked() SettingsTab.cancel(self) - def service_name_check_box_toggled(self, default_service_enabled): - """ - Service Name options changed - """ - self.service_name_day.setEnabled(default_service_enabled) - time_enabled = default_service_enabled and self.service_name_day.currentIndex() != 7 - self.service_name_time.setEnabled(time_enabled) - self.service_name_edit.setEnabled(default_service_enabled) - self.service_name_revert_button.setEnabled(default_service_enabled) - - def generate_service_name_example(self): - """ - Display an example of the template used - """ - preset_is_valid = True - if self.service_name_day.currentIndex() == 7: - local_time = datetime.now() - else: - now = datetime.now() - day_delta = self.service_name_day.currentIndex() - now.weekday() - if day_delta < 0: - day_delta += 7 - time = now + timedelta(days=day_delta) - local_time = time.replace( - hour=self.service_name_time.time().hour(), - minute=self.service_name_time.time().minute() - ) - try: - service_name_example = format_time(self.service_name_edit.text(), local_time) - except ValueError: - preset_is_valid = False - service_name_example = translate('OpenLP.AdvancedTab', 'Syntax error.') - return preset_is_valid, service_name_example - - def update_service_name_example(self, returned_value): - """ - Update the example service name. - """ - if not self.should_update_service_name_example: - return - name_example = self.generate_service_name_example()[1] - self.service_name_example.setText(name_example) - - def on_service_name_day_changed(self, service_day): - """ - React to the day of the service name changing. - """ - self.service_name_time.setEnabled(service_day != 7) - self.update_service_name_example(None) - - def on_service_name_revert_button_clicked(self): - """ - Revert to the default service name. - """ - self.service_name_edit.setText(UiStrings().DefaultServiceName) - self.service_name_edit.setFocus() - def on_data_directory_path_edit_path_changed(self, new_path): """ Handle the `editPathChanged` signal of the data_directory_path_edit @@ -597,21 +264,3 @@ class AdvancedTab(SettingsTab): translate('OpenLP.AdvancedTab', 'This change will only take effect once OpenLP ' 'has been restarted.')) - - def on_end_slide_button_clicked(self): - """ - Stop at the end either top ot bottom - """ - self.slide_limits = SlideLimits.End - - def on_wrap_slide_button_clicked(self): - """ - Wrap round the service item - """ - self.slide_limits = SlideLimits.Wrap - - def on_next_item_button_clicked(self): - """ - Advance to the next service item - """ - self.slide_limits = SlideLimits.Next diff --git a/openlp/core/ui/generaltab.py b/openlp/core/ui/generaltab.py index 802e0e3ea..2a91eda69 100644 --- a/openlp/core/ui/generaltab.py +++ b/openlp/core/ui/generaltab.py @@ -24,12 +24,12 @@ The general tab of the configuration dialog. import logging from pathlib import Path -from PyQt5 import QtGui, QtWidgets +from PyQt5 import QtCore, QtGui, QtWidgets -from openlp.core.common import get_images_filter +from openlp.core.common import get_images_filter, is_win from openlp.core.common.i18n import UiStrings, translate -from openlp.core.display.screens import ScreenList from openlp.core.lib.settingstab import SettingsTab +from openlp.core.ui.style import HAS_DARK_STYLE from openlp.core.widgets.buttons import ColorButton from openlp.core.widgets.edits import PathEdit @@ -46,8 +46,11 @@ class GeneralTab(SettingsTab): Initialise the general settings tab """ self.logo_background_color = '#ffffff' - self.screens = ScreenList() self.icon_path = ':/icon/openlp-logo.svg' + self.autoscroll_map = [None, {'dist': -1, 'pos': 0}, {'dist': -1, 'pos': 1}, {'dist': -1, 'pos': 2}, + {'dist': 0, 'pos': 0}, {'dist': 0, 'pos': 1}, {'dist': 0, 'pos': 2}, + {'dist': 0, 'pos': 3}, {'dist': 1, 'pos': 0}, {'dist': 1, 'pos': 1}, + {'dist': 1, 'pos': 2}, {'dist': 1, 'pos': 3}] general_translated = translate('OpenLP.GeneralTab', 'General') super(GeneralTab, self).__init__(parent, 'Core', general_translated) @@ -58,32 +61,8 @@ class GeneralTab(SettingsTab): self.setObjectName('GeneralTab') super(GeneralTab, self).setup_ui() self.tab_layout.setStretch(1, 1) - # CCLI Details - self.ccli_group_box = QtWidgets.QGroupBox(self.left_column) - self.ccli_group_box.setObjectName('ccli_group_box') - self.ccli_layout = QtWidgets.QFormLayout(self.ccli_group_box) - self.ccli_layout.setObjectName('ccli_layout') - self.number_label = QtWidgets.QLabel(self.ccli_group_box) - self.number_label.setObjectName('number_label') - self.number_edit = QtWidgets.QLineEdit(self.ccli_group_box) - self.number_edit.setValidator(QtGui.QIntValidator()) - self.number_edit.setObjectName('number_edit') - self.ccli_layout.addRow(self.number_label, self.number_edit) - self.username_label = QtWidgets.QLabel(self.ccli_group_box) - self.username_label.setObjectName('username_label') - self.username_edit = QtWidgets.QLineEdit(self.ccli_group_box) - self.username_edit.setObjectName('username_edit') - self.ccli_layout.addRow(self.username_label, self.username_edit) - self.password_label = QtWidgets.QLabel(self.ccli_group_box) - self.password_label.setObjectName('password_label') - self.password_edit = QtWidgets.QLineEdit(self.ccli_group_box) - self.password_edit.setEchoMode(QtWidgets.QLineEdit.Password) - self.password_edit.setObjectName('password_edit') - self.ccli_layout.addRow(self.password_label, self.password_edit) - self.left_layout.addWidget(self.ccli_group_box) - self.left_layout.addStretch() # Application Startup - self.startup_group_box = QtWidgets.QGroupBox(self.right_column) + self.startup_group_box = QtWidgets.QGroupBox(self.left_column) self.startup_group_box.setObjectName('startup_group_box') self.startup_layout = QtWidgets.QVBoxLayout(self.startup_group_box) self.startup_layout.setObjectName('startup_layout') @@ -99,9 +78,9 @@ class GeneralTab(SettingsTab): self.check_for_updates_check_box = QtWidgets.QCheckBox(self.startup_group_box) self.check_for_updates_check_box.setObjectName('check_for_updates_check_box') self.startup_layout.addWidget(self.check_for_updates_check_box) - self.right_layout.addWidget(self.startup_group_box) + self.left_layout.addWidget(self.startup_group_box) # Logo - self.logo_group_box = QtWidgets.QGroupBox(self.right_column) + self.logo_group_box = QtWidgets.QGroupBox(self.left_column) self.logo_group_box.setObjectName('logo_group_box') self.logo_layout = QtWidgets.QFormLayout(self.logo_group_box) self.logo_layout.setObjectName('logo_layout') @@ -118,78 +97,160 @@ class GeneralTab(SettingsTab): self.logo_hide_on_startup_check_box = QtWidgets.QCheckBox(self.logo_group_box) self.logo_hide_on_startup_check_box.setObjectName('logo_hide_on_startup_check_box') self.logo_layout.addRow(self.logo_hide_on_startup_check_box) - self.right_layout.addWidget(self.logo_group_box) + self.left_layout.addWidget(self.logo_group_box) self.logo_color_button.colorChanged.connect(self.on_logo_background_color_changed) - # Application Settings - self.settings_group_box = QtWidgets.QGroupBox(self.right_column) - self.settings_group_box.setObjectName('settings_group_box') - self.settings_layout = QtWidgets.QFormLayout(self.settings_group_box) - self.settings_layout.setObjectName('settings_layout') - self.auto_unblank_check_box = QtWidgets.QCheckBox(self.settings_group_box) - self.auto_unblank_check_box.setObjectName('auto_unblank_check_box') - self.settings_layout.addRow(self.auto_unblank_check_box) - self.click_live_slide_to_unblank_check_box = QtWidgets.QCheckBox(self.settings_group_box) - self.click_live_slide_to_unblank_check_box.setObjectName('click_live_slide_to_unblank') - self.settings_layout.addRow(self.click_live_slide_to_unblank_check_box) - self.auto_preview_check_box = QtWidgets.QCheckBox(self.settings_group_box) - self.auto_preview_check_box.setObjectName('auto_preview_check_box') - self.settings_layout.addRow(self.auto_preview_check_box) - # Moved here from image tab - self.timeout_label = QtWidgets.QLabel(self.settings_group_box) - self.timeout_label.setObjectName('timeout_label') - self.timeout_spin_box = QtWidgets.QSpinBox(self.settings_group_box) - self.timeout_spin_box.setObjectName('timeout_spin_box') - self.timeout_spin_box.setRange(1, 180) - self.settings_layout.addRow(self.timeout_label, self.timeout_spin_box) - self.right_layout.addWidget(self.settings_group_box) + # CCLI Details + self.ccli_group_box = QtWidgets.QGroupBox(self.left_column) + self.ccli_group_box.setObjectName('ccli_group_box') + self.ccli_layout = QtWidgets.QFormLayout(self.ccli_group_box) + self.ccli_layout.setObjectName('ccli_layout') + self.number_label = QtWidgets.QLabel(self.ccli_group_box) + self.number_label.setObjectName('number_label') + self.number_edit = QtWidgets.QLineEdit(self.ccli_group_box) + self.number_edit.setValidator(QtGui.QIntValidator()) + self.number_edit.setObjectName('number_edit') + self.ccli_layout.addRow(self.number_label, self.number_edit) + self.left_layout.addWidget(self.ccli_group_box) + # Ui Settings + self.ui_group_box = QtWidgets.QGroupBox(self.right_column) + self.ui_group_box.setObjectName('ui_group_box') + self.ui_layout = QtWidgets.QFormLayout(self.ui_group_box) + self.ui_layout.setObjectName('ui_layout') + self.recent_label = QtWidgets.QLabel(self.ui_group_box) + self.recent_label.setObjectName('recent_label') + self.recent_spin_box = QtWidgets.QSpinBox(self.ui_group_box) + self.recent_spin_box.setObjectName('recent_spin_box') + self.recent_spin_box.setMinimum(0) + self.ui_layout.addRow(self.recent_label, self.recent_spin_box) + self.media_plugin_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.media_plugin_check_box.setObjectName('media_plugin_check_box') + self.ui_layout.addRow(self.media_plugin_check_box) + self.hide_mouse_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.hide_mouse_check_box.setObjectName('hide_mouse_check_box') + self.ui_layout.addRow(self.hide_mouse_check_box) + self.double_click_live_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.double_click_live_check_box.setObjectName('double_click_live_check_box') + self.ui_layout.addRow(self.double_click_live_check_box) + self.single_click_preview_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.single_click_preview_check_box.setObjectName('single_click_preview_check_box') + self.ui_layout.addRow(self.single_click_preview_check_box) + self.single_click_service_preview_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.single_click_service_preview_check_box.setObjectName('single_click_service_preview_check_box') + self.ui_layout.addRow(self.single_click_service_preview_check_box) + self.expand_service_item_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.expand_service_item_check_box.setObjectName('expand_service_item_check_box') + self.ui_layout.addRow(self.expand_service_item_check_box) + self.slide_max_height_label = QtWidgets.QLabel(self.ui_group_box) + self.slide_max_height_label.setObjectName('slide_max_height_label') + self.slide_max_height_combo_box = QtWidgets.QComboBox(self.ui_group_box) + self.slide_max_height_combo_box.addItem('', userData=0) + self.slide_max_height_combo_box.addItem('', userData=-4) + # Generate numeric values for combo box dynamically + for px in range(60, 801, 5): + self.slide_max_height_combo_box.addItem(str(px) + 'px', userData=px) + self.slide_max_height_combo_box.setObjectName('slide_max_height_combo_box') + self.ui_layout.addRow(self.slide_max_height_label, self.slide_max_height_combo_box) + self.autoscroll_label = QtWidgets.QLabel(self.ui_group_box) + self.autoscroll_label.setObjectName('autoscroll_label') + self.autoscroll_combo_box = QtWidgets.QComboBox(self.ui_group_box) + self.autoscroll_combo_box.addItems(['', '', '', '', '', '', '', '', '', '', '', '']) + self.autoscroll_combo_box.setObjectName('autoscroll_combo_box') + self.ui_layout.addRow(self.autoscroll_label) + self.ui_layout.addRow(self.autoscroll_combo_box) + self.search_as_type_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.search_as_type_check_box.setObjectName('SearchAsType_check_box') + self.ui_layout.addRow(self.search_as_type_check_box) + self.enable_auto_close_check_box = QtWidgets.QCheckBox(self.ui_group_box) + self.enable_auto_close_check_box.setObjectName('enable_auto_close_check_box') + self.ui_layout.addRow(self.enable_auto_close_check_box) + if not is_win() and HAS_DARK_STYLE: + self.use_dark_style_checkbox = QtWidgets.QCheckBox(self.ui_group_box) + self.use_dark_style_checkbox.setObjectName('use_dark_style_checkbox') + self.ui_layout.addRow(self.use_dark_style_checkbox) + self.right_layout.addWidget(self.ui_group_box) + # Push everything in both columns to the top + self.left_layout.addStretch() self.right_layout.addStretch() - # Remove for now - self.username_label.setVisible(False) - self.username_edit.setVisible(False) - self.password_label.setVisible(False) - self.password_edit.setVisible(False) + # Connect a few things + self.search_as_type_check_box.stateChanged.connect(self.on_search_as_type_check_box_changed) def retranslate_ui(self): """ Translate the general settings tab to the currently selected language """ self.tab_title_visible = translate('OpenLP.GeneralTab', 'General') + # Application Startup self.startup_group_box.setTitle(translate('OpenLP.GeneralTab', 'Application Startup')) self.warning_check_box.setText(translate('OpenLP.GeneralTab', 'Show blank screen warning')) self.auto_open_check_box.setText(translate('OpenLP.GeneralTab', 'Automatically open the previous service file')) self.show_splash_check_box.setText(translate('OpenLP.GeneralTab', 'Show the splash screen')) + # Logo self.logo_group_box.setTitle(translate('OpenLP.GeneralTab', 'Logo')) self.logo_color_label.setText(UiStrings().BackgroundColorColon) self.logo_file_label.setText(translate('OpenLP.GeneralTab', 'Logo file:')) self.logo_hide_on_startup_check_box.setText(translate('OpenLP.GeneralTab', 'Don\'t show logo on startup')) self.check_for_updates_check_box.setText(translate('OpenLP.GeneralTab', 'Check for updates to OpenLP')) - self.settings_group_box.setTitle(translate('OpenLP.GeneralTab', 'Application Settings')) - self.click_live_slide_to_unblank_check_box.setText(translate('OpenLP.GeneralTab', - 'Unblank display when changing slide in Live')) - self.auto_unblank_check_box.setText(translate('OpenLP.GeneralTab', 'Unblank display when sending ' - 'items to Live')) - self.auto_preview_check_box.setText(translate('OpenLP.GeneralTab', - 'Automatically preview the next item in service')) - self.timeout_label.setText(translate('OpenLP.GeneralTab', 'Timed slide interval:')) - self.timeout_spin_box.setSuffix(translate('OpenLP.GeneralTab', ' sec')) + # CCLI Details self.ccli_group_box.setTitle(translate('OpenLP.GeneralTab', 'CCLI Details')) self.number_label.setText(UiStrings().CCLINumberLabel) - self.username_label.setText(translate('OpenLP.GeneralTab', 'SongSelect username:')) - self.password_label.setText(translate('OpenLP.GeneralTab', 'SongSelect password:')) self.logo_file_path_edit.dialog_caption = translate('OpenLP.AdvancedTab', 'Select Logo File') self.logo_file_path_edit.dialog_caption = translate('OpenLP.AdvancedTab', 'Select Logo File') self.logo_file_path_edit.filters = '{text};;{names} (*)'.format( text=get_images_filter(), names=UiStrings().AllFiles) + # UI Settings + self.ui_group_box.setTitle(translate('OpenLP.AdvancedTab', 'UI Settings')) + self.recent_label.setText(translate('OpenLP.AdvancedTab', 'Number of recent service files to display:')) + self.media_plugin_check_box.setText(translate('OpenLP.AdvancedTab', + 'Open the last used Library tab on startup')) + self.double_click_live_check_box.setText(translate('OpenLP.AdvancedTab', + 'Double-click to send items straight to Live')) + self.single_click_preview_check_box.setText(translate('OpenLP.AdvancedTab', + 'Preview items when clicked in Library')) + self.single_click_service_preview_check_box.setText(translate('OpenLP.AdvancedTab', + 'Preview items when clicked in Service')) + self.expand_service_item_check_box.setText(translate('OpenLP.AdvancedTab', + 'Expand new service items on creation')) + self.slide_max_height_label.setText(translate('OpenLP.AdvancedTab', + 'Max height for non-text slides\nin slide controller:')) + self.slide_max_height_combo_box.setItemText(0, translate('OpenLP.AdvancedTab', 'Disabled')) + self.slide_max_height_combo_box.setItemText(1, translate('OpenLP.AdvancedTab', 'Automatic')) + self.autoscroll_label.setText(translate('OpenLP.AdvancedTab', + 'When changing slides:')) + self.autoscroll_combo_box.setItemText(0, translate('OpenLP.AdvancedTab', 'Do not auto-scroll')) + self.autoscroll_combo_box.setItemText(1, translate('OpenLP.AdvancedTab', + 'Auto-scroll the previous slide into view')) + self.autoscroll_combo_box.setItemText(2, translate('OpenLP.AdvancedTab', + 'Auto-scroll the previous slide to top')) + self.autoscroll_combo_box.setItemText(3, translate('OpenLP.AdvancedTab', + 'Auto-scroll the previous slide to middle')) + self.autoscroll_combo_box.setItemText(4, translate('OpenLP.AdvancedTab', + 'Auto-scroll the current slide into view')) + self.autoscroll_combo_box.setItemText(5, translate('OpenLP.AdvancedTab', + 'Auto-scroll the current slide to top')) + self.autoscroll_combo_box.setItemText(6, translate('OpenLP.AdvancedTab', + 'Auto-scroll the current slide to middle')) + self.autoscroll_combo_box.setItemText(7, translate('OpenLP.AdvancedTab', + 'Auto-scroll the current slide to bottom')) + self.autoscroll_combo_box.setItemText(8, translate('OpenLP.AdvancedTab', + 'Auto-scroll the next slide into view')) + self.autoscroll_combo_box.setItemText(9, translate('OpenLP.AdvancedTab', + 'Auto-scroll the next slide to top')) + self.autoscroll_combo_box.setItemText(10, translate('OpenLP.AdvancedTab', + 'Auto-scroll the next slide to middle')) + self.autoscroll_combo_box.setItemText(11, translate('OpenLP.AdvancedTab', + 'Auto-scroll the next slide to bottom')) + self.enable_auto_close_check_box.setText(translate('OpenLP.AdvancedTab', + 'Enable application exit confirmation')) + self.search_as_type_check_box.setText(translate('SongsPlugin.GeneralTab', 'Enable search as you type')) + if not is_win() and HAS_DARK_STYLE: + self.use_dark_style_checkbox.setText(translate('OpenLP.AdvancedTab', 'Use dark style (needs restart)')) + self.hide_mouse_check_box.setText(translate('OpenLP.AdvancedTab', 'Hide mouse cursor when over display window')) def load(self): """ Load the settings to populate the form """ self.number_edit.setText(self.settings.value('core/ccli number')) - self.username_edit.setText(self.settings.value('core/songselect username')) - self.password_edit.setText(self.settings.value('core/songselect password')) - self.auto_unblank_check_box.setChecked(self.settings.value('core/auto unblank')) - self.click_live_slide_to_unblank_check_box.setChecked(self.settings.value('core/click live slide to unblank')) self.warning_check_box.setChecked(self.settings.value('core/blank warning')) self.auto_open_check_box.setChecked(self.settings.value('core/auto open')) self.show_splash_check_box.setChecked(self.settings.value('core/show splash')) @@ -198,8 +259,32 @@ class GeneralTab(SettingsTab): self.logo_hide_on_startup_check_box.setChecked(self.settings.value('core/logo hide on startup')) self.logo_color_button.color = self.logo_background_color self.check_for_updates_check_box.setChecked(self.settings.value('core/update check')) - self.auto_preview_check_box.setChecked(self.settings.value('core/auto preview')) - self.timeout_spin_box.setValue(self.settings.value('core/loop delay')) + # UI Settings + # The max recent files value does not have an interface and so never + # gets actually stored in the settings therefore the default value of + # 20 will always be used. + self.recent_spin_box.setMaximum(self.settings.value('advanced/max recent files')) + self.recent_spin_box.setValue(self.settings.value('advanced/recent file count')) + self.media_plugin_check_box.setChecked(self.settings.value('advanced/save current plugin')) + self.double_click_live_check_box.setChecked(self.settings.value('advanced/double click live')) + self.single_click_preview_check_box.setChecked(self.settings.value('advanced/single click preview')) + self.single_click_service_preview_check_box.setChecked( + self.settings.value('advanced/single click service preview')) + self.expand_service_item_check_box.setChecked(self.settings.value('advanced/expand service item')) + slide_max_height_value = self.settings.value('advanced/slide max height') + for i in range(0, self.slide_max_height_combo_box.count()): + if self.slide_max_height_combo_box.itemData(i) == slide_max_height_value: + self.slide_max_height_combo_box.setCurrentIndex(i) + autoscroll_value = self.settings.value('advanced/autoscrolling') + for i in range(0, len(self.autoscroll_map)): + if self.autoscroll_map[i] == autoscroll_value and i < self.autoscroll_combo_box.count(): + self.autoscroll_combo_box.setCurrentIndex(i) + self.enable_auto_close_check_box.setChecked(self.settings.value('advanced/enable exit confirmation')) + if not is_win() and HAS_DARK_STYLE: + self.use_dark_style_checkbox.setChecked(self.settings.value('advanced/use_dark_style')) + self.hide_mouse_check_box.setChecked(self.settings.value('advanced/hide mouse')) + self.is_search_as_you_type_enabled = self.settings.value('advanced/search as type') + self.search_as_type_check_box.setChecked(self.is_search_as_you_type_enabled) def save(self): """ @@ -212,14 +297,24 @@ class GeneralTab(SettingsTab): self.settings.setValue('core/logo file', self.logo_file_path_edit.path) self.settings.setValue('core/logo hide on startup', self.logo_hide_on_startup_check_box.isChecked()) self.settings.setValue('core/update check', self.check_for_updates_check_box.isChecked()) - self.settings.setValue('core/auto unblank', self.auto_unblank_check_box.isChecked()) - self.settings.setValue('core/click live slide to unblank', - self.click_live_slide_to_unblank_check_box.isChecked()) - self.settings.setValue('core/auto preview', self.auto_preview_check_box.isChecked()) - self.settings.setValue('core/loop delay', self.timeout_spin_box.value()) self.settings.setValue('core/ccli number', self.number_edit.displayText()) - self.settings.setValue('core/songselect username', self.username_edit.displayText()) - self.settings.setValue('core/songselect password', self.password_edit.displayText()) + # UI Settings + self.settings.setValue('advanced/recent file count', self.recent_spin_box.value()) + self.settings.setValue('advanced/save current plugin', self.media_plugin_check_box.isChecked()) + self.settings.setValue('advanced/double click live', self.double_click_live_check_box.isChecked()) + self.settings.setValue('advanced/single click preview', self.single_click_preview_check_box.isChecked()) + self.settings.setValue('advanced/single click service preview', + self.single_click_service_preview_check_box.isChecked()) + self.settings.setValue('advanced/expand service item', self.expand_service_item_check_box.isChecked()) + slide_max_height_index = self.slide_max_height_combo_box.currentIndex() + slide_max_height_value = self.slide_max_height_combo_box.itemData(slide_max_height_index) + self.settings.setValue('advanced/slide max height', slide_max_height_value) + self.settings.setValue('advanced/autoscrolling', self.autoscroll_map[self.autoscroll_combo_box.currentIndex()]) + self.settings.setValue('advanced/enable exit confirmation', self.enable_auto_close_check_box.isChecked()) + self.settings.setValue('advanced/hide mouse', self.hide_mouse_check_box.isChecked()) + self.settings.setValue('advanced/search as type', self.is_search_as_you_type_enabled) + if not is_win() and HAS_DARK_STYLE: + self.settings.setValue('advanced/use_dark_style', self.use_dark_style_checkbox.isChecked()) self.post_set_up() def post_set_up(self): @@ -233,3 +328,8 @@ class GeneralTab(SettingsTab): Select the background color for logo. """ self.logo_background_color = color + + def on_search_as_type_check_box_changed(self, check_state): + self.is_search_as_you_type_enabled = (check_state == QtCore.Qt.Checked) + self.settings_form.register_post_process('songs_config_updated') + self.settings_form.register_post_process('custom_config_updated') diff --git a/openlp/core/ui/media/mediatab.py b/openlp/core/ui/media/mediatab.py index 5e853be38..9a4d4086f 100644 --- a/openlp/core/ui/media/mediatab.py +++ b/openlp/core/ui/media/mediatab.py @@ -64,11 +64,12 @@ class MediaTab(SettingsTab): self.left_layout.addWidget(self.live_media_group_box) self.vlc_arguments_group_box = QtWidgets.QGroupBox(self.left_column) self.vlc_arguments_group_box.setObjectName('vlc_arguments_group_box') - self.vlc_arguments_layout = QtWidgets.QHBoxLayout(self.vlc_arguments_group_box) + self.vlc_arguments_layout = QtWidgets.QFormLayout(self.vlc_arguments_group_box) self.vlc_arguments_layout.setObjectName('vlc_arguments_layout') - self.vlc_arguments_layout.setContentsMargins(0, 0, 0, 0) + self.vlc_arguments_label = QtWidgets.QLabel(self.vlc_arguments_group_box) + self.vlc_arguments_label.setObjectName('vlc_arguments_label') self.vlc_arguments_edit = QtWidgets.QLineEdit(self) - self.vlc_arguments_layout.addWidget(self.vlc_arguments_edit) + self.vlc_arguments_layout.addRow(self.vlc_arguments_label, self.vlc_arguments_edit) self.left_layout.addWidget(self.vlc_arguments_group_box) self.left_layout.addStretch() self.right_layout.addStretch() @@ -80,7 +81,8 @@ class MediaTab(SettingsTab): Translate the UI on the fly """ self.live_media_group_box.setTitle(translate('MediaPlugin.MediaTab', 'Live Media')) - self.vlc_arguments_group_box.setTitle(translate('MediaPlugin.MediaTab', 'VLC arguments (requires restart)')) + self.vlc_arguments_group_box.setTitle(translate('MediaPlugin.MediaTab', 'VLC (requires restart)')) + self.vlc_arguments_label.setText(translate('MediaPlugin.MediaTab', 'Extra arguments:')) self.auto_start_check_box.setText(translate('MediaPlugin.MediaTab', 'Start Live items automatically')) def load(self): diff --git a/openlp/core/ui/servicetab.py b/openlp/core/ui/servicetab.py new file mode 100644 index 000000000..602373184 --- /dev/null +++ b/openlp/core/ui/servicetab.py @@ -0,0 +1,326 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2020 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, either version 3 of the License, or # +# (at your option) any later version. # +# # +# 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, see . # +########################################################################## +""" +The services tab of the configuration dialog. +""" +import logging +from datetime import datetime, timedelta + +from PyQt5 import QtCore, QtGui, QtWidgets + +from openlp.core.common import SlideLimits +from openlp.core.common.i18n import UiStrings, format_time, translate +from openlp.core.ui.icons import UiIcons +from openlp.core.lib.settingstab import SettingsTab + +log = logging.getLogger(__name__) + + +class ServiceTab(SettingsTab): + """ + ServiceTab is the service settings tab in the settings dialog. + """ + def __init__(self, parent): + """ + Initialise the service settings tab + """ + # self.logo_background_color = '#ffffff' + self.icon_path = UiIcons().live + self.should_update_service_name_example = True + service_translated = translate('OpenLP.ServiceTab', 'Service') + super(ServiceTab, self).__init__(parent, 'Service', service_translated) + + def setup_ui(self): + """ + Create the user interface for the service settings tab + """ + self.setObjectName('ServiceTab') + super(ServiceTab, self).setup_ui() + self.tab_layout.setStretch(1, 1) + # Default service name + self.service_name_group_box = QtWidgets.QGroupBox(self.left_column) + self.service_name_group_box.setObjectName('service_name_group_box') + self.service_name_layout = QtWidgets.QFormLayout(self.service_name_group_box) + self.service_name_check_box = QtWidgets.QCheckBox(self.service_name_group_box) + self.service_name_check_box.setObjectName('service_name_check_box') + self.service_name_layout.setObjectName('service_name_layout') + self.service_name_layout.addRow(self.service_name_check_box) + self.service_name_time_label = QtWidgets.QLabel(self.service_name_group_box) + self.service_name_time_label.setObjectName('service_name_time_label') + self.service_name_day = QtWidgets.QComboBox(self.service_name_group_box) + self.service_name_day.addItems(['', '', '', '', '', '', '', '']) + self.service_name_day.setObjectName('service_name_day') + self.service_name_time = QtWidgets.QTimeEdit(self.service_name_group_box) + self.service_name_time.setObjectName('service_name_time') + self.service_name_time_layout = QtWidgets.QHBoxLayout() + self.service_name_time_layout.setObjectName('service_name_time_layout') + self.service_name_time_layout.addWidget(self.service_name_day) + self.service_name_time_layout.addWidget(self.service_name_time) + self.service_name_layout.addRow(self.service_name_time_label, self.service_name_time_layout) + self.service_name_label = QtWidgets.QLabel(self.service_name_group_box) + self.service_name_label.setObjectName('service_name_label') + self.service_name_edit = QtWidgets.QLineEdit(self.service_name_group_box) + self.service_name_edit.setObjectName('service_name_edit') + self.service_name_edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(r'[^/\\?*|<>\[\]":+]+'), self)) + self.service_name_revert_button = QtWidgets.QToolButton(self.service_name_group_box) + self.service_name_revert_button.setObjectName('service_name_revert_button') + self.service_name_revert_button.setIcon(UiIcons().undo) + self.service_name_button_layout = QtWidgets.QHBoxLayout() + self.service_name_button_layout.setObjectName('service_name_button_layout') + self.service_name_button_layout.addWidget(self.service_name_edit) + self.service_name_button_layout.addWidget(self.service_name_revert_button) + self.service_name_layout.addRow(self.service_name_label, self.service_name_button_layout) + self.service_name_example_label = QtWidgets.QLabel(self.service_name_group_box) + self.service_name_example_label.setObjectName('service_name_example_label') + self.service_name_example = QtWidgets.QLabel(self.service_name_group_box) + self.service_name_example.setObjectName('service_name_example') + self.service_name_layout.addRow(self.service_name_example_label, self.service_name_example) + self.left_layout.addWidget(self.service_name_group_box) + # Slide Controller + self.slide_controller_groupbox = QtWidgets.QGroupBox(self.left_column) + self.slide_controller_groupbox.setObjectName('slide_controller_groupbox') + self.slide_controller_layout = QtWidgets.QFormLayout(self.slide_controller_groupbox) + self.slide_controller_layout.setObjectName('slide_controller_layout') + self.auto_unblank_check_box = QtWidgets.QCheckBox(self.slide_controller_groupbox) + self.auto_unblank_check_box.setObjectName('auto_unblank_check_box') + self.slide_controller_layout.addRow(self.auto_unblank_check_box) + self.click_live_slide_to_unblank_check_box = QtWidgets.QCheckBox(self.slide_controller_groupbox) + self.click_live_slide_to_unblank_check_box.setObjectName('click_live_slide_to_unblank') + self.slide_controller_layout.addRow(self.click_live_slide_to_unblank_check_box) + self.auto_preview_check_box = QtWidgets.QCheckBox(self.slide_controller_groupbox) + self.auto_preview_check_box.setObjectName('auto_preview_check_box') + self.slide_controller_layout.addRow(self.auto_preview_check_box) + self.timeout_label = QtWidgets.QLabel(self.slide_controller_groupbox) + self.timeout_label.setObjectName('timeout_label') + self.timeout_spin_box = QtWidgets.QSpinBox(self.slide_controller_groupbox) + self.timeout_spin_box.setObjectName('timeout_spin_box') + self.timeout_spin_box.setRange(1, 180) + self.slide_controller_layout.addRow(self.timeout_label, self.timeout_spin_box) + self.left_layout.addWidget(self.slide_controller_groupbox) + # Service Item Wrapping + self.slide_group_box = QtWidgets.QGroupBox(self.right_column) + self.slide_group_box.setObjectName('slide_group_box') + self.slide_layout = QtWidgets.QVBoxLayout(self.slide_group_box) + self.slide_layout.setObjectName('slide_layout') + self.slide_label = QtWidgets.QLabel(self.slide_group_box) + self.slide_label.setWordWrap(True) + self.slide_layout.addWidget(self.slide_label) + self.end_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) + self.end_slide_radio_button.setObjectName('end_slide_radio_button') + self.slide_layout.addWidget(self.end_slide_radio_button) + self.wrap_slide_radio_button = QtWidgets.QRadioButton(self.slide_group_box) + self.wrap_slide_radio_button.setObjectName('wrap_slide_radio_button') + self.slide_layout.addWidget(self.wrap_slide_radio_button) + self.next_item_radio_button = QtWidgets.QRadioButton(self.slide_group_box) + self.next_item_radio_button.setObjectName('next_item_radio_button') + self.slide_layout.addWidget(self.next_item_radio_button) + self.right_layout.addWidget(self.slide_group_box) + # Push everything in both columns to the top + self.left_layout.addStretch() + self.right_layout.addStretch() + # Connect signals and slots + self.should_update_service_name_example = False + # Default Service Name + self.service_name_check_box.toggled.connect(self.service_name_check_box_toggled) + self.service_name_day.currentIndexChanged.connect(self.on_service_name_day_changed) + self.service_name_time.timeChanged.connect(self.update_service_name_example) + self.service_name_edit.textChanged.connect(self.update_service_name_example) + self.service_name_revert_button.clicked.connect(self.on_service_name_revert_button_clicked) + # Service Item Wrapping + self.end_slide_radio_button.clicked.connect(self.on_end_slide_button_clicked) + self.wrap_slide_radio_button.clicked.connect(self.on_wrap_slide_button_clicked) + self.next_item_radio_button.clicked.connect(self.on_next_item_button_clicked) + + def retranslate_ui(self): + """ + Translate the service settings tab to the currently selected language + """ + self.tab_title_visible = translate('OpenLP.ServiceTab', 'Service') + # Default Service Name + self.service_name_group_box.setTitle(translate('OpenLP.ServiceTab', 'Default Service Name')) + self.service_name_check_box.setText(translate('OpenLP.ServiceTab', 'Enable default service name')) + self.service_name_time_label.setText(translate('OpenLP.ServiceTab', 'Date and Time:')) + self.service_name_day.setItemText(0, translate('OpenLP.ServiceTab', 'Monday')) + self.service_name_day.setItemText(1, translate('OpenLP.ServiceTab', 'Tuesday')) + self.service_name_day.setItemText(2, translate('OpenLP.ServiceTab', 'Wednesday')) + self.service_name_day.setItemText(3, translate('OpenLP.ServiceTab', 'Thursday')) + self.service_name_day.setItemText(4, translate('OpenLP.ServiceTab', 'Friday')) + self.service_name_day.setItemText(5, translate('OpenLP.ServiceTab', 'Saturday')) + self.service_name_day.setItemText(6, translate('OpenLP.ServiceTab', 'Sunday')) + self.service_name_day.setItemText(7, translate('OpenLP.ServiceTab', 'Now')) + self.service_name_time.setToolTip(translate('OpenLP.ServiceTab', 'Time service usually starts.')) + self.service_name_label.setText(translate('OpenLP.ServiceTab', 'Name:')) + self.service_name_edit.setToolTip(translate('OpenLP.ServiceTab', 'Consult the OpenLP manual for usage.')) + self.service_name_revert_button.setToolTip( + translate('OpenLP.ServiceTab', + 'Revert to the default service name "{name}".').format(name=UiStrings().DefaultServiceName)) + self.service_name_example_label.setText(translate('OpenLP.ServiceTab', 'Example:')) + # Slide Controller + self.slide_controller_groupbox.setTitle(translate('OpenLP.ServiceTab', 'Slide Controller')) + self.click_live_slide_to_unblank_check_box.setText(translate('OpenLP.ServiceTab', + 'Unblank display when changing slide in Live')) + self.auto_unblank_check_box.setText(translate('OpenLP.ServiceTab', 'Unblank display when sending ' + 'items to Live')) + self.auto_preview_check_box.setText(translate('OpenLP.ServiceTab', + 'Automatically preview the next item in service')) + self.timeout_label.setText(translate('OpenLP.ServiceTab', 'Timed slide interval:')) + self.timeout_spin_box.setSuffix(translate('OpenLP.ServiceTab', ' sec')) + # Service Item Wrapping + self.slide_group_box.setTitle(translate('OpenLP.ServiceTab', 'Service Item Wrapping')) + self.slide_label.setText(translate('OpenLP.ServiceTab', 'Behavior of next/previous on the last/first slide:')) + self.end_slide_radio_button.setText(translate('OpenLP.ServiceTab', '&Remain on Slide')) + self.wrap_slide_radio_button.setText(translate('OpenLP.ServiceTab', '&Wrap around')) + self.next_item_radio_button.setText(translate('OpenLP.ServiceTab', '&Move to next/previous service item')) + + def load(self): + """ + Load the settings to populate the form + """ + # Default Service Name + self.service_name_day.setCurrentIndex(self.settings.value('advanced/default service day')) + self.service_name_time.setTime(QtCore.QTime(self.settings.value('advanced/default service hour'), + self.settings.value('advanced/default service minute'))) + self.should_update_service_name_example = True + self.service_name_edit.setText(self.settings.value('advanced/default service name')) + default_service_enabled = self.settings.value('advanced/default service enabled') + self.service_name_check_box.setChecked(default_service_enabled) + self.service_name_check_box_toggled(default_service_enabled) + # Slide Controller + self.auto_unblank_check_box.setChecked(self.settings.value('core/auto unblank')) + self.click_live_slide_to_unblank_check_box.setChecked(self.settings.value('core/click live slide to unblank')) + self.auto_preview_check_box.setChecked(self.settings.value('core/auto preview')) + self.timeout_spin_box.setValue(self.settings.value('core/loop delay')) + # Service Item Wrapping + self.slide_limits = self.settings.value('advanced/slide limits') + if self.slide_limits == SlideLimits.End: + self.end_slide_radio_button.setChecked(True) + elif self.slide_limits == SlideLimits.Wrap: + self.wrap_slide_radio_button.setChecked(True) + else: + self.next_item_radio_button.setChecked(True) + + def save(self): + """ + Save the settings from the form + """ + # Default Service Name + self.settings.setValue('advanced/default service enabled', self.service_name_check_box.isChecked()) + service_name = self.service_name_edit.text() + preset_is_valid = self.generate_service_name_example()[0] + if service_name == UiStrings().DefaultServiceName or not preset_is_valid: + self.settings.remove('advanced/default service name') + self.service_name_edit.setText(service_name) + else: + self.settings.setValue('advanced/default service name', service_name) + self.settings.setValue('advanced/default service day', self.service_name_day.currentIndex()) + self.settings.setValue('advanced/default service hour', self.service_name_time.time().hour()) + self.settings.setValue('advanced/default service minute', self.service_name_time.time().minute()) + # Slide Controller + self.settings.setValue('core/auto unblank', self.auto_unblank_check_box.isChecked()) + self.settings.setValue('core/click live slide to unblank', + self.click_live_slide_to_unblank_check_box.isChecked()) + self.settings.setValue('core/auto preview', self.auto_preview_check_box.isChecked()) + self.settings.setValue('core/loop delay', self.timeout_spin_box.value()) + # Service Item Wrapping + self.settings.setValue('advanced/slide limits', self.slide_limits) + self.settings_form.register_post_process('slidecontroller_update_slide_limits') + self.post_set_up() + + def post_set_up(self): + """ + Apply settings after the tab has loaded + """ + self.settings_form.register_post_process('slidecontroller_live_spin_delay') + + def service_name_check_box_toggled(self, default_service_enabled): + """ + Service Name options changed + """ + self.service_name_day.setEnabled(default_service_enabled) + time_enabled = default_service_enabled and self.service_name_day.currentIndex() != 7 + self.service_name_time.setEnabled(time_enabled) + self.service_name_edit.setEnabled(default_service_enabled) + self.service_name_revert_button.setEnabled(default_service_enabled) + + def generate_service_name_example(self): + """ + Display an example of the template used + """ + preset_is_valid = True + if self.service_name_day.currentIndex() == 7: + local_time = datetime.now() + else: + now = datetime.now() + day_delta = self.service_name_day.currentIndex() - now.weekday() + if day_delta < 0: + day_delta += 7 + time = now + timedelta(days=day_delta) + local_time = time.replace( + hour=self.service_name_time.time().hour(), + minute=self.service_name_time.time().minute() + ) + try: + service_name_example = format_time(self.service_name_edit.text(), local_time) + except ValueError: + preset_is_valid = False + service_name_example = translate('OpenLP.ServiceTab', 'Syntax error.') + return preset_is_valid, service_name_example + + def update_service_name_example(self, returned_value): + """ + Update the example service name. + """ + if not self.should_update_service_name_example: + return + name_example = self.generate_service_name_example()[1] + self.service_name_example.setText(name_example) + + def on_service_name_day_changed(self, service_day): + """ + React to the day of the service name changing. + """ + self.service_name_time.setEnabled(service_day != 7) + self.update_service_name_example(None) + + def on_service_name_revert_button_clicked(self): + """ + Revert to the default service name. + """ + self.service_name_edit.setText(UiStrings().DefaultServiceName) + self.service_name_edit.setFocus() + + def on_end_slide_button_clicked(self): + """ + Stop at the end either top ot bottom + """ + self.slide_limits = SlideLimits.End + + def on_wrap_slide_button_clicked(self): + """ + Wrap round the service item + """ + self.slide_limits = SlideLimits.Wrap + + def on_next_item_button_clicked(self): + """ + Advance to the next service item + """ + self.slide_limits = SlideLimits.Next diff --git a/openlp/core/ui/settingsdialog.py b/openlp/core/ui/settingsdialog.py index 21c8bfcb9..c5d3f8a17 100644 --- a/openlp/core/ui/settingsdialog.py +++ b/openlp/core/ui/settingsdialog.py @@ -38,7 +38,7 @@ class Ui_SettingsDialog(object): """ settings_dialog.setObjectName('settings_dialog') settings_dialog.setWindowIcon(UiIcons().main_icon) - settings_dialog.resize(920, 625) + settings_dialog.resize(900, 500) self.dialog_layout = QtWidgets.QGridLayout(settings_dialog) self.dialog_layout.setObjectName('dialog_layout') self.dialog_layout.setContentsMargins(8, 8, 8, 8) diff --git a/openlp/core/ui/settingsform.py b/openlp/core/ui/settingsform.py index 262afe3e7..0570ba7ab 100644 --- a/openlp/core/ui/settingsform.py +++ b/openlp/core/ui/settingsform.py @@ -33,6 +33,7 @@ from openlp.core.lib import build_icon from openlp.core.projectors.tab import ProjectorTab from openlp.core.ui.advancedtab import AdvancedTab from openlp.core.ui.generaltab import GeneralTab +from openlp.core.ui.servicetab import ServiceTab from openlp.core.ui.screenstab import ScreensTab from openlp.core.ui.themestab import ThemesTab from openlp.core.ui.media.mediatab import MediaTab @@ -58,6 +59,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties): self.setup_ui(self) self.setting_list_widget.currentRowChanged.connect(self.list_item_changed) self.general_tab = None + self.service_tab = None self.themes_tab = None self.player_tab = None self.projector_tab = None @@ -75,6 +77,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties): # take at 0 and the rest shuffle up. self.stacked_layout.takeAt(0) self.insert_tab(self.general_tab) + self.insert_tab(self.service_tab) self.insert_tab(self.advanced_tab) self.insert_tab(self.screens_tab) self.insert_tab(self.themes_tab) @@ -159,6 +162,7 @@ class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties): """ try: self.general_tab = GeneralTab(self) + self.service_tab = ServiceTab(self) self.themes_tab = ThemesTab(self) self.projector_tab = ProjectorTab(self) self.advanced_tab = AdvancedTab(self) diff --git a/tests/functional/openlp_core/ui/test_advancedtab.py b/tests/functional/openlp_core/ui/test_advancedtab.py index 74ecfc863..7069a0893 100644 --- a/tests/functional/openlp_core/ui/test_advancedtab.py +++ b/tests/functional/openlp_core/ui/test_advancedtab.py @@ -37,20 +37,3 @@ def test_creation(settings): # THEN: assert "Advanced" == advanced_tab.tab_title, 'The tab title should be Advanced' - - -def test_change_search_as_type(settings): - """ - Test that when search as type is changed custom and song configs are updated - """ - # GIVEN: A new Advanced Tab - settings_form = SettingsForm(None) - advanced_tab = AdvancedTab(settings_form) - - # WHEN: I change search as type check box - advanced_tab.on_search_as_type_check_box_changed(True) - - # THEN: we should have two post save processed to run - assert 2 == len(settings_form.processes), 'Two post save processes should be created' - assert "songs_config_updated" in settings_form.processes, 'The songs plugin should be called' - assert "custom_config_updated" in settings_form.processes, 'The custom plugin should be called' diff --git a/tests/openlp_core/ui/test_generaltab.py b/tests/openlp_core/ui/test_generaltab.py new file mode 100644 index 000000000..a24733f45 --- /dev/null +++ b/tests/openlp_core/ui/test_generaltab.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2020 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, either version 3 of the License, or # +# (at your option) any later version. # +# # +# 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, see . # +########################################################################## +""" +Package to test the openlp.core.ui.generaltab package. +""" +from openlp.core.ui.generaltab import GeneralTab +from openlp.core.ui.settingsform import SettingsForm + + +def test_creation(settings): + """ + Test that General Tab is created. + """ + # GIVEN: A new General Tab + settings_form = SettingsForm(None) + + # WHEN: I create an general tab + general_tab = GeneralTab(settings_form) + + # THEN: + assert "Core" == general_tab.tab_title, 'The tab title should be Core' + + +def test_change_search_as_type(settings): + """ + Test that when search as type is changed custom and song configs are updated + """ + # GIVEN: A new General Tab + settings_form = SettingsForm(None) + general_tab = GeneralTab(settings_form) + + # WHEN: I change search as type check box + general_tab.on_search_as_type_check_box_changed(True) + + # THEN: we should have two post save processed to run + assert 2 == len(settings_form.processes), 'Two post save processes should be created' + assert "songs_config_updated" in settings_form.processes, 'The songs plugin should be called' + assert "custom_config_updated" in settings_form.processes, 'The custom plugin should be called' diff --git a/tests/openlp_core/ui/test_servicetab.py b/tests/openlp_core/ui/test_servicetab.py new file mode 100644 index 000000000..15ba3ca8d --- /dev/null +++ b/tests/openlp_core/ui/test_servicetab.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +########################################################################## +# OpenLP - Open Source Lyrics Projection # +# ---------------------------------------------------------------------- # +# Copyright (c) 2008-2020 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, either version 3 of the License, or # +# (at your option) any later version. # +# # +# 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, see . # +########################################################################## +""" +Package to test the openlp.core.ui.servicetab package. +""" +from openlp.core.ui.servicetab import ServiceTab +from openlp.core.ui.settingsform import SettingsForm + + +def test_creation(settings): + """ + Test that Service Tab is created. + """ + # GIVEN: A new Service Tab + settings_form = SettingsForm(None) + + # WHEN: I create an service tab + service_tab = ServiceTab(settings_form) + + # THEN: + assert "Service" == service_tab.tab_title, 'The tab title should be Service'