gfxdetails: Update UI a bit
Refactor the internals to cleanly separate the pieces that fill in the UI, and the pieces that react to UI state to dynamically show/hide fields. Improve spice GL warnings while he are here, and several other minor fixes Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
parent
525afd1aa6
commit
a10d746c41
|
@ -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")
|
||||
|
|
101
ui/gfxdetails.ui
101
ui/gfxdetails.ui
|
@ -53,6 +53,7 @@
|
|||
<object class="GtkEntry" id="graphics-password">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="visibility">False</property>
|
||||
<property name="invisible_char">●</property>
|
||||
<signal name="changed" handler="on_graphics_password_changed" swapped="no"/>
|
||||
|
@ -297,45 +298,34 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkGrid" id="graphics-opengl-box">
|
||||
<object class="GtkGrid" id="graphics-opengl-subopts-box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="row_spacing">3</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box77">
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">3</property>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="graphics-opengl">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_graphics_opengl_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="graphics-opengl-warn">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-dialog-warning</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<property name="valign">start</property>
|
||||
<property name="stock">gtk-dialog-warning</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="stock">gtk-dialog-warning</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
|
@ -360,14 +350,63 @@
|
|||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="width">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="graphics-warn-virtio">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">OpenGL only works with 'virtio' graphics with '3D acceleration' enabled</property>
|
||||
<property name="wrap">True</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.80000000000000004"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="graphics-warn-listen">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">OpenGL only works with 'Listen type' value 'none'</property>
|
||||
<property name="wrap">True</property>
|
||||
<attributes>
|
||||
<attribute name="scale" value="0.80000000000000004"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="graphics-opengl">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<signal name="toggled" handler="on_graphics_opengl_toggled" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
|
@ -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("<b>%s</b>" % title)
|
||||
|
||||
def _refresh_sound_page(self, sound):
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue