# -*- coding: utf-8 -*- # vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4 ########################################################################## # OpenLP - Open Source Lyrics Projection # # ---------------------------------------------------------------------- # # Copyright (c) 2008-2019 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 :mod:`settingsform` provides a user interface for the OpenLP settings """ import logging from PyQt5 import QtCore, QtWidgets from openlp.core.state import State from openlp.core.api.tab import ApiTab from openlp.core.common.mixins import RegistryProperties from openlp.core.common.registry import Registry from openlp.core.common.settings import Settings 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.screenstab import ScreensTab from openlp.core.ui.themestab import ThemesTab from openlp.core.ui.media.mediatab import MediaTab from openlp.core.ui.settingsdialog import Ui_SettingsDialog log = logging.getLogger(__name__) class SettingsForm(QtWidgets.QDialog, Ui_SettingsDialog, RegistryProperties): """ Provide the form to manipulate the settings for OpenLP """ def __init__(self, parent=None): """ Initialise the settings form """ Registry().register('settings_form', self) Registry().register_function('bootstrap_post_set_up', self.bootstrap_post_set_up) super(SettingsForm, self).__init__(parent, QtCore.Qt.WindowSystemMenuHint | QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowCloseButtonHint) self.processes = [] self.setup_ui(self) self.setting_list_widget.currentRowChanged.connect(self.list_item_changed) self.general_tab = None self.themes_tab = None self.projector_tab = None self.advanced_tab = None self.api_tab = None def exec(self): """ Execute the form """ # load all the widgets self.setting_list_widget.blockSignals(True) self.setting_list_widget.clear() while self.stacked_layout.count(): # take at 0 and the rest shuffle up. self.stacked_layout.takeAt(0) self.insert_tab(self.general_tab) self.insert_tab(self.advanced_tab) self.insert_tab(self.screens_tab) self.insert_tab(self.themes_tab) if Settings().value('core/experimental'): self.insert_tab(self.player_tab) self.insert_tab(self.projector_tab) self.insert_tab(self.api_tab) for plugin in State().list_plugins(): if plugin.settings_tab: self.insert_tab(plugin.settings_tab, plugin.is_active()) self.setting_list_widget.setCurrentRow(0) self.setting_list_widget.blockSignals(False) return QtWidgets.QDialog.exec(self) def insert_tab(self, tab_widget, is_visible=True): """ Add a tab to the form at a specific location :param tab_widget: The widget to add :param is_visible: If this tab should be visible """ log.debug('Inserting {text} tab'.format(text=tab_widget.tab_title)) # add the tab to get it to display in the correct part of the screen self.stacked_layout.addWidget(tab_widget) if is_visible: list_item = QtWidgets.QListWidgetItem(build_icon(tab_widget.icon_path), tab_widget.tab_title_visible) list_item.setData(QtCore.Qt.UserRole, tab_widget.tab_title) self.setting_list_widget.addItem(list_item) tab_widget.load() def accept(self): """ Process the form saving the settings """ log.debug('Processing settings exit') # We add all the forms into the stacked layout, even if the plugin is inactive, # but we don't add the item to the list on the side if the plugin is inactive, # so loop through the list items, and then find the tab for that item. for item_index in range(self.setting_list_widget.count()): # Get the list item list_item = self.setting_list_widget.item(item_index) if not list_item: continue # Now figure out if there's a tab for it, and save the tab. plugin_name = list_item.data(QtCore.Qt.UserRole) for tab_index in range(self.stacked_layout.count()): tab_widget = self.stacked_layout.widget(tab_index) if tab_widget.tab_title == plugin_name: tab_widget.save() # if the image background has been changed we need to regenerate the image cache if 'images_config_updated' in self.processes or 'config_screen_changed' in self.processes: self.register_post_process('images_regenerate') # Now lets process all the post save handlers while self.processes: Registry().execute(self.processes.pop(0)) return QtWidgets.QDialog.accept(self) def reject(self): """ Process the form saving the settings """ self.processes = [] # Same as accept(), we need to loop over the visible tabs, and skip the inactive ones for item_index in range(self.setting_list_widget.count()): # Get the list item list_item = self.setting_list_widget.item(item_index) if not list_item: continue # Now figure out if there's a tab for it, and save the tab. plugin_name = list_item.data(QtCore.Qt.UserRole) for tab_index in range(self.stacked_layout.count()): tab_widget = self.stacked_layout.widget(tab_index) if tab_widget.tab_title == plugin_name: tab_widget.cancel() return QtWidgets.QDialog.reject(self) def bootstrap_post_set_up(self): """ Run any post-setup code for the tabs on the form """ try: self.general_tab = GeneralTab(self) self.themes_tab = ThemesTab(self) self.projector_tab = ProjectorTab(self) self.advanced_tab = AdvancedTab(self) if Settings().value('core/experimental'): self.player_tab = MediaTab(self) self.api_tab = ApiTab(self) self.screens_tab = ScreensTab(self) except Exception as e: print(e) self.general_tab.post_set_up() self.themes_tab.post_set_up() self.advanced_tab.post_set_up() if Settings().value('core/experimental'): self.player_tab.post_set_up() self.api_tab.post_set_up() for plugin in State().list_plugins(): if plugin.settings_tab: plugin.settings_tab.post_set_up() def list_item_changed(self, item_index): """ A different settings tab is selected :param item_index: The index of the item that was selected """ # Get the item we clicked on list_item = self.setting_list_widget.item(item_index) # Quick exit to the left if the item doesn't exist (maybe -1?) if not list_item: return # Loop through the list of tabs in the stacked layout for tab_index in range(self.stacked_layout.count()): # Get the widget tab_widget = self.stacked_layout.itemAt(tab_index).widget() # Check that the title of the tab (i.e. plugin name) is the same as the data in the list item if tab_widget.tab_title == list_item.data(QtCore.Qt.UserRole): # Make the matching tab visible tab_widget.tab_visited = True self.stacked_layout.setCurrentIndex(tab_index) self.stacked_layout.currentWidget().tab_visible() def register_post_process(self, function): """ Register for updates to be done on save removing duplicate functions :param function: The function to be called """ if function not in self.processes: self.processes.append(function)