preferences: Disable XML editing by default

This adds a field in gsettings and preferences UI to enable
XML editing. It's off by default. The XML tab page is still visible,
but the textview is not editable, and there's a warning at the top:

  XML editing is disabled in 'Preferences'.
  Only enable it if you know what you are doing.

When the setting is enabled, the warning goes away and the textview
is editable. This puts a roadblock up for people that don't know what
they are doing, but still advertises the feature and keeps the
UI surface difference fairly small between on/off states.
This commit is contained in:
Cole Robinson 2019-06-05 17:40:54 -04:00
parent 2a1cf411dd
commit 2266b650a5
16 changed files with 161 additions and 12 deletions

View File

@ -53,6 +53,12 @@
<description>Show system tray icon while app is running</description>
</key>
<key name="xmleditor-enabled" type="b">
<default>false</default>
<summary>Enable XML editting UI</summary>
<description>Enable XML editting UI</description>
</key>
<key name="enable-libguestfs-vm-inspection" type="b">
<default>true</default>
<summary>Enable libguestfs VM inspection</summary>

View File

@ -660,6 +660,7 @@ class AddHardware(uiutils.UITestCase):
"""
Test XML editor integration
"""
self.app.open(xmleditor_enabled=True)
details = self._open_details_window()
win = self._open_addhw_window(details)
finish = win.find("Finish", "push button")

View File

@ -59,6 +59,7 @@ class CreateNet(uiutils.UITestCase):
def testCreateNetXMLEditor(self):
self.app.open(xmleditor_enabled=True)
hostwin = self._open_host_window("Virtual Networks")
win = self._open_create_win(hostwin)
name = win.find("Name:", "text")

View File

@ -89,6 +89,7 @@ class CreatePool(uiutils.UITestCase):
def testCreatePoolXMLEditor(self):
self.app.open(xmleditor_enabled=True)
hostwin = self._open_host_window("Storage")
win = self._open_create_win(hostwin)
finish = win.find("Finish", "push button")

View File

@ -66,6 +66,7 @@ class CreateVol(uiutils.UITestCase):
def testCreateVolXMLEditor(self):
self.app.open(xmleditor_enabled=True)
hostwin = self._open_host_window("Storage")
poolcell = hostwin.find("default-pool", "table cell")
poolcell.click()

View File

@ -487,6 +487,7 @@ class Details(uiutils.UITestCase):
"""
Test XML editing interaction
"""
self.app.open(xmleditor_enabled=True)
win = self._open_details_window(vmname="test-clone-simple")
finish = win.find("config-apply")
xmleditor = win.find("XML editor")

View File

@ -30,6 +30,7 @@ class Host(uiutils.UITestCase):
"""
Test edits to net config
"""
self.app.open(xmleditor_enabled=True)
win = self._open_host_window("Virtual Networks").find("network-grid")
finish = win.find("Apply", "push button")
@ -69,6 +70,7 @@ class Host(uiutils.UITestCase):
"""
Test edits to pool config
"""
self.app.open(xmleditor_enabled=True)
win = self._open_host_window("Storage").find("storage-grid")
finish = win.find("Apply", "push button")

View File

@ -432,6 +432,7 @@ class NewVM(uiutils.UITestCase):
"""
Test new VM with raw XML editing via customize wizard
"""
self.app.open(xmleditor_enabled=True)
newvm = self._open_create_wizard()
# Create a custom named VM, using CDROM media, and default storage

View File

@ -55,3 +55,34 @@ class VMMPrefs(uiutils.UITestCase):
win.find_fuzzy("Close", "push button").click()
uiutils.check_in_loop(lambda: win.visible is False)
def testPrefsXMLEditor(self):
managerwin = self.app.topwin
detailswin = self._open_details_window(vmname="test-clone-simple")
finish = detailswin.find("config-apply")
xmleditor = detailswin.find("XML editor")
detailswin.find("XML", "page tab").click()
warnlabel = detailswin.find_fuzzy("XML editing is disabled")
self.assertTrue(warnlabel.visible)
origtext = xmleditor.text
xmleditor.typeText("1234abcd")
self.assertEqual(xmleditor.text, origtext)
managerwin.click()
managerwin.find("Edit", "menu").click()
managerwin.find("Preferences", "menu item").click()
prefswin = self.app.root.find_fuzzy("Preferences", "frame")
prefswin.find_fuzzy("Enable XML").click()
prefswin.find_fuzzy("Close", "push button").click()
uiutils.check_in_loop(lambda: prefswin.visible is False)
managerwin.keyCombo("<alt>F4")
detailswin.click()
xmleditor.text = xmleditor.text.replace(">",
"><title>FOOTITLE</title>", 1)
finish.click()
detailswin.find("Details", "page tab").click()
uiutils.check_in_loop(lambda:
detailswin.find("Title:", "text").text == "FOOTITLE")

View File

@ -444,7 +444,7 @@ class VMMDogtailApp(object):
return bool(self._proc and self._proc.poll() is None)
def open(self, extra_opts=None, check_already_running=True, use_uri=True,
window_name=None):
window_name=None, xmleditor_enabled=False):
extra_opts = extra_opts or []
if tests.utils.clistate.debug:
@ -460,9 +460,12 @@ class VMMDogtailApp(object):
cmd += ["-m", "coverage", "run", "--append",
"--omit", "/usr/*"]
cmd += [os.path.join(os.getcwd(), "virt-manager"),
"--test-first-run", "--no-fork"]
"--test-first-run",
"--no-fork"]
if use_uri:
cmd += ["--connect", self.uri]
if xmleditor_enabled:
cmd += ["--test-options=xmleditor-enabled"]
cmd += extra_opts
if check_already_running:

View File

@ -119,6 +119,21 @@
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="prefs-xmleditor">
<property name="label" translatable="yes">Enable _XML editing</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_prefs_xmleditor_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>

View File

@ -36,11 +36,18 @@
</packing>
</child>
<child>
<object class="GtkBox" id="xml-box">
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_top">6</property>
<property name="row_spacing">6</property>
<child>
<object class="GtkBox" id="xml-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
@ -59,6 +66,49 @@
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="xml-warning-box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkImage">
<property name="visible">True</property>
<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">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;small&gt;XML editing is disabled in 'Preferences'. Only enable it if you know what you are doing.&lt;/small&gt;</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>

View File

@ -192,6 +192,7 @@ class CLITestOptionsClass:
self.leak_debug = _get("leak-debug")
self.old_poll = _get("old-poll")
self.no_events = _get("no-events")
self.xmleditor_enabled = _get("xmleditor-enabled")
if opts:
print("Unknown --test-options keys: %s" % opts)

View File

@ -169,6 +169,8 @@ class vmmConfig(object):
self.conf = _SettingsWrapper("org.virt-manager.virt-manager")
self.CLITestOptions = CLITestOptions
if self.CLITestOptions.xmleditor_enabled:
self.set_xmleditor_enabled(True)
# We don't create it straight away, since we don't want
# to block the app pending user authorization to access
@ -364,6 +366,16 @@ class vmmConfig(object):
def set_view_system_tray(self, val):
self.conf.set("/system-tray", val)
# XML editor enabled
def on_xmleditor_enabled_changed(self, cb):
return self.conf.notify_add("/xmleditor-enabled", cb)
def get_xmleditor_enabled(self):
return self.conf.get("/xmleditor-enabled")
def set_xmleditor_enabled(self, val):
self.conf.set("/xmleditor-enabled", val)
# Libguestfs VM inspection
def on_libguestfs_inspect_vms_changed(self, cb):
return self.conf.notify_add("/enable-libguestfs-vm-inspection", cb)

View File

@ -36,6 +36,7 @@ class vmmPreferences(vmmGObjectUI):
self._orig_libguestfs_val = None
self.refresh_view_system_tray()
self.refresh_xmleditor()
self.refresh_libguestfs()
self.refresh_update_interval()
self.refresh_console_accels()
@ -65,6 +66,7 @@ class vmmPreferences(vmmGObjectUI):
"on_prefs_close_clicked": self.close,
"on_prefs_system_tray_toggled": self.change_view_system_tray,
"on_prefs_xmleditor_toggled": self.change_xmleditor,
"on_prefs_libguestfs_toggled": self.change_libguestfs,
"on_prefs_stats_update_interval_changed": self.change_update_interval,
"on_prefs_console_accels_toggled": self.change_console_accels,
@ -203,6 +205,10 @@ class vmmPreferences(vmmGObjectUI):
val = self.config.get_view_system_tray()
self.widget("prefs-system-tray").set_active(bool(val))
def refresh_xmleditor(self):
val = self.config.get_xmleditor_enabled()
self.widget("prefs-xmleditor").set_active(bool(val))
def refresh_libguestfs(self):
val = self.config.get_libguestfs_inspect_vms()
if self._orig_libguestfs_val is None:
@ -364,6 +370,8 @@ class vmmPreferences(vmmGObjectUI):
def change_view_system_tray(self, src):
self.config.set_view_system_tray(src.get_active())
def change_xmleditor(self, src):
self.config.set_xmleditor_enabled(src.get_active())
def change_libguestfs(self, src):
val = src.get_active()
self.config.set_libguestfs_inspect_vms(val)

View File

@ -6,6 +6,7 @@ import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
from . import uiutil
from .baseclass import vmmGObjectUI
_PAGE_DETAILS = 0
@ -33,6 +34,10 @@ class vmmXMLEditor(vmmGObjectUI):
self._srcbuf = None
self._init_ui()
self.add_gsettings_handle(
self.config.on_xmleditor_enabled_changed(
self._xmleditor_enabled_changed_cb))
def _cleanup(self):
pass
@ -42,6 +47,12 @@ class vmmXMLEditor(vmmGObjectUI):
# UI init #
###########
def _set_xmleditor_enabled_from_config(self):
enabled = self.config.get_xmleditor_enabled()
self._srcview.set_editable(enabled)
uiutil.set_grid_row_visible(self.widget("xml-warning-box"),
not enabled)
def _init_ui(self):
self._srcview = GtkSource.View()
self._srcbuff = self._srcview.get_buffer()
@ -63,6 +74,7 @@ class vmmXMLEditor(vmmGObjectUI):
self._srcview.show_all()
self.widget("xml-scroll").add(self._srcview)
self._set_xmleditor_enabled_from_config()
####################
@ -178,3 +190,6 @@ class vmmXMLEditor(vmmGObjectUI):
def _after_page_changed_cb(self, notebook, gparam):
self._curpage = notebook.get_current_page()
def _xmleditor_enabled_changed_cb(self):
self._set_xmleditor_enabled_from_config()