Skip to content

Commit

Permalink
Ensure options are registered in profiles on startup
Browse files Browse the repository at this point in the history
Move option dialog setting registration out of constructors. Fixes option
profiles only working after options dialog has been opened.
  • Loading branch information
phw committed Jan 2, 2025
1 parent 0b2a61b commit 7d95755
Show file tree
Hide file tree
Showing 28 changed files with 240 additions and 187 deletions.
4 changes: 3 additions & 1 deletion picard/extension_points/options_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Copyright (C) 2006-2007 Lukáš Lalinský
# Copyright (C) 2009 Nikolai Prokoschenko
# Copyright (C) 2009, 2019-2022 Philipp Wolfer
# Copyright (C) 2009, 2019-2022, 2025 Philipp Wolfer
# Copyright (C) 2013, 2015, 2018-2024 Laurent Monin
# Copyright (C) 2016-2017 Sambhav Kothari
#
Expand All @@ -30,3 +30,5 @@

def register_options_page(page_class):
ext_point_options_pages.register(page_class.__module__, page_class)
for opt_name, opt_highlights in page_class.OPTIONS:
page_class.register_setting(opt_name, opt_highlights)
12 changes: 5 additions & 7 deletions picard/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,15 @@
# The translated title will be displayed in Profiles option page.
#
# 2. If the option is a 'setting' which is edited in one of the option pages,
# then the option can be registered in the `__init__()` method of the
# matching `OptionPage` declaration with a call to the page's
# `register_setting()` method.
# then the option must be added to the OPTIONS tuple in the class. The
# first parameter is the option name, the second is a list of UI elements
# to highlight if the option is part of an option profile. If the setting
# can be overridden in profiles, the `highlights` has to be a list of
# widget names associated with the option.
#
# Registering a setting allows it to be reset to the default when the user
# asks for it on the corresponding option page.
#
# If the setting can be overriden in profiles, the `highlights` parameter
# has to be set a list of widget names associated with the option.
#
#
# Please, try to keep options ordered by section and name in their own group.


Expand Down
13 changes: 7 additions & 6 deletions picard/ui/options/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# Copyright (C) 2006-2007 Lukáš Lalinský
# Copyright (C) 2009 Nikolai Prokoschenko
# Copyright (C) 2009, 2019-2022 Philipp Wolfer
# Copyright (C) 2009, 2019-2022, 2025 Philipp Wolfer
# Copyright (C) 2013, 2015, 2018-2024 Laurent Monin
# Copyright (C) 2016-2017 Sambhav Kothari
#
Expand Down Expand Up @@ -53,7 +53,9 @@ class OptionsPage(QtWidgets.QWidget):
HELP_URL = None
STYLESHEET_ERROR = "QWidget { background-color: #f55; color: white; font-weight:bold; padding: 2px; }"
STYLESHEET = "QLabel { qproperty-wordWrap: true; }"
OPTIONS = ()

_registered_settings = []
initialized = False
loaded = False

Expand All @@ -72,8 +74,6 @@ def on_destroyed(obj=None):
self.deleted = True
self.destroyed.connect(on_destroyed)

self._registered_settings = []

def set_dialog(self, dialog):
self.dialog = dialog

Expand Down Expand Up @@ -131,12 +131,13 @@ def live_checker(text):

regex_edit.textChanged.connect(live_checker)

def register_setting(self, name, highlights=None):
@classmethod
def register_setting(cls, name, highlights=None):
"""Register a setting edited in the page, used to restore defaults
and to highlight when profiles are used"""
option = Option.get('setting', name)
if option is None:
raise Exception(f"Cannot register setting for non-existing option {name}")
self._registered_settings.append(option)
OptionsPage._registered_settings.append(option)
if highlights is not None:
profile_groups_add_setting(self.NAME, name, tuple(highlights), title=self.TITLE)
profile_groups_add_setting(cls.NAME, name, tuple(highlights), title=cls.TITLE)
24 changes: 13 additions & 11 deletions picard/ui/options/advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,25 @@ class AdvancedOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_advanced.html"

OPTIONS = (
('ignore_regex', ['ignore_regex']),
('ignore_hidden_files', ['ignore_hidden_files']),
('recursively_add_files', ['recursively_add_files']),
('ignore_track_duration_difference_under', ['ignore_track_duration_difference_under', 'label_track_duration_diff']),
('query_limit', ['query_limit', 'label_query_limit']),
('completeness_ignore_videos', ['completeness_ignore_videos']),
('completeness_ignore_pregap', ['completeness_ignore_pregap']),
('completeness_ignore_data', ['completeness_ignore_data']),
('completeness_ignore_silence', ['completeness_ignore_silence']),
('compare_ignore_tags', ['groupBox_ignore_tags']),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui_AdvancedOptionsPage()
self.ui.setupUi(self)
self.init_regex_checker(self.ui.ignore_regex, self.ui.regex_error)

self.register_setting('ignore_regex', ['ignore_regex'])
self.register_setting('ignore_hidden_files', ['ignore_hidden_files'])
self.register_setting('recursively_add_files', ['recursively_add_files'])
self.register_setting('ignore_track_duration_difference_under', ['ignore_track_duration_difference_under', 'label_track_duration_diff'])
self.register_setting('query_limit', ['query_limit', 'label_query_limit'])
self.register_setting('completeness_ignore_videos', ['completeness_ignore_videos'])
self.register_setting('completeness_ignore_pregap', ['completeness_ignore_pregap'])
self.register_setting('completeness_ignore_data', ['completeness_ignore_data'])
self.register_setting('completeness_ignore_silence', ['completeness_ignore_silence'])
self.register_setting('compare_ignore_tags', ['groupBox_ignore_tags'])

def load(self):
config = get_config()
self.ui.ignore_regex.setText(config.setting['ignore_regex'])
Expand Down
6 changes: 4 additions & 2 deletions picard/ui/options/cdlookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class CDLookupOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_cdlookup.html"

OPTIONS = (
('cd_lookup_device', None),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui_CDLookupOptionsPage()
Expand All @@ -60,8 +64,6 @@ def __init__(self, parent=None):
self._device_list = get_cdrom_drives()
self.ui.cd_lookup_device.addItems(self._device_list)

self.register_setting('cd_lookup_device')

def load(self):
config = get_config()
device = config.setting['cd_lookup_device']
Expand Down
28 changes: 15 additions & 13 deletions picard/ui/options/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ class CoverOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_cover.html"

OPTIONS = (
('save_images_to_tags', ['save_images_to_tags']),
('embed_only_one_front_image', ['cb_embed_front_only']),
('dont_replace_with_smaller_cover', ['cb_dont_replace_with_smaller']),
('dont_replace_cover_of_types', ['cb_never_replace_types']),
('dont_replace_included_types', ['dont_replace_included_types']),
('dont_replace_excluded_types', ['dont_replace_excluded_types']),
('save_images_to_files', ['save_images_to_files']),
('cover_image_filename', ['cover_image_filename']),
('save_images_overwrite', ['save_images_overwrite']),
('save_only_one_front_image', ['save_only_one_front_image']),
('image_type_as_filename', ['image_type_as_filename']),
('ca_providers', ['ca_providers_list']),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui_CoverOptionsPage()
Expand All @@ -72,19 +87,6 @@ def __init__(self, parent=None):
self.move_view = MoveableListView(self.ui.ca_providers_list, self.ui.up_button,
self.ui.down_button)

self.register_setting('save_images_to_tags', ['save_images_to_tags'])
self.register_setting('embed_only_one_front_image', ['cb_embed_front_only'])
self.register_setting('dont_replace_with_smaller_cover', ['dont_replace_with_smaller_cover'])
self.register_setting('dont_replace_cover_of_types', ['dont_replace_cover_of_types'])
self.register_setting('dont_replace_included_types', ['dont_replace_included_types'])
self.register_setting('dont_replace_excluded_types', ['dont_replace_excluded_types'])
self.register_setting('save_images_to_files', ['save_images_to_files'])
self.register_setting('cover_image_filename', ['cover_image_filename'])
self.register_setting('save_images_overwrite', ['save_images_overwrite'])
self.register_setting('save_only_one_front_image', ['save_only_one_front_image'])
self.register_setting('image_type_as_filename', ['image_type_as_filename'])
self.register_setting('ca_providers', ['ca_providers_list'])

def restore_defaults(self):
# Remove previous entries
self.ui.ca_providers_list.clear()
Expand Down
37 changes: 20 additions & 17 deletions picard/ui/options/cover_processing.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,27 +49,30 @@ class CoverProcessingOptionsPage(OptionsPage):
PARENT = 'cover'
SORT_ORDER = 0

OPTIONS = (
('filter_cover_by_size', None),
('cover_minimum_width', None),
('cover_minimum_height', None),
('cover_tags_enlarge', None),
('cover_tags_resize', None),
('cover_tags_resize_target_width', None),
('cover_tags_resize_target_height', None),
('cover_tags_resize_mode', None),
('cover_tags_convert_images', None),
('cover_tags_convert_to_format', None),
('cover_file_enlarge', None),
('cover_file_resize', None),
('cover_file_resize_target_width', None),
('cover_file_resize_target_height', None),
('cover_file_resize_mode', None),
('cover_file_convert_images', None),
('cover_file_convert_to_format', None),
)

def __init__(self, parent=None):
super().__init__(parent)
self.ui = Ui_CoverProcessingOptionsPage()
self.ui.setupUi(self)
self.register_setting('filter_cover_by_size')
self.register_setting('cover_minimum_width')
self.register_setting('cover_minimum_height')
self.register_setting('cover_tags_enlarge')
self.register_setting('cover_tags_resize')
self.register_setting('cover_tags_resize_target_width')
self.register_setting('cover_tags_resize_target_height')
self.register_setting('cover_tags_resize_mode')
self.register_setting('cover_tags_convert_images')
self.register_setting('cover_tags_convert_to_format')
self.register_setting('cover_file_enlarge')
self.register_setting('cover_file_resize')
self.register_setting('cover_file_resize_target_width')
self.register_setting('cover_file_resize_target_height')
self.register_setting('cover_file_resize_mode')
self.register_setting('cover_file_convert_images')
self.register_setting('cover_file_convert_to_format')

for resize_mode in COVER_RESIZE_MODES:
self.ui.tags_resize_mode.addItem(resize_mode.title, resize_mode.mode.value)
Expand Down
16 changes: 9 additions & 7 deletions picard/ui/options/fingerprinting.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ class FingerprintingOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_fingerprinting.html"

OPTIONS = (
('fingerprinting_system', None),
('acoustid_fpcalc', None),
('acoustid_apikey', None),
('ignore_existing_acoustid_fingerprints', None),
('save_acoustid_fingerprints', None),
('fpcalc_threads', None),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self._fpcalc_valid = True
Expand All @@ -79,13 +88,6 @@ def __init__(self, parent=None):
self.ui.acoustid_apikey_get.clicked.connect(self.acoustid_apikey_get)
self.ui.acoustid_apikey.setValidator(ApiKeyValidator())

self.register_setting('fingerprinting_system')
self.register_setting('acoustid_fpcalc')
self.register_setting('acoustid_apikey')
self.register_setting('ignore_existing_acoustid_fingerprints')
self.register_setting('save_acoustid_fingerprints')
self.register_setting('fpcalc_threads')

def load(self):
config = get_config()
if config.setting['fingerprinting_system'] == 'acoustid':
Expand Down
24 changes: 13 additions & 11 deletions picard/ui/options/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ class GeneralOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_general.html"

OPTIONS = (
('server_host', ['server_host']),
('server_port', ['server_port']),
('analyze_new_files', ['analyze_new_files']),
('cluster_new_files', ['cluster_new_files']),
('ignore_file_mbids', ['ignore_file_mbids']),
('check_for_plugin_updates', ['check_for_plugin_updates']),
('check_for_updates', ['check_for_updates']),
('update_check_days', ['update_check_days']),
('update_level', ['update_level']),
('use_server_for_submission', ['use_server_for_submission']),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui_GeneralOptionsPage()
Expand All @@ -74,17 +87,6 @@ def __init__(self, parent=None):
self.ui.login_error.hide()
self.update_login_logout()

self.register_setting('server_host', ['server_host'])
self.register_setting('server_port', ['server_port'])
self.register_setting('analyze_new_files', ['analyze_new_files'])
self.register_setting('cluster_new_files', ['cluster_new_files'])
self.register_setting('ignore_file_mbids', ['ignore_file_mbids'])
self.register_setting('check_for_plugin_updates', ['check_for_plugin_updates'])
self.register_setting('check_for_updates', ['check_for_updates'])
self.register_setting('update_check_days', ['update_check_days'])
self.register_setting('update_level', ['update_level'])
self.register_setting('use_server_for_submission')

def load(self):
config = get_config()
self.ui.server_host.setEditText(config.setting['server_host'])
Expand Down
20 changes: 11 additions & 9 deletions picard/ui/options/genres.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ class GenresOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_genres.html"

OPTIONS = (
('use_genres', None),
('only_my_genres', ['only_my_genres']),
('artists_genres', ['artists_genres']),
('folksonomy_tags', ['folksonomy_tags']),
('min_genre_usage', ['min_genre_usage']),
('max_genres', ['max_genres']),
('join_genres', ['join_genres']),
('genres_filter', ['genres_filter']),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui_GenresOptionsPage()
Expand All @@ -108,15 +119,6 @@ def __init__(self, parent=None):
self.fmt_clear = QTextBlockFormat()
self.fmt_clear.clearBackground()

self.register_setting('use_genres', [])
self.register_setting('only_my_genres', ['only_my_genres'])
self.register_setting('artists_genres', ['artists_genres'])
self.register_setting('folksonomy_tags', ['folksonomy_tags'])
self.register_setting('min_genre_usage', ['min_genre_usage'])
self.register_setting('max_genres', ['max_genres'])
self.register_setting('join_genres', ['join_genres'])
self.register_setting('genres_filter', ['genres_filter'])

def load(self):
config = get_config()
self.ui.use_genres.setChecked(config.setting['use_genres'])
Expand Down
30 changes: 16 additions & 14 deletions picard/ui/options/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ class InterfaceOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_interface.html"

OPTIONS = (
('toolbar_show_labels', ['toolbar_show_labels']),
('show_menu_icons', ['show_menu_icons']),
('ui_language', ['ui_language']),
('ui_theme', ['ui_theme']),
('allow_multi_dirs_selection', ['allow_multi_dirs_selection']),
('builtin_search', ['builtin_search']),
('use_adv_search_syntax', ['use_adv_search_syntax']),
('show_new_user_dialog', ['new_user_dialog']),
('quit_confirmation', ['quit_confirmation']),
('file_save_warning', ['file_save_warning']),
('filebrowser_horizontal_autoscroll', ['filebrowser_horizontal_autoscroll']),
('starting_directory', ['starting_directory']),
('starting_directory_path', ['starting_directory_path']),
)

# Those are labels for theme display
_UI_THEME_LABELS = {
UiTheme.DEFAULT: {
Expand Down Expand Up @@ -126,20 +142,6 @@ def fcmp(x):

self.ui.allow_multi_dirs_selection.stateChanged.connect(self.multi_selection_warning)

self.register_setting('toolbar_show_labels', ['toolbar_show_labels'])
self.register_setting('show_menu_icons', ['show_menu_icons'])
self.register_setting('ui_language', ['ui_language', 'label'])
self.register_setting('ui_theme', ['ui_theme', 'label_theme'])
self.register_setting('allow_multi_dirs_selection', ['allow_multi_dirs_selection'])
self.register_setting('builtin_search', ['builtin_search'])
self.register_setting('use_adv_search_syntax', ['use_adv_search_syntax'])
self.register_setting('show_new_user_dialog', ['new_user_dialog'])
self.register_setting('quit_confirmation', ['quit_confirmation'])
self.register_setting('file_save_warning', ['file_save_warning'])
self.register_setting('filebrowser_horizontal_autoscroll', ['filebrowser_horizontal_autoscroll'])
self.register_setting('starting_directory', ['starting_directory'])
self.register_setting('starting_directory_path', ['starting_directory_path'])

def load(self):
# Don't display the multi-selection warning when loading values.
# This is required because loading a different option profile could trigger the warning.
Expand Down
8 changes: 5 additions & 3 deletions picard/ui/options/interface_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class InterfaceColorsOptionsPage(OptionsPage):
ACTIVE = True
HELP_URL = "/config/options_interface_colors.html"

OPTIONS = (
('interface_colors', ['colors']),
('interface_colors_dark', ['colors']),
)

def __init__(self, parent=None):
super().__init__(parent=parent)
self.ui = Ui_InterfaceColorsOptionsPage()
Expand All @@ -108,9 +113,6 @@ def __init__(self, parent=None):
self.colors_list = QtWidgets.QVBoxLayout()
self.ui.colors.setLayout(self.colors_list)

self.register_setting('interface_colors', ['colors'])
self.register_setting('interface_colors_dark', ['colors'])

def update_color_selectors(self):
if self.colors_list:
delete_items_of_layout(self.colors_list)
Expand Down
Loading

0 comments on commit 7d95755

Please sign in to comment.