Settings dialog: Add icons when settings have changed from default

This commit is contained in:
Rebecca Breu 2024-01-06 11:34:41 +01:00
parent fb3bc234c7
commit 3cefa4dbc3
6 changed files with 98 additions and 55 deletions

View file

@ -13,6 +13,8 @@ Added
Keyboard Shortcuts). The KeyboardSettings.ini file will now only
store values which are changed from the default, since it's no longer
needed as a reference.
* Settings dialog now displays icons to indicate changes from default
values
Fixed

View file

@ -87,6 +87,7 @@ class Action(dict):
return QtGui.QKeySequence()
def shortcuts_changed(self):
"""Whether shortcuts have changed from their defaults."""
return self.get_shortcuts() != self.get('shortcuts', [])
def get_default_shortcut(self, index):

View file

@ -159,6 +159,11 @@ class BeeSettings(QtCore.QSettings):
val = conf['default']
return val
def value_changed(self, key):
"""Whether the value for given key has changed from its default."""
return self.valueOrDefault(key) != self.FIELDS[key]['default']
def restore_defaults(self):
"""Restore all the values specified in FILEDS to their default values
by removing them from the settings file.

View file

@ -26,57 +26,73 @@ from beeref.config import BeeSettings, KeyboardSettings, settings_events
logger = logging.getLogger(__name__)
class RadioGroup(QtWidgets.QGroupBox):
CHANGED_SYMBOL = ''
class GroupBase(QtWidgets.QGroupBox):
def __init__(self):
super().__init__()
self.settings = BeeSettings()
self.update_title()
self.layout = QtWidgets.QVBoxLayout()
self.setLayout(self.layout)
settings_events.restore_defaults.connect(self.on_restore_defaults)
if self.HELPTEXT:
helptxt = QtWidgets.QLabel(self.HELPTEXT)
helptxt.setWordWrap(True)
self.layout.addWidget(helptxt)
def update_title(self):
title = [self.TITLE]
if self.settings.value_changed(self.KEY):
title.append(CHANGED_SYMBOL)
self.setTitle(' '.join(title))
def on_value_changed(self, value):
if self.ignore_value_changed:
return
if value != self.settings.valueOrDefault(self.KEY):
logger.debug(f'Setting {self.KEY} changed to: {value}')
self.settings.setValue(self.KEY, value)
self.update_title()
class RadioGroup(GroupBase):
TITLE = None
HELPTEXT = None
KEY = None
OPTIONS = None
def __init__(self):
super().__init__(self.TITLE)
self.settings = BeeSettings()
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
settings_events.restore_keyboard_defaults.connect(
self.on_restore_defaults)
super().__init__()
if self.HELPTEXT:
helptxt = QtWidgets.QLabel(self.HELPTEXT)
helptxt.setWordWrap(True)
layout.addWidget(helptxt)
self.ignore_values_changed = True
self.ignore_value_changed = True
self.buttons = {}
for (value, label, helptext) in self.OPTIONS:
btn = QtWidgets.QRadioButton(label)
self.buttons[value] = btn
btn.setToolTip(helptext)
btn.toggled.connect(
partial(self.on_values_changed, value=value, button=btn))
btn.toggled.connect(partial(self.on_value_changed, value=value))
if value == self.settings.valueOrDefault(self.KEY):
btn.setChecked(True)
layout.addWidget(btn)
self.layout.addWidget(btn)
self.ignore_values_changed = False
layout.addStretch(100)
def on_values_changed(self, value, button):
if self.ignore_values_changed:
return
if value != self.settings.valueOrDefault(self.KEY):
logger.debug(f'Setting {self.KEY} changed to: {value}')
self.settings.setValue(self.KEY, value)
self.ignore_value_changed = False
self.layout.addStretch(100)
def on_restore_defaults(self):
new_value = self.settings.valueOrDefault(self.KEY)
self.ignore_values_changed = True
self.ignore_value_changed = True
for value, btn in self.buttons.items():
btn.setChecked(value == new_value)
self.ignore_values_changed = False
self.ignore_value_changed = False
self.update_title()
class IntegerGroup(QtWidgets.QGroupBox):
class IntegerGroup(GroupBase):
TITLE = None
HELPTEXT = None
KEY = None
@ -84,38 +100,21 @@ class IntegerGroup(QtWidgets.QGroupBox):
MAX = None
def __init__(self):
super().__init__(self.TITLE)
self.settings = BeeSettings()
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
settings_events.restore_defaults.connect(self.on_restore_defaults)
if self.HELPTEXT:
helptxt = QtWidgets.QLabel(self.HELPTEXT)
helptxt.setWordWrap(True)
layout.addWidget(helptxt)
super().__init__()
self.input = QtWidgets.QSpinBox()
self.input.setValue(self.settings.valueOrDefault(self.KEY))
self.input.setRange(self.MIN, self.MAX)
self.input.valueChanged.connect(self.on_value_changed)
layout.addWidget(self.input)
layout.addStretch(100)
self.ignore_values_changed = False
def on_value_changed(self, value):
if self.ignore_values_changed:
return
if value != self.settings.valueOrDefault(self.KEY):
logger.debug(f'Setting {self.KEY} changed to: {value}')
self.settings.setValue(self.KEY, value)
self.layout.addWidget(self.input)
self.layout.addStretch(100)
self.ignore_value_changed = False
def on_restore_defaults(self):
new_value = self.settings.valueOrDefault(self.KEY)
self.ignore_values_changed = True
self.ignore_value_changed = True
self.input.setValue(new_value)
self.ignore_values_changed = False
self.ignore_value_changed = False
self.update_title()
class ImageStorageFormatWidget(RadioGroup):
@ -262,7 +261,7 @@ class KeyboardShortcutsModel(QtCore.QAbstractTableModel):
if index.column() == 0:
return txt.replace('&', '').removesuffix('...')
if index.column() == 1 and action.shortcuts_changed():
return ''
return CHANGED_SYMBOL
if index.column() > 1:
return action.get_qkeysequence(index.column() - 2)
@ -353,7 +352,8 @@ class KeyboardShortcutsView(QtWidgets.QTableView):
1, QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
self.setSelectionMode(
QtWidgets.QHeaderView.SelectionMode.SingleSelection)
settings_events.restore_defaults.connect(self.on_restore_defaults)
settings_events.restore_keyboard_defaults.connect(
self.on_restore_defaults)
def on_restore_defaults(self):
self.viewport().update()

View file

@ -59,6 +59,15 @@ def test_settings_value_or_default_gets_default_when_cast_error(settings):
assert settings.valueOrDefault('Items/arrange_gap') == 0
def test_settings_value_changed_when_default(settings):
assert settings.value_changed('Items/image_storage_format') is False
def test_settings_value_changed_when_chagned(settings):
settings.setValue('Items/image_storage_format', 'jpg')
assert settings.value_changed('Items/image_storage_format') is True
def test_settings_restore_defaults_restores(settings):
settings.setValue('Items/image_storage_format', 'png')
settings.restore_defaults()

View file

@ -15,6 +15,17 @@ from beeref.widgets.settings import (
)
def test_image_storage_format_sets_title_when_not_edited(settings, view):
widget = ImageStorageFormatWidget()
assert widget.title() == 'Image Storage Format:'
def test_image_storage_format_sets_title_when_edited(settings, view):
settings.setValue('Items/image_storage_format', 'jpg')
widget = ImageStorageFormatWidget()
assert widget.title() == 'Image Storage Format: ✎'
def test_image_storage_format_selects_radiobox(settings, view):
settings.setValue('Items/image_storage_format', 'jpg')
widget = ImageStorageFormatWidget()
@ -31,6 +42,7 @@ def test_image_storage_format_saves_change(settings, view):
assert widget.buttons['png'].isChecked() is False
assert widget.buttons['jpg'].isChecked() is True
assert settings.valueOrDefault('Items/image_storage_format') == 'jpg'
assert widget.title() == 'Image Storage Format: ✎'
def test_image_storage_format_on_restore_defaults(settings, view):
@ -41,6 +53,7 @@ def test_image_storage_format_on_restore_defaults(settings, view):
assert widget.buttons['best'].isChecked() is True
assert widget.buttons['png'].isChecked() is False
assert widget.buttons['jpg'].isChecked() is False
assert widget.title() == 'Image Storage Format:'
def test_arrange_gap_initialises_input_from_settings(settings, view):
@ -49,11 +62,23 @@ def test_arrange_gap_initialises_input_from_settings(settings, view):
assert widget.input.value() == 6
def test_arrange_gap_sets_title_when_not_edited(settings, view):
widget = ArrangeGapWidget()
assert widget.title() == 'Arrange Gap:'
def test_arrange_gap_sets_title_when_edited(settings, view):
settings.setValue('Items/arrange_gap', 6)
widget = ArrangeGapWidget()
assert widget.title() == 'Arrange Gap: ✎'
def test_arrange_gap_saves_change(settings, view):
settings.setValue('Items/arrange_gap', 6)
widget = ArrangeGapWidget()
widget.input.setValue(8)
assert settings.valueOrDefault('Items/arrange_gap') == 8
assert widget.title() == 'Arrange Gap: ✎'
def test_arrange_gap_on_restore_defaults(settings, view):
@ -62,6 +87,7 @@ def test_arrange_gap_on_restore_defaults(settings, view):
settings.setValue('Items/arrange_gap', 0)
widget.on_restore_defaults()
assert widget.input.value() == 0
assert widget.title() == 'Arrange Gap:'
@patch('PyQt6.QtWidgets.QMessageBox.question',