Commit 21a29289 authored by Roman Alifanov's avatar Roman Alifanov

settings: add reload_page_after_set/get options

Requested-by: @fiersik
parent 362ed68a
...@@ -11,6 +11,10 @@ class ClassicSection(BaseSection): ...@@ -11,6 +11,10 @@ class ClassicSection(BaseSection):
self.settings = [Setting(s, module) for s in section_data.get('settings', [])] self.settings = [Setting(s, module) for s in section_data.get('settings', [])]
self.settings = sorted(self.settings, key=lambda s: s.weight, reverse=True) self.settings = sorted(self.settings, key=lambda s: s.weight, reverse=True)
# Link settings to their section for page tracking
for setting in self.settings:
setting.section = self
self.module.add_section(self) self.module.add_section(self)
def create_preferences_group(self): def create_preferences_group(self):
......
import logging import logging
from gi.repository import GLib from gi.repository import GLib, Gtk, Adw
from ..executor import get_executor from ..executor import get_executor
from ..searcher import SearcherFactory from ..searcher import SearcherFactory
...@@ -10,6 +10,10 @@ class BaseSetting: ...@@ -10,6 +10,10 @@ class BaseSetting:
def __init__(self, setting_data, module): def __init__(self, setting_data, module):
self._ = module.get_translation self._ = module.get_translation
self.module = module self.module = module
# section will be set by Section after creation (for Setting)
# or before super().__init__ (for CustomSetting)
if not hasattr(self, 'section'):
self.section = None
self.name = self._(setting_data["name"]) self.name = self._(setting_data["name"])
self.orig_name = setting_data["name"] self.orig_name = setting_data["name"]
...@@ -57,6 +61,10 @@ class BaseSetting: ...@@ -57,6 +61,10 @@ class BaseSetting:
if self.update_interval: if self.update_interval:
self._start_update_timer() self._start_update_timer()
# Page reload flags
self.reload_page_after_set = setting_data.get("reload_page_after_set", False)
self.reload_page_after_get = setting_data.get("reload_page_after_get", False)
def bind_widget(self, widget): def bind_widget(self, widget):
self.widget = widget self.widget = widget
self._sync_busy() self._sync_busy()
...@@ -217,7 +225,7 @@ class BaseSetting: ...@@ -217,7 +225,7 @@ class BaseSetting:
if self._current_value is None or force: if self._current_value is None or force:
self._fetch_value_async(force=force) self._fetch_value_async(force=force)
def _fetch_value_async(self, force=False): def _fetch_value_async(self, force=False, skip_reload=False):
if self._value_loading: if self._value_loading:
return return
...@@ -232,6 +240,8 @@ class BaseSetting: ...@@ -232,6 +240,8 @@ class BaseSetting:
return return
self._current_value = value self._current_value = value
self._update_widget() self._update_widget()
if self.reload_page_after_get and not skip_reload:
self._reload_page()
def _on_error(exc): def _on_error(exc):
if self._destroyed: if self._destroyed:
...@@ -251,6 +261,91 @@ class BaseSetting: ...@@ -251,6 +261,91 @@ class BaseSetting:
self._fetch_value_async(force=force) self._fetch_value_async(force=force)
return self._current_value if self._current_value is not None else self.default return self._current_value if self._current_value is not None else self.default
def _reload_page(self):
"""
Reload all settings on the current page with scroll position preserved.
"""
if not self.widget or not self.section:
return
# Get the page name for this setting
page_name = self.section.page
# Find the PreferencesPage and its ScrolledWindow
row = self.widget.row if hasattr(self.widget, 'row') else None
if not row:
return
# Find the Adw.PreferencesPage ancestor
pref_page = row.get_ancestor(Adw.PreferencesPage)
if not pref_page:
return
# Find ScrolledWindow inside PreferencesPage to save scroll position
scroll_pos = self._get_scroll_position(pref_page)
# Refresh all settings on the same page
self._refresh_page_settings(page_name)
# Restore scroll position after a short delay to allow UI update
if scroll_pos is not None:
GLib.timeout_add(50, lambda: self._restore_scroll_position(pref_page, scroll_pos))
def _get_scroll_position(self, pref_page):
"""
Get the vertical scroll position from PreferencesPage's internal ScrolledWindow.
"""
# Adw.PreferencesPage contains a ScrolledWindow internally
# We need to traverse to find it
scrolled = self._find_scrolled_window(pref_page)
if scrolled:
vadj = scrolled.get_vadjustment()
if vadj:
return vadj.get_value()
return None
def _restore_scroll_position(self, pref_page, position):
"""
Restore the vertical scroll position.
"""
scrolled = self._find_scrolled_window(pref_page)
if scrolled:
vadj = scrolled.get_vadjustment()
if vadj:
vadj.set_value(position)
return False # Don't repeat the timeout
def _find_scrolled_window(self, widget):
"""
Recursively find a ScrolledWindow child widget.
"""
if isinstance(widget, Gtk.ScrolledWindow):
return widget
# Check children
child = widget.get_first_child() if hasattr(widget, 'get_first_child') else None
while child:
result = self._find_scrolled_window(child)
if result:
return result
child = child.get_next_sibling() if hasattr(child, 'get_next_sibling') else None
return None
def _refresh_page_settings(self, page_name):
"""
Refresh all settings that belong to the same page.
"""
for section in self.module.sections:
# Check if this section belongs to the same page
if section.page == page_name or (section.page is None and page_name == 'Default'):
for setting in section.settings:
# Skip self to avoid infinite loop
if setting is self:
continue
# Refresh the setting value (skip_reload=True to prevent cascade)
setting._fetch_value_async(force=True, skip_reload=True)
def _set_backend_value(self, value): def _set_backend_value(self, value):
previous_value = self._current_value previous_value = self._current_value
self._current_value = value self._current_value = value
...@@ -260,6 +355,12 @@ class BaseSetting: ...@@ -260,6 +355,12 @@ class BaseSetting:
def _save(): def _save():
return self._set_backend_value_sync(value) return self._set_backend_value_sync(value)
def _on_success(result):
if self._destroyed:
return
if self.reload_page_after_set:
self._reload_page()
def _on_error(exc): def _on_error(exc):
if self._destroyed: if self._destroyed:
return return
...@@ -272,7 +373,7 @@ class BaseSetting: ...@@ -272,7 +373,7 @@ class BaseSetting:
return return
self._set_busy(False) self._set_busy(False)
self._submit_task(_save, on_error=_on_error, on_done=_on_done) self._submit_task(_save, on_success=_on_success, on_error=_on_error, on_done=_on_done)
def _get_backend_range(self): def _get_backend_range(self):
if not self._map_ready: if not self._map_ready:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment