diff --git a/tests/uitests/test_details.py b/tests/uitests/test_details.py
index 0292ac69..71fcef91 100644
--- a/tests/uitests/test_details.py
+++ b/tests/uitests/test_details.py
@@ -472,6 +472,7 @@ class Details(uiutils.UITestCase):
tab.combo_select("Type:", "VNC")
tab.combo_select("Listen type:", "Address")
tab.find("graphics-port-auto", "check").click()
+ tab.find("graphics-port-auto", "check").click()
tab.find("graphics-port", "spin button").set_text("6001")
tab.find("Password:", "check").click()
passwd = tab.find_fuzzy("graphics-password", "text")
diff --git a/ui/gfxdetails.ui b/ui/gfxdetails.ui
index f8711025..b55c7202 100644
--- a/ui/gfxdetails.ui
+++ b/ui/gfxdetails.ui
@@ -53,6 +53,7 @@
+
+ 1
+ 6
+
+
+
+
+ True
+ True
+ False
+ True
+
1
5
+
+
+
diff --git a/virtManager/details/details.py b/virtManager/details/details.py
index 5557b08a..9ed6923d 100644
--- a/virtManager/details/details.py
+++ b/virtManager/details/details.py
@@ -2096,7 +2096,9 @@ class vmmDetails(vmmGObjectUI):
_("Hypervisor does not support removing this device"))
def _refresh_graphics_page(self, gfx):
- title = self.gfxdetails.set_dev(gfx)
+ pretty_type = vmmGraphicsDetails.graphics_pretty_type_simple(gfx.type)
+ title = (_("%(graphicstype)s Server") % {"graphicstype": pretty_type})
+ self.gfxdetails.set_dev(gfx)
self.widget("graphics-title").set_markup("%s" % title)
def _refresh_sound_page(self, sound):
diff --git a/virtManager/device/gfxdetails.py b/virtManager/device/gfxdetails.py
index 13ba7367..9f88eab9 100644
--- a/virtManager/device/gfxdetails.py
+++ b/virtManager/device/gfxdetails.py
@@ -33,8 +33,8 @@ class vmmGraphicsDetails(vmmGObjectUI):
self.builder.connect_signals({
"on_graphics_type_changed": self._change_graphics_type,
"on_graphics_port_auto_toggled": self._change_port_auto,
- "on_graphics_use_password": self._change_password_chk,
- "on_graphics_show_password": self._show_password_chk,
+ "on_graphics_use_password": self._change_password_cb,
+ "on_graphics_show_password": self._show_password_cb,
"on_graphics_listen_type_changed": self._change_graphics_listen,
"on_graphics_password_changed": lambda ignore: self.emit("changed-password"),
@@ -114,6 +114,69 @@ class vmmGraphicsDetails(vmmGObjectUI):
port = -1
return port
+ ##############
+ # UI syncing #
+ ##############
+
+ def _sync_ui(self):
+ gtype = uiutil.get_list_selection(self.widget("graphics-type"))
+ is_vnc = gtype == "vnc"
+ is_spice = gtype == "spice"
+
+ listen = uiutil.get_list_selection(self.widget("graphics-listen-type"))
+ has_listen_none = (listen in ["none", "socket"])
+
+ has_virtio_3d = bool([
+ v for v in self.vm.xmlobj.devices.video if
+ (v.model == "virtio" and v.accel3d)])
+
+ uiutil.set_grid_row_visible(
+ self.widget("graphics-warn-virtio"),
+ not has_virtio_3d)
+ uiutil.set_grid_row_visible(
+ self.widget("graphics-warn-listen"),
+ not has_listen_none)
+
+ passwd_enabled = self.widget("graphics-password-chk").get_active()
+ self.widget("graphics-password").set_sensitive(passwd_enabled)
+ if not passwd_enabled:
+ self.widget("graphics-password").set_text("")
+ passwd_visible = self.widget("graphics-visiblity-chk").get_active()
+ self.widget("graphics-password").set_visibility(passwd_visible)
+
+ glval = self.widget("graphics-opengl").get_active()
+ uiutil.set_grid_row_visible(
+ self.widget("graphics-opengl-subopts-box"),
+ glval and is_spice)
+
+ all_rows = [
+ "graphics-listen-type",
+ "graphics-address",
+ "graphics-password-box",
+ "graphics-port-box",
+ "graphics-opengl",
+ "graphics-opengl-subopts-box",
+ ]
+
+ is_auto = (self.widget("graphics-port-auto").get_active() or
+ self.widget("graphics-port-auto").get_inconsistent())
+ self.widget("graphics-port").set_visible(not is_auto)
+
+ rows = ["graphics-password-box", "graphics-listen-type"]
+ if listen == 'address':
+ rows.extend(["graphics-port-box", "graphics-address"])
+ if is_spice:
+ rows.append("graphics-opengl")
+ if glval:
+ rows.append("graphics-opengl-subopts-box")
+
+ if not is_vnc and not is_spice:
+ rows = []
+
+ for row in all_rows:
+ uiutil.set_grid_row_visible(self.widget(row), row in rows)
+
+
##############
# Public API #
@@ -128,13 +191,12 @@ class vmmGraphicsDetails(vmmGObjectUI):
rendermodel = self.widget("graphics-rendernode").get_model()
self.widget("graphics-rendernode").set_active_iter(rendermodel[-1].iter)
- self._change_ports()
self.widget("graphics-port-auto").set_active(True)
self.widget("graphics-password").set_text("")
self.widget("graphics-password").set_sensitive(False)
self.widget("graphics-password-chk").set_active(False)
self.widget("graphics-opengl").set_active(False)
- self._sync_opengl_ui()
+ self._sync_ui()
def get_values(self):
gtype = uiutil.get_list_selection(self.widget("graphics-type"))
@@ -146,156 +208,88 @@ class vmmGraphicsDetails(vmmGObjectUI):
if not self.widget("graphics-password-chk").get_active():
passwd = None
- gl = self.widget("graphics-opengl").get_active()
+ glval = self.widget("graphics-opengl").get_active()
+ if not self.widget("graphics-opengl").is_visible():
+ glval = None
+
rendernode = uiutil.get_list_selection(self.widget("graphics-rendernode"))
- if not self.widget("graphics-rendernode").get_visible():
+ if not self.widget("graphics-rendernode").is_visible():
rendernode = None
- return gtype, port, listen, addr, passwd, gl, rendernode
+ return gtype, port, listen, addr, passwd, glval, rendernode
def set_dev(self, gfx):
self.reset_state()
- def set_port(basename, val):
- auto = self.widget(basename + "-auto")
- widget = self.widget(basename)
- auto.set_inconsistent(False)
- label = _("A_uto")
+ portval = gfx.port
+ portautolabel = _("A_uto")
- if val == -1 or gfx.autoport:
- auto.set_active(True)
- if val and val != -1: # pragma: no cover
- # Triggering this with the test driver is tough
- # because it doesn't fill in runtime port values
- label = _("A_uto (Port %(port)d)") % {"port": val}
- elif val is None:
- auto.set_inconsistent(True)
- else:
- auto.set_active(False)
- widget.set_value(val)
+ if portval == -1 or gfx.autoport:
+ portauto = True
+ if portval and portval != -1: # pragma: no cover
+ # Triggering this with the test driver is tough
+ # because it doesn't fill in runtime port values
+ portautolabel = _("A_uto (Port %(port)d)") % {"port": portval}
+ elif portval is None:
+ portauto = None
+ else:
+ portauto = False
- auto.set_label(label)
+ self.widget("graphics-port").set_value(portval or 0)
+ self.widget("graphics-port-auto").set_label(portautolabel)
+ self.widget("graphics-port-auto").set_active(bool(portauto))
+ self.widget("graphics-port-auto").set_inconsistent(portauto is None)
gtype = gfx.type
- is_vnc = (gtype == "vnc")
- is_spice = (gtype == "spice")
- pretty_type = vmmGraphicsDetails.graphics_pretty_type_simple(gtype)
- title = (_("%(graphicstype)s Server") % {"graphicstype": pretty_type})
-
- if is_vnc or is_spice:
- use_passwd = gfx.passwd is not None
-
- set_port("graphics-port", gfx.port)
- listentype = gfx.get_first_listen_type()
- if listentype and listentype == 'none':
- uiutil.set_list_selection(self.widget("graphics-listen-type"), 'none')
- else:
- uiutil.set_list_selection(self.widget("graphics-listen-type"), 'address')
- uiutil.set_list_selection(
- self.widget("graphics-address"), gfx.listen)
-
- self.widget("graphics-password").set_text(gfx.passwd or "")
- self.widget("graphics-password-chk").set_active(use_passwd)
- self.widget("graphics-password").set_sensitive(use_passwd)
-
- if is_spice:
- opengl_warning = ""
- glval = bool(gfx.gl)
- renderval = gfx.rendernode or None
-
- # If the config doesn't support spice GL, show a warning
- # but still let the user set the value in case we are wrong
- if not [v for v in self.vm.xmlobj.devices.video if
- (v.model == "virtio" and v.accel3d)]:
- opengl_warning = _("Spice GL requires "
- "VirtIO graphics configured with accel3d.")
- elif gfx.get_first_listen_type() not in ["none", "socket"]:
- opengl_warning = _("Graphics listen type does not support "
- "spice GL.")
-
- self.widget("graphics-opengl").set_active(glval)
- if glval:
- # Only sync rendernode UI with XML, if gl=on, otherwise
- # we want to preserve the suggested rendernode already
- # selected in the UI
- uiutil.set_list_selection(
- self.widget("graphics-rendernode"), renderval)
-
- self.widget("graphics-opengl-warn").set_tooltip_text(
- opengl_warning or None)
- self.widget("graphics-opengl-warn").set_visible(
- bool(opengl_warning))
-
uiutil.set_list_selection(self.widget("graphics-type"), gtype)
- return title
+
+ use_passwd = gfx.passwd is not None
+ self.widget("graphics-password").set_text(gfx.passwd or "")
+ self.widget("graphics-password-chk").set_active(use_passwd)
+
+ listentype = gfx.get_first_listen_type()
+ uiutil.set_list_selection(
+ self.widget("graphics-listen-type"), listentype)
+ uiutil.set_list_selection(
+ self.widget("graphics-address"), gfx.listen)
+
+ glval = bool(gfx.gl)
+ renderval = gfx.rendernode or None
+ self.widget("graphics-opengl").set_active(glval)
+
+ if glval:
+ # Only sync rendernode UI with XML, if gl=on, otherwise
+ # we want to preserve the suggested rendernode already
+ # selected in the UI
+ uiutil.set_list_selection(
+ self.widget("graphics-rendernode"), renderval)
#############
# Listeners #
#############
- def _show_rows_from_type(self):
- hide_all = ["graphics-address",
- "graphics-password-box", "graphics-port-box",
- "graphics-opengl-box"]
-
- gtype = uiutil.get_list_selection(self.widget("graphics-type"))
- listen = uiutil.get_list_selection(self.widget("graphics-listen-type"))
-
- vnc_rows = ["graphics-password-box"]
- if listen == 'address':
- vnc_rows.extend(["graphics-port-box", "graphics-address"])
- spice_rows = vnc_rows[:]
- spice_rows.extend(["graphics-opengl-box"])
-
- rows = []
- if gtype == "vnc":
- rows = vnc_rows
- elif gtype == "spice":
- rows = spice_rows
-
- for row in hide_all:
- uiutil.set_grid_row_visible(self.widget(row), row in rows)
-
def _change_graphics_type(self, ignore):
- self._show_rows_from_type()
+ self._sync_ui()
self.emit("changed-type")
def _change_graphics_listen(self, ignore):
- self._show_rows_from_type()
+ self._sync_ui()
self.emit("changed-listen")
- def _sync_opengl_ui(self):
- uiutil.set_grid_row_visible(
- self.widget("graphics-rendernode"),
- self.widget("graphics-opengl").get_active())
-
def _change_opengl(self, ignore):
- self._sync_opengl_ui()
+ self._sync_ui()
self.emit("changed-opengl")
self.emit("changed-rendernode")
def _change_port_auto(self, ignore):
self.widget("graphics-port-auto").set_inconsistent(False)
- self._change_ports()
+ self._sync_ui()
self.emit("changed-port")
- def _change_ports(self):
- is_auto = (self.widget("graphics-port-auto").get_active() or
- self.widget("graphics-port-auto").get_inconsistent())
-
- self.widget("graphics-port").set_visible(not is_auto)
-
- def _change_password_chk(self, ignore=None):
- if self.widget("graphics-password-chk").get_active():
- self.widget("graphics-password").set_sensitive(True)
- else:
- self.widget("graphics-password").set_text("")
- self.widget("graphics-password").set_sensitive(False)
+ def _change_password_cb(self, src):
+ self._sync_ui()
self.emit("changed-password")
- def _show_password_chk(self, ignore=None):
- if self.widget("graphics-visiblity-chk").get_active():
- self.widget("graphics-password").set_visibility(True)
- else:
- self.widget("graphics-password").set_visibility(False)
+ def _show_password_cb(self, src):
+ self._sync_ui()