summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Hrdina <phrdina@redhat.com>2019-06-15 11:58:43 +0200
committerPavel Hrdina <phrdina@redhat.com>2019-06-15 15:05:28 +0200
commitd6b6397ce0b77acea7f828cd7edb3a8929a8abd4 (patch)
tree9921b1515ff74d62edc467be2c19240cd588bd2f
parent5eb5913f345ae267d26d30d0b45443eae006d5f5 (diff)
downloadvirt-manager-d6b6397ce0b77acea7f828cd7edb3a8929a8abd4.tar.gz
virtManager: xmleditor: warn when switching to XML tab
If there are unapplied changes in the UI warn user when they tries to switch to XML editor. Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
-rw-r--r--tests/uitests/details.py17
-rw-r--r--virtManager/details.py3
-rw-r--r--virtManager/hostnets.py2
-rw-r--r--virtManager/storagelist.py2
-rw-r--r--virtManager/xmleditor.py68
5 files changed, 68 insertions, 24 deletions
diff --git a/tests/uitests/details.py b/tests/uitests/details.py
index 63bc2345..cdf4f36a 100644
--- a/tests/uitests/details.py
+++ b/tests/uitests/details.py
@@ -483,6 +483,23 @@ class Details(uiutils.UITestCase):
self._stop_vm(win)
self.assertTrue(not share.checked)
+ # Unapplied changes should warn when switching to XML tab
+ tab = self._select_hw(win, "Overview", "overview-tab")
+ tab.find("Description:", "text").text = "hey new description"
+ win.find("XML", "page tab").click()
+ alert = self.app.root.find("vmm dialog")
+ alert.find_fuzzy("changes will be lost")
+
+ # Select 'No', meaning don't abandon changes
+ alert.find("No", "push button").click()
+ uiutils.check_in_loop(lambda: tab.showing)
+
+ # Try unapplied changes again, this time abandon our changes
+ win.find("XML", "page tab").click()
+ alert = self.app.root.find("vmm dialog")
+ alert.find("Yes", "push button").click()
+ uiutils.check_in_loop(lambda: not tab.showing)
+
def testDetailsXMLEdit(self):
"""
Test XML editing interaction
diff --git a/virtManager/details.py b/virtManager/details.py
index 34547f92..64f3f79f 100644
--- a/virtManager/details.py
+++ b/virtManager/details.py
@@ -1194,6 +1194,7 @@ class vmmDetails(vmmGObjectUI):
self.active_edits = []
self.widget("config-apply").set_sensitive(False)
self.widget("config-cancel").set_sensitive(False)
+ self._xmleditor.details_changed = False
def enable_apply(self, *arglist):
edittype = arglist[-1]
@@ -1201,6 +1202,8 @@ class vmmDetails(vmmGObjectUI):
self.widget("config-cancel").set_sensitive(True)
if edittype not in self.active_edits:
self.active_edits.append(edittype)
+ if edittype != EDIT_XML:
+ self._xmleditor.details_changed = True
# Idmap
def config_idmap_enable(self, src):
diff --git a/virtManager/hostnets.py b/virtManager/hostnets.py
index ca6d2f08..ee066dcd 100644
--- a/virtManager/hostnets.py
+++ b/virtManager/hostnets.py
@@ -474,10 +474,12 @@ class vmmHostNets(vmmGObjectUI):
def _disable_net_apply(self):
self._active_edits = set()
self.widget("net-apply").set_sensitive(False)
+ self._xmleditor.details_changed = False
def _enable_net_apply(self, edittype):
self.widget("net-apply").set_sensitive(True)
self._active_edits.add(edittype)
+ self._xmleditor.details_changed = True
def _confirm_changes(self):
if (self.is_visible() and
diff --git a/virtManager/storagelist.py b/virtManager/storagelist.py
index 8531ce19..414de035 100644
--- a/virtManager/storagelist.py
+++ b/virtManager/storagelist.py
@@ -601,10 +601,12 @@ class vmmStorageList(vmmGObjectUI):
def _enable_pool_apply(self, edittype):
self._active_edits.add(edittype)
self.widget("pool-apply").set_sensitive(True)
+ self._xmleditor.details_changed = True
def _disable_pool_apply(self):
self._active_edits = set()
self.widget("pool-apply").set_sensitive(False)
+ self._xmleditor.details_changed = False
def _confirm_changes(self):
if (self.is_visible() and
diff --git a/virtManager/xmleditor.py b/virtManager/xmleditor.py
index e5ecb39e..21786bf9 100644
--- a/virtManager/xmleditor.py
+++ b/virtManager/xmleditor.py
@@ -34,6 +34,8 @@ class vmmXMLEditor(vmmGObjectUI):
self._srcbuf = None
self._init_ui()
+ self.details_changed = False
+
self.add_gsettings_handle(
self.config.on_xmleditor_enabled_changed(
self._xmleditor_enabled_changed_cb))
@@ -81,10 +83,10 @@ class vmmXMLEditor(vmmGObjectUI):
# Internal helpers #
####################
- def _reselect_xml_page(self):
+ def _reselect_page(self, pagenum):
# Setting _curpage first will shortcircuit our page changed callback
- self._curpage = _PAGE_XML
- self.widget("xml-notebook").set_current_page(_PAGE_XML)
+ self._curpage = pagenum
+ self.widget("xml-notebook").set_current_page(pagenum)
def _reset_xml(self):
self.set_xml("")
@@ -98,6 +100,32 @@ class vmmXMLEditor(vmmGObjectUI):
startiter.forward_line()
self._srcbuff.place_cursor(startiter)
+ def _detials_unapplied_changes(self):
+ if not self.details_changed:
+ return False
+
+ ret = self.err.yes_no(
+ _("There are unapplied changes."),
+ _("Your changes will be lost if you leave this tab. "
+ "Really leave this tab?"))
+ if ret:
+ self.details_changed = False
+
+ return not ret
+
+ def _xml_unapplied_changes(self):
+ if self._srcxml == self.get_xml():
+ return False
+
+ ret = self.err.yes_no(
+ _("There are unapplied changes."),
+ _("Your XML changes will be lost if you leave this tab. "
+ "Really leave this tab?"))
+
+ return not ret
+
+
+
##############
# Public API #
@@ -159,34 +187,26 @@ class vmmXMLEditor(vmmGObjectUI):
def _before_page_changed_cb(self, notebook, widget, pagenum):
if self._curpage == pagenum:
return
+ prevpage = self._curpage
self._curpage = pagenum
- # If the XML page is clicked, emit xml-requested signal which
- # expects the user to call set_xml/set_libvirtobject. This saves
- # having to fetch inactive XML up front, and gives users like
- # a hook to actually serialize the final XML to return
if pagenum == _PAGE_XML:
- self.emit("xml-requested")
- return
-
- # If the details page is selected from the XML page, and the user
- # edited the XML, we need to warn that leaving this screen will
- # invalidate the changes.
- if self._srcxml == self.get_xml():
- return
-
- ret = self.err.yes_no(
- _("There are unapplied changes."),
- _("Your XML changes will be lost if you leave this tab. "
- "Really leave this tab?"))
- if ret:
- self._reset_xml()
- return
+ if not self._detials_unapplied_changes():
+ # If the XML page is clicked, emit xml-requested signal which
+ # expects the user to call set_xml/set_libvirtobject. This saves
+ # having to fetch inactive XML up front, and gives users like
+ # a hook to actually serialize the final XML to return
+ self.emit("xml-requested")
+ return
+ else:
+ if not self._xml_unapplied_changes():
+ self._reset_xml()
+ return
# I can't find anyway to make the notebook stay on the current page
# So set an idle callback to switch back to the XML page. It causes
# a visual UI blip unfortunately
- self.idle_add(self._reselect_xml_page)
+ self.idle_add(self._reselect_page, prevpage)
def _after_page_changed_cb(self, notebook, gparam):
self._curpage = notebook.get_current_page()