[virt-tools-list] [RFC PATCH v3 7/7] virtManager: config: Prevent global default write-through

Michael Weiser michael.weiser at gmx.de
Mon Dec 9 21:53:17 UTC 2019


Setting a widget's state using set_active() will trigger the "toggled"
signal if the new state is different from the previous. For boolean
per-vm settings which have a global default this can lead to the global
default being written as per-vm settings whenever the global default
changes.

Block the repective signals when updating state so it does not trigger
another roundtrip including writing of the per-vm setting. Allow for
disabling the blocking for cases where it's known that the handler is
not connected yet. Blocking would otherwise throw TypeError which is too
nonspecific to just ignore.

Signed-off-by: Michael Weiser <michael.weiser at gmx.de>
---
 virtManager/baseclass.py       |  8 ++++++++
 virtManager/details/console.py | 30 +++++++++++++++++++-----------
 virtManager/vmwindow.py        | 18 ++++++++++--------
 3 files changed, 37 insertions(+), 19 deletions(-)

diff --git a/virtManager/baseclass.py b/virtManager/baseclass.py
index 451e8a8a..1ab3f095 100644
--- a/virtManager/baseclass.py
+++ b/virtManager/baseclass.py
@@ -295,6 +295,14 @@ class vmmGObjectUI(vmmGObject):
     def widget(self, name):
         return self.builder.get_object(name)
 
+    def _set_active_blocked(self, name, val, cb, connected=True):
+        widget = self.widget(name)
+        if connected:
+            widget.handler_block_by_func(cb)
+        widget.set_active(val)
+        if connected:
+            widget.handler_unblock_by_func(cb)
+
     def cleanup(self):
         if self.__cleaned_up:
             return
diff --git a/virtManager/details/console.py b/virtManager/details/console.py
index 193e79eb..b3a3f00c 100644
--- a/virtManager/details/console.py
+++ b/virtManager/details/console.py
@@ -230,12 +230,12 @@ class vmmConsolePages(vmmGObjectUI):
             self._scroll_size_allocate)
 
         self._refresh_widget_states()
-        self._refresh_scaling_from_settings()
+        self._refresh_scaling_from_settings(False)
 
         self.add_gsettings_handle(
             self.vm.on_console_scaling_changed(
                 self._refresh_scaling_from_settings))
-        self._refresh_resizeguest_from_settings()
+        self._refresh_resizeguest_from_settings(False)
         self.add_gsettings_handle(
             self.vm.on_console_resizeguest_changed(
                 self._refresh_resizeguest_from_settings))
@@ -407,7 +407,7 @@ class vmmConsolePages(vmmGObjectUI):
         viewer_alloc.height = desktop_h
         self._viewer.console_size_allocate(viewer_alloc)
 
-    def _refresh_resizeguest_from_settings(self):
+    def _refresh_resizeguest_from_settings(self, handler_connected=True):
         tooltip = ""
         if self._viewer:
             if self._viewer.viewer_type != "spice":
@@ -422,7 +422,9 @@ class vmmConsolePages(vmmGObjectUI):
         widget.set_tooltip_text(tooltip)
         widget.set_sensitive(not bool(tooltip))
         if not tooltip:
-            self.widget("details-menu-view-resizeguest").set_active(bool(val))
+            self._set_active_blocked(
+                "details-menu-view-resizeguest", bool(val),
+                self.details_resizeguest_ui_changed_cb, handler_connected)
 
         self._sync_resizeguest_with_display()
 
@@ -463,14 +465,20 @@ class vmmConsolePages(vmmGObjectUI):
     # Scaling APIs #
     ################
 
-    def _refresh_scaling_from_settings(self):
+    def _refresh_scaling_from_settings(self, handlers_connected=True):
         scale_type = self.vm.get_console_scaling()
-        self.widget("details-menu-view-scale-always").set_active(
-            scale_type == self.config.CONSOLE_SCALE_ALWAYS)
-        self.widget("details-menu-view-scale-never").set_active(
-            scale_type == self.config.CONSOLE_SCALE_NEVER)
-        self.widget("details-menu-view-scale-fullscreen").set_active(
-            scale_type == self.config.CONSOLE_SCALE_FULLSCREEN)
+        self._set_active_blocked(
+            "details-menu-view-scale-always",
+            scale_type == self.config.CONSOLE_SCALE_ALWAYS,
+            self.details_scaling_ui_changed_cb, handlers_connected)
+        self._set_active_blocked(
+            "details-menu-view-scale-never",
+            scale_type == self.config.CONSOLE_SCALE_NEVER,
+            self.details_scaling_ui_changed_cb, handlers_connected)
+        self._set_active_blocked(
+            "details-menu-view-scale-fullscreen",
+            scale_type == self.config.CONSOLE_SCALE_FULLSCREEN,
+            self.details_scaling_ui_changed_cb, handlers_connected)
 
         self._sync_scaling_with_display()
 
diff --git a/virtManager/vmwindow.py b/virtManager/vmwindow.py
index b4cf20fc..8bfb1ee5 100644
--- a/virtManager/vmwindow.py
+++ b/virtManager/vmwindow.py
@@ -90,11 +90,6 @@ class vmmVMWindow(vmmGObjectUI):
         self._vmmenu = None
         self.init_menus()
 
-        self._refresh_sync_guest_time_on_resume_from_settings()
-        self.add_gsettings_handle(
-            self.vm.on_sync_guest_time_on_resume_changed(
-                self._refresh_sync_guest_time_on_resume_from_settings))
-
         self.builder.connect_signals({
             "on_close_details_clicked": self.close,
             "on_details_menu_close_activate": self.close,
@@ -154,6 +149,12 @@ class vmmVMWindow(vmmGObjectUI):
         self.vm.connect("inspection-changed",
                 lambda *x: self._details.refresh_os_page())
 
+        # has to be here so handler is connected and can be blocked
+        self._refresh_sync_guest_time_on_resume_from_settings()
+        self.add_gsettings_handle(
+            self.vm.on_sync_guest_time_on_resume_changed(
+                self._refresh_sync_guest_time_on_resume_from_settings))
+
         self.refresh_vm_state()
         self.activate_default_page()
 
@@ -512,9 +513,10 @@ class vmmVMWindow(vmmGObjectUI):
                                       buttons=Gtk.ButtonsType.CLOSE)
 
     def _refresh_sync_guest_time_on_resume_from_settings(self):
-        sync_time = self.widget("details-menu-sync-guest-time-on-resume")
-        does_sync_time = self.vm.get_sync_guest_time_on_resume()
-        sync_time.set_active(does_sync_time)
+        self._set_active_blocked(
+            "details-menu-sync-guest-time-on-resume",
+            self.vm.get_sync_guest_time_on_resume(),
+            self.details_sync_guest_time_on_resume_changed)
 
     def details_sync_guest_time_on_resume_changed(self, src):
         if not src.get_sensitive():
-- 
2.24.0





More information about the virt-tools-list mailing list