diff --git a/picard/config.py b/picard/config.py index 22f48eebb..5b58831f3 100644 --- a/picard/config.py +++ b/picard/config.py @@ -46,10 +46,7 @@ from picard import ( PICARD_VERSION, log, ) -from picard.profile import ( - USER_SETTINGS_PROFILE_ID, - UserProfileGroups, -) +from picard.profile import UserProfileGroups from picard.version import Version @@ -152,21 +149,14 @@ class SettingConfigSection(ConfigSection): self.__prefix = self.__name + '/' self._memoization = defaultdict(Memovar) self.init_profile_options() - self._selected_profile = None def _get_active_profile_ids(self): - if self._selected_profile is not None: - if self._selected_profile == USER_SETTINGS_PROFILE_ID: - return - # Act as if the selected profile is the only active profile. - yield self._selected_profile - else: - profiles = self.__qt_config.profiles[self.PROFILES_KEY] - if profiles is None: - return - for profile in profiles: - if profile['enabled']: - yield profile["id"] + profiles = self.__qt_config.profiles[self.PROFILES_KEY] + if profiles is None: + return + for profile in profiles: + if profile['enabled']: + yield profile["id"] def _get_active_profile_settings(self): for id in self._get_active_profile_ids(): @@ -197,10 +187,9 @@ class SettingConfigSection(ConfigSection): if name in settings: self._save_profile_setting(id, name, value) return - if self._selected_profile is None or self._selected_profile == USER_SETTINGS_PROFILE_ID: - key = self.key(name) - self.__qt_config.setValue(key, value) - self._memoization[key].dirty = True + key = self.key(name) + self.__qt_config.setValue(key, value) + self._memoization[key].dirty = True def _save_profile_setting(self, profile_id, name, value): profile_settings = self.__qt_config.profiles[self.SETTINGS_KEY] @@ -209,9 +198,6 @@ class SettingConfigSection(ConfigSection): self.__qt_config.setValue(key, profile_settings) self._memoization[key].dirty = True - def set_profile(self, profile_id=None): - self._selected_profile = profile_id - class Config(QtCore.QSettings): diff --git a/picard/profile.py b/picard/profile.py index 771df83aa..d68d40aaa 100644 --- a/picard/profile.py +++ b/picard/profile.py @@ -27,9 +27,6 @@ from collections import ( from picard import i18n # noqa: F401,E402 # pylint: disable=unused-import -USER_SETTINGS_PROFILE_ID = 'user_settings' - - SettingDesc = namedtuple('SettingDesc', ('name', 'title', 'fields')) diff --git a/picard/ui/options/dialog.py b/picard/ui/options/dialog.py index 72f62f521..0aba0f784 100644 --- a/picard/ui/options/dialog.py +++ b/picard/ui/options/dialog.py @@ -45,10 +45,7 @@ from picard.config import ( TextOption, get_config, ) -from picard.profile import ( - USER_SETTINGS_PROFILE_ID, - UserProfileGroups, -) +from picard.profile import UserProfileGroups from picard.util import ( restore_method, webbrowser2, @@ -193,19 +190,9 @@ class OptionsDialog(PicardDialog, SingletonDialog): self.first_enter = True self.installEventFilter(self) - self.USER_SETTINGS_TITLE = _("User base settings") - if config.profiles[SettingConfigSection.PROFILES_KEY]: self.ui.profile_frame.show() - self.ui.save_to_profile.clear() - self.ui.save_to_profile.addItem(self.USER_SETTINGS_TITLE, USER_SETTINGS_PROFILE_ID) - index = 0 - for idx, item in enumerate(config.profiles[SettingConfigSection.PROFILES_KEY], start=1): - self.ui.save_to_profile.addItem(item["title"], item["id"]) - if not index and item["enabled"]: - index = idx - self.ui.save_to_profile.currentIndexChanged.connect(self.switch_profile) - self.ui.save_to_profile.setCurrentIndex(index) + self.highlight_enabled_profile_options() else: self.ui.profile_frame.hide() @@ -237,39 +224,31 @@ class OptionsDialog(PicardDialog, SingletonDialog): profile_dialog.activateWindow() def _get_profile_title_from_id(self, profile_id): - if profile_id == USER_SETTINGS_PROFILE_ID: - return self.USER_SETTINGS_TITLE config = get_config() for item in config.profiles[SettingConfigSection.PROFILES_KEY]: if item["id"] == profile_id: return item["title"] return _('Unknown profile') - def switch_profile(self, index): + def highlight_enabled_profile_options(self): + config = get_config() + if not config.profiles[SettingConfigSection.PROFILES_KEY]: + return + + self.ui.notice_text.hide() + HighlightColors = namedtuple('HighlightColors', ('fg', 'bg')) HIGHLIGHT_FMT = "#%s { color: %s; background-color: %s; }" if theme.is_dark_theme: option_colors = HighlightColors('#FFFFFF', '#000080') - profile_colors = HighlightColors('#FFFFFF', '#300000') else: option_colors = HighlightColors('#000000', '#F9F906') - profile_colors = HighlightColors('#000000', '#FFA500') - # Highlight profile selector if profile selected. - if self.ui.save_to_profile.currentIndex(): - self.ui.save_to_profile.setStyleSheet(HIGHLIGHT_FMT % ('save_to_profile', profile_colors.fg, profile_colors.bg)) - else: - self.ui.save_to_profile.setStyleSheet("") + self.ui.notice_text.setStyleSheet(HIGHLIGHT_FMT % ("notice_text", option_colors.fg, option_colors.bg)) + self.ui.notice_text.setText(_("Highlighted options will be saved to a profile.")) + self.ui.notice_text.setToolTip(_("Hover your cursor over a highlighted option to see which profile will be updated.")) - profile_id = self.ui.save_to_profile.currentData() - profile_title = self._get_profile_title_from_id(profile_id) - config = get_config() - config.setting.set_profile(profile_id) settings = config.profiles[SettingConfigSection.SETTINGS_KEY] - if profile_id in settings: - profile_settings = settings[profile_id] - else: - profile_settings = {} for page in self.pages: page.load() @@ -281,17 +260,24 @@ class OptionsDialog(PicardDialog, SingletonDialog): obj = getattr(page.ui, opt_field) except AttributeError: continue - if opt.name in profile_settings: - style = HIGHLIGHT_FMT % (opt_field, option_colors.fg, option_colors.bg) - tooltip = _("This option is managed by profile: %s") % profile_title - else: - style = "" - tooltip = "" - try: - obj.setStyleSheet(style) - obj.setToolTip(tooltip) - except AttributeError: - pass + for item in config.profiles[SettingConfigSection.PROFILES_KEY]: + if item["enabled"]: + profile_id = item["id"] + profile_title = item["title"] + if profile_id in settings: + profile_settings = settings[profile_id] + else: + profile_settings = {} + if opt.name in profile_settings: + style = HIGHLIGHT_FMT % (opt_field, option_colors.fg, option_colors.bg) + tooltip = _("This option will be saved to profile: %s") % profile_title + try: + obj.setStyleSheet(style) + obj.setToolTip(tooltip) + except AttributeError: + pass + self.ui.notice_text.show() + break def eventFilter(self, object, event): """Process selected events. @@ -333,17 +319,6 @@ class OptionsDialog(PicardDialog, SingletonDialog): return url def accept(self): - profile_id = self.ui.save_to_profile.currentData() - if profile_id and profile_id != USER_SETTINGS_PROFILE_ID: - profile_name = self._get_profile_title_from_id(profile_id) - message_box = QtWidgets.QMessageBox(self) - message_box.setIcon(QtWidgets.QMessageBox.Warning) - message_box.setWindowModality(QtCore.Qt.WindowModal) - message_box.setWindowTitle(_("Save to Profile")) - message_box.setText(_("Changes will only be saved to the profile: \"%s\"\n\nDo you want to continue?") % profile_name) - message_box.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel) - if message_box.exec_() != QtWidgets.QMessageBox.Yes: - return for page in self.pages: try: page.check() @@ -361,18 +336,8 @@ class OptionsDialog(PicardDialog, SingletonDialog): log.exception('Failed saving options page %r', page) self._show_page_error(page, e) return - self.reset_profile() super().accept() - def reject(self): - self.reset_profile() - super().reject() - - @staticmethod - def reset_profile(): - config = get_config() - config.setting.set_profile() - def _show_page_error(self, page, error): if not isinstance(error, OptionsCheckError): error = OptionsCheckError(_('Unexpected error'), str(error)) @@ -462,7 +427,7 @@ class AttachedProfilesDialog(PicardDialog): window_title = _("Profiles Attached to Options in %s Section") % group_title self.setWindowTitle(window_title) - for name, title in group_options: + for name, title, object_name in group_options: option_item = QtGui.QStandardItem(_(title)) option_item.setEditable(False) row = [option_item] diff --git a/picard/ui/ui_options.py b/picard/ui/ui_options.py index 5dac32f3b..a3ea4327e 100644 --- a/picard/ui/ui_options.py +++ b/picard/ui/ui_options.py @@ -39,25 +39,24 @@ class Ui_Dialog(object): self.profile_frame.setLineWidth(0) self.profile_frame.setObjectName("profile_frame") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.profile_frame) + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.notice_text = QtWidgets.QLabel(self.profile_frame) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.notice_text.sizePolicy().hasHeightForWidth()) + self.notice_text.setSizePolicy(sizePolicy) + font = QtGui.QFont() + font.setPointSize(10) + font.setBold(False) + font.setWeight(50) + self.notice_text.setFont(font) + self.notice_text.setText("") + self.notice_text.setObjectName("notice_text") + self.horizontalLayout_2.addWidget(self.notice_text) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) - self.label = QtWidgets.QLabel(self.profile_frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) - self.label.setSizePolicy(sizePolicy) - self.label.setObjectName("label") - self.horizontalLayout_2.addWidget(self.label) - self.save_to_profile = QtWidgets.QComboBox(self.profile_frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.save_to_profile.sizePolicy().hasHeightForWidth()) - self.save_to_profile.setSizePolicy(sizePolicy) - self.save_to_profile.setObjectName("save_to_profile") - self.horizontalLayout_2.addWidget(self.save_to_profile) self.profiles_buttonbox = QtWidgets.QDialogButtonBox(self.profile_frame) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) @@ -80,4 +79,3 @@ class Ui_Dialog(object): def retranslateUi(self, Dialog): _translate = QtCore.QCoreApplication.translate Dialog.setWindowTitle(_("Options")) - self.label.setText(_("Save settings to:")) diff --git a/test/test_profiles.py b/test/test_profiles.py index 4eb79c80a..4b12c9e73 100644 --- a/test/test_profiles.py +++ b/test/test_profiles.py @@ -199,108 +199,6 @@ class TestUserProfiles(TestPicardProfilesCommon): self.assertEqual(self.config.setting[self.test_setting_1], False) self.assertEqual(self.config.setting[self.test_setting_2], 99) - # Test retrieval with profiles disabled and specific profile set - self.config.profiles[self.PROFILES_KEY] = self.get_profiles(enabled=False) - self.config.setting.set_profile("test_key_0") - self.assertEqual(self.config.setting[self.test_setting_0], "def") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 86) - - # Test setting with profiles disabled and specific profile set - self.config.setting[self.test_setting_0] = "jkl" - - # Stack: - # setting_0 setting_1 setting_2 - # --------- --------- --------- - # test_key_0: jkl n/a n/a - # test_key_1: n/a False n/a - # test_key_2: n/a n/a 99 - # user_settings: ghi True 86 - - self.assertEqual(self.config.setting[self.test_setting_0], "jkl") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 86) - - # Test retrieval with profiles disabled and no specific profile set - self.config.profiles[self.PROFILES_KEY] = self.get_profiles(enabled=False) - self.config.setting.set_profile() - self.assertEqual(self.config.setting[self.test_setting_0], "ghi") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 86) - - # Test retrieval with profiles enabled and no specific profile set - self.config.profiles[self.PROFILES_KEY] = self.get_profiles(enabled=True) - self.config.setting.set_profile() - self.assertEqual(self.config.setting[self.test_setting_0], "jkl") - self.assertEqual(self.config.setting[self.test_setting_1], False) - self.assertEqual(self.config.setting[self.test_setting_2], 99) - - # Test save with profiles disabled and specific profile set - self.config.profiles[self.PROFILES_KEY] = self.get_profiles(enabled=False) - self.config.setting.set_profile("test_key_2") - self.config.setting[self.test_setting_0] = "xyz" - self.config.setting[self.test_setting_2] = 1 - - # Stack: - # setting_0 setting_1 setting_2 - # --------- --------- --------- - # test_key_0: jkl n/a n/a - # test_key_1: n/a False n/a - # test_key_2: n/a n/a 1 - # user_settings: ghi True 86 - - self.assertEqual(self.config.setting[self.test_setting_0], "ghi") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 1) - self.config.setting.set_profile() - self.assertEqual(self.config.setting[self.test_setting_0], "ghi") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 86) - - # Test save with profiles enabled and specific profile set - self.config.profiles[self.PROFILES_KEY] = self.get_profiles(enabled=True) - self.config.setting.set_profile("test_key_2") - self.config.setting[self.test_setting_0] = "xyz" - self.config.setting[self.test_setting_2] = 2 - - # Stack: - # setting_0 setting_1 setting_2 - # --------- --------- --------- - # test_key_0: jkl n/a n/a - # test_key_1: n/a False n/a - # test_key_2: n/a n/a 2 - # user_settings: ghi True 86 - - self.assertEqual(self.config.setting[self.test_setting_0], "ghi") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 2) - self.config.setting.set_profile() - self.assertEqual(self.config.setting[self.test_setting_0], "jkl") - self.assertEqual(self.config.setting[self.test_setting_1], False) - self.assertEqual(self.config.setting[self.test_setting_2], 2) - - # Test save with profiles enabled and "user_settings" profile set - self.config.profiles[self.PROFILES_KEY] = self.get_profiles(enabled=True) - self.config.setting.set_profile("user_settings") - self.config.setting[self.test_setting_0] = "xyz" - self.config.setting[self.test_setting_2] = 3 - - # Stack: - # setting_0 setting_1 setting_2 - # --------- --------- --------- - # test_key_0: jkl n/a n/a - # test_key_1: n/a False n/a - # test_key_2: n/a n/a 2 - # user_settings: xyz True 3 - - self.assertEqual(self.config.setting[self.test_setting_0], "xyz") - self.assertEqual(self.config.setting[self.test_setting_1], True) - self.assertEqual(self.config.setting[self.test_setting_2], 3) - self.config.setting.set_profile() - self.assertEqual(self.config.setting[self.test_setting_0], "jkl") - self.assertEqual(self.config.setting[self.test_setting_1], False) - self.assertEqual(self.config.setting[self.test_setting_2], 2) - def test_config_option_rename(self): from picard.config_upgrade import rename_option self.config.setting[self.test_setting_0] = "abc" diff --git a/ui/options.ui b/ui/options.ui index 185960ca2..0061cc548 100644 --- a/ui/options.ui +++ b/ui/options.ui @@ -69,6 +69,38 @@ 0 + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 10 + 50 + false + + + + + + + @@ -82,29 +114,6 @@ - - - - - 0 - 0 - - - - Save settings to: - - - - - - - - 0 - 0 - - - -