From 268b4621264bd42760869d714ae8b9a770b607de Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sun, 22 Sep 2013 13:24:59 -0400 Subject: [PATCH] uihelpers: Add VMShutdownMenu class And use it in all the places where we are duplicating a similar menu --- ui/vmm-details.ui | 1 + virtManager/details.py | 12 ++---- virtManager/engine.py | 1 + virtManager/manager.py | 79 ++++++++------------------------------ virtManager/systray.py | 55 ++++---------------------- virtManager/uihelpers.py | 83 ++++++++++++++++++++-------------------- 6 files changed, 70 insertions(+), 161 deletions(-) diff --git a/ui/vmm-details.ui b/ui/vmm-details.ui index 0302d5119..1fd0c5b0e 100644 --- a/ui/vmm-details.ui +++ b/ui/vmm-details.ui @@ -346,6 +346,7 @@ True False + Redirect USB device attached on host to virtual machine with SPICE graphics. USB Redirection device is required for Virtual Machine to support this functionality. Auto-redirection is enabled by default _Redirect USB device True diff --git a/virtManager/details.py b/virtManager/details.py index 7cd3ee700..19dcb749f 100644 --- a/virtManager/details.py +++ b/virtManager/details.py @@ -634,14 +634,9 @@ class vmmDetails(vmmGObjectUI): def init_menus(self): # Virtual Machine menu - self.widget("details-menu-usb-redirection").set_tooltip_text( - _("Redirect USB device attached on host to virtual machine with SPICE graphics. USB Redirection device is required for Virtual Machine to support this functionality. Auto-redirection is enabled by default")) - uihelpers.build_shutdown_button_menu(self.widget("control-shutdown"), - self.control_vm_shutdown, - self.control_vm_reboot, - self.control_vm_reset, - self.control_vm_destroy, - self.control_vm_save) + menu = uihelpers.VMShutdownMenu(self, lambda: self.vm) + self.widget("control-shutdown").set_menu(menu) + self.widget("control-shutdown").set_icon_name("system-shutdown") for name in ["details-menu-shutdown", "details-menu-reboot", @@ -1353,6 +1348,7 @@ class vmmDetails(vmmGObjectUI): self.widget("details-menu-migrate").set_sensitive(stop) self.widget("control-shutdown").set_sensitive(stop) + self.widget("control-shutdown").get_menu().update_widget_states(vm) self.widget("details-menu-shutdown").set_sensitive(stop) self.widget("details-menu-save").set_sensitive(stop) self.widget("control-pause").set_sensitive(stop) diff --git a/virtManager/engine.py b/virtManager/engine.py index 161860b4e..51e0c794d 100644 --- a/virtManager/engine.py +++ b/virtManager/engine.py @@ -160,6 +160,7 @@ class vmmEngine(vmmGObject): self.systray.connect("action-reboot-domain", self._do_reboot_domain) self.systray.connect("action-destroy-domain", self._do_destroy_domain) self.systray.connect("action-reset-domain", self._do_reset_domain) + self.systray.connect("action-save-domain", self._do_save_domain) self.systray.connect("action-show-vm", self._do_show_vm) self.systray.connect("action-exit-app", self.exit_app) diff --git a/virtManager/manager.py b/virtManager/manager.py index 8473ef92a..6ec164423 100644 --- a/virtManager/manager.py +++ b/virtManager/manager.py @@ -125,9 +125,8 @@ class vmmManager(vmmGObjectUI): self.prev_position = None self.vmmenu = Gtk.Menu() - self.vmmenushutdown = Gtk.Menu() + self.vmmenushutdown = uihelpers.VMShutdownMenu(self, self.current_vm) self.vmmenu_items = {} - self.vmmenushutdown_items = {} self.connmenu = Gtk.Menu() self.connmenu_items = {} @@ -238,9 +237,8 @@ class vmmManager(vmmGObjectUI): self.vmmenu.destroy() self.vmmenu = None self.vmmenu_items = None - self.vmmenushutdown.destroy() + self.vmmenushutdown.destroy() # pylint: disable=E1101 self.vmmenushutdown = None - self.vmmenushutdown_items = None self.connmenu.destroy() self.connmenu = None self.connmenu_items = None @@ -288,12 +286,10 @@ class vmmManager(vmmGObjectUI): def init_toolbar(self): self.widget("vm-new").set_icon_name("vm_new") self.widget("vm-open").set_icon_name("icon_console") - uihelpers.build_shutdown_button_menu(self.widget("vm-shutdown"), - self.poweroff_vm, - self.reboot_vm, - self.reset_vm, - self.destroy_vm, - self.save_vm) + + menu = uihelpers.VMShutdownMenu(self, self.current_vm) + self.widget("vm-shutdown").set_icon_name("system-shutdown") + self.widget("vm-shutdown").set_menu(menu) tool = self.widget("vm-toolbar") tool.set_property("icon-size", Gtk.IconSize.LARGE_TOOLBAR) @@ -301,22 +297,15 @@ class vmmManager(vmmGObjectUI): c.set_homogeneous(False) def init_context_menus(self): - def build_icon(name): - return Gtk.Image.new_from_icon_name(name, Gtk.IconSize.MENU) - def build_stock(name): return Gtk.Image.new_from_stock(name, Gtk.IconSize.MENU) - shutdownmenu_icon = build_icon("system-shutdown") - reboot_icon = build_icon("system-shutdown") - shutdown_icon = build_icon("system-shutdown") - destroy_icon = build_icon("system-shutdown") - reset_icon = build_icon("system-shutdown") - run_icon = build_stock(Gtk.STOCK_MEDIA_PLAY) - pause_icon = build_stock(Gtk.STOCK_MEDIA_PAUSE) - save_icon = build_stock(Gtk.STOCK_SAVE) - resume_icon = build_stock(Gtk.STOCK_MEDIA_PAUSE) - delete_icon = build_stock(Gtk.STOCK_DELETE) + shutdownmenu_icon = Gtk.Image.new_from_icon_name( + "system-shutdown", Gtk.IconSize.MENU) + run_icon = build_stock(Gtk.STOCK_MEDIA_PLAY) + pause_icon = build_stock(Gtk.STOCK_MEDIA_PAUSE) + resume_icon = build_stock(Gtk.STOCK_MEDIA_PAUSE) + delete_icon = build_stock(Gtk.STOCK_DELETE) def add_to_menu(menu, items, idx, text, icon, cb): if text[0:3] == 'gtk': @@ -333,9 +322,6 @@ class vmmManager(vmmGObjectUI): def add_vm_menu(idx, text, icon, cb): add_to_menu(self.vmmenu, self.vmmenu_items, idx, text, icon, cb) - def add_shutdown_menu(idx, text, icon, cb): - add_to_menu(self.vmmenushutdown, self.vmmenushutdown_items, - idx, text, icon, cb) def add_conn_menu(idx, text, icon, cb): add_to_menu(self.connmenu, self.connmenu_items, idx, text, icon, cb) @@ -352,15 +338,6 @@ class vmmManager(vmmGObjectUI): add_vm_menu("shutdown", _("_Shut Down"), shutdownmenu_icon, None) self.vmmenu_items["shutdown"].set_submenu(self.vmmenushutdown) - add_shutdown_menu("reboot", _("_Reboot"), reboot_icon, self.reboot_vm) - add_shutdown_menu("poweroff", _("_Shut Down"), shutdown_icon, - self.poweroff_vm) - add_shutdown_menu("forcereset", _("_Force Reset"), reset_icon, - self.reset_vm) - add_shutdown_menu("forcepoweroff", _("_Force Off"), destroy_icon, - self.destroy_vm) - add_sep(self.vmmenushutdown, self.vmmenushutdown_items, "sep") - add_shutdown_menu("save", _("Sa_ve"), save_icon, self.save_vm) add_sep(self.vmmenu, self.vmmenu_items, "hsep1") add_vm_menu("clone", _("_Clone..."), None, self.open_clone_window) @@ -617,36 +594,12 @@ class vmmManager(vmmGObjectUI): self.emit("action-run-domain", vm.conn.get_uri(), vm.get_uuid()) - def reboot_vm(self, ignore): - vm = self.current_vm() - if vm is not None: - self.emit("action-reboot-domain", - vm.conn.get_uri(), vm.get_uuid()) - def poweroff_vm(self, ignore): vm = self.current_vm() if vm is not None: self.emit("action-shutdown-domain", vm.conn.get_uri(), vm.get_uuid()) - def destroy_vm(self, ignore): - vm = self.current_vm() - if vm is not None: - self.emit("action-destroy-domain", - vm.conn.get_uri(), vm.get_uuid()) - - def reset_vm(self, ignore): - vm = self.current_vm() - if vm is not None: - self.emit("action-reset-domain", - vm.conn.get_uri(), vm.get_uuid()) - - def save_vm(self, ignore): - vm = self.current_vm() - if vm is not None: - self.emit("action-save-domain", - vm.conn.get_uri(), vm.get_uuid()) - def pause_vm(self, ignore): vm = self.current_vm() if vm is not None: @@ -980,6 +933,8 @@ class vmmManager(vmmGObjectUI): self.widget("vm-open").set_sensitive(show_open) self.widget("vm-run").set_sensitive(show_run) self.widget("vm-shutdown").set_sensitive(show_shutdown) + self.widget("vm-shutdown").get_menu().update_widget_states(vm) + self.set_pause_state(is_paused) self.widget("vm-pause").set_sensitive(show_pause) @@ -1015,7 +970,6 @@ class vmmManager(vmmGObjectUI): # Popup the vm menu vm = model.get_value(_iter, ROW_HANDLE) - destroy = vm.is_destroyable() run = vm.is_runable() stop = vm.is_stoppable() paused = vm.is_paused() @@ -1029,11 +983,8 @@ class vmmManager(vmmGObjectUI): self.vmmenu_items["resume"].set_sensitive(paused) self.vmmenu_items["migrate"].set_sensitive(stop) self.vmmenu_items["clone"].set_sensitive(not ro) + self.vmmenushutdown.update_widget_states(vm) - self.vmmenushutdown_items["poweroff"].set_sensitive(stop) - self.vmmenushutdown_items["reboot"].set_sensitive(stop) - self.vmmenushutdown_items["forcepoweroff"].set_sensitive(destroy) - self.vmmenushutdown_items["save"].set_sensitive(destroy) self.vmmenu.popup(None, None, None, None, 0, event.time) else: # Pop up connection menu diff --git a/virtManager/systray.py b/virtManager/systray.py index 2f78bf436..d90738d48 100644 --- a/virtManager/systray.py +++ b/virtManager/systray.py @@ -25,6 +25,7 @@ from gi.repository import GObject from gi.repository import Gtk # pylint: enable=E0611 +from virtManager import uihelpers from virtManager.baseclass import vmmGObject from virtManager.error import vmmErrorDialog @@ -57,6 +58,7 @@ class vmmSystray(vmmGObject): "action-reset-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-reboot-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-destroy-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), + "action-save-domain": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-show-host": (GObject.SignalFlags.RUN_FIRST, None, [str]), "action-show-vm": (GObject.SignalFlags.RUN_FIRST, None, [str, str]), "action-exit-app": (GObject.SignalFlags.RUN_FIRST, None, []), @@ -194,45 +196,11 @@ class vmmSystray(vmmGObject): "action-run-domain", vm.get_uuid()) # Shutdown menu - reboot_item = Gtk.ImageMenuItem.new_with_mnemonic(_("_Reboot")) - reboot_img = Gtk.Image.new_from_icon_name("system-shutdown", icon_size) - reboot_item.set_image(reboot_img) - reboot_item.connect("activate", self.run_vm_action, - "action-reboot-domain", vm.get_uuid()) - reboot_item.show() - - shutdown_item = Gtk.ImageMenuItem.new_with_mnemonic(_("_Shut Down")) - shutdown_img = Gtk.Image.new_from_icon_name("system-shutdown", - icon_size) - shutdown_item.set_image(shutdown_img) - shutdown_item.connect("activate", self.run_vm_action, - "action-shutdown-domain", vm.get_uuid()) - shutdown_item.show() - - reset_item = Gtk.ImageMenuItem.new_with_mnemonic(_("_Force Reset")) - reset_img = Gtk.Image.new_from_icon_name("system-shutdown", icon_size) - reset_item.set_image(reset_img) - reset_item.show() - reset_item.connect("activate", self.run_vm_action, - "action-reset-domain", vm.get_uuid()) - - destroy_item = Gtk.ImageMenuItem.new_with_mnemonic(_("_Force Off")) - destroy_img = Gtk.Image.new_from_icon_name("system-shutdown", - icon_size) - destroy_item.set_image(destroy_img) - destroy_item.show() - destroy_item.connect("activate", self.run_vm_action, - "action-destroy-domain", vm.get_uuid()) - - shutdown_menu = Gtk.Menu() - shutdown_menu.add(reboot_item) - shutdown_menu.add(shutdown_item) - shutdown_menu.add(reset_item) - shutdown_menu.add(destroy_item) - shutdown_menu_item = Gtk.ImageMenuItem.new_with_mnemonic(_("_Shut Down")) - shutdown_menu_img = Gtk.Image.new_from_icon_name("system-shutdown", - icon_size) - shutdown_menu_item.set_image(shutdown_menu_img) + shutdown_menu = uihelpers.VMShutdownMenu(self, lambda: vm) + shutdown_menu_item = Gtk.ImageMenuItem.new_with_mnemonic( + _("_Shut Down")) + shutdown_menu_item.set_image(Gtk.Image.new_from_icon_name( + "system-shutdown", icon_size)) shutdown_menu_item.set_submenu(shutdown_menu) sep = Gtk.SeparatorMenuItem() @@ -247,10 +215,6 @@ class vmmSystray(vmmGObject): vm_action_dict["pause"] = pause_item vm_action_dict["resume"] = resume_item vm_action_dict["shutdown_menu"] = shutdown_menu_item - vm_action_dict["reboot"] = reboot_item - vm_action_dict["shutdown"] = shutdown_item - vm_action_dict["reset"] = reset_item - vm_action_dict["destroy"] = destroy_item vm_action_dict["sep"] = sep vm_action_dict["open"] = open_item @@ -436,10 +400,7 @@ class vmmSystray(vmmGObject): actions["pause"].set_sensitive(vm.is_pauseable()) actions["resume"].set_sensitive(vm.is_paused()) actions["shutdown_menu"].set_sensitive(vm.is_active()) - actions["shutdown"].set_sensitive(vm.is_stoppable()) - actions["reboot"].set_sensitive(vm.is_stoppable()) - actions["reset"].set_sensitive(vm.is_destroyable()) - actions["destroy"].set_sensitive(vm.is_destroyable()) + actions["shutdown_menu"].get_submenu().update_widget_states(vm) actions["pause"].set_visible(not is_paused) actions["resume"].set_visible(is_paused) diff --git a/virtManager/uihelpers.py b/virtManager/uihelpers.py index 242e6b0f3..83507e40a 100644 --- a/virtManager/uihelpers.py +++ b/virtManager/uihelpers.py @@ -908,55 +908,54 @@ def mediadev_set_default_selection(widget): # Build toolbar shutdown button menu (manager and details toolbar) # #################################################################### -def build_shutdown_button_menu(widget, shutdown_cb, reboot_cb, reset_cb, - destroy_cb, save_cb): - widget.set_icon_name("system-shutdown") - menu = Gtk.Menu() - widget.set_menu(menu) +class VMShutdownMenu(Gtk.Menu): + # pylint: disable=E1101 + # pylint can't detect functions we inheirit from Gtk, ex self.add - rebootimg = Gtk.Image.new_from_icon_name("system-shutdown", - Gtk.IconSize.MENU) - shutdownimg = Gtk.Image.new_from_icon_name("system-shutdown", - Gtk.IconSize.MENU) - destroyimg = Gtk.Image.new_from_icon_name("system-shutdown", - Gtk.IconSize.MENU) - resetimg = Gtk.Image.new_from_icon_name("system-shutdown", - Gtk.IconSize.MENU) - saveimg = Gtk.Image.new_from_icon_name(Gtk.STOCK_SAVE, Gtk.IconSize.MENU) + def __init__(self, src, current_vm_cb): + Gtk.Menu.__init__(self) + self._parent = src + self._current_vm_cb = current_vm_cb + self._init_state() - reboot = Gtk.ImageMenuItem.new_with_mnemonic(_("_Reboot")) - reboot.set_image(rebootimg) - reboot.show() - reboot.connect("activate", reboot_cb) - menu.add(reboot) + def _init_state(self): + def _add_action(label, signal, iconname="system-shutdown"): + item = Gtk.ImageMenuItem.new_with_mnemonic(label) + icon = Gtk.Image.new_from_icon_name(iconname, Gtk.IconSize.MENU) + item.set_image(icon) + item.connect("activate", self._action_cb) + item.vmm_widget_name = signal + self.add(item) - shutdown = Gtk.ImageMenuItem.new_with_mnemonic(_("_Shut Down")) - shutdown.set_image(shutdownimg) - shutdown.show() - shutdown.connect("activate", shutdown_cb) - menu.add(shutdown) + _add_action(_("_Reboot"), "reboot") + _add_action(_("_Shut Down"), "shutdown") + _add_action(_("F_orce Reset"), "reset") + _add_action(_("_Force Off"), "destroy") + self.add(Gtk.SeparatorMenuItem()) + _add_action(_("Sa_ve"), "save", iconname=Gtk.STOCK_SAVE) - reset = Gtk.ImageMenuItem.new_with_mnemonic(_("_Force Reset")) - reset.set_image(resetimg) - reset.show() - reset.connect("activate", reset_cb) - menu.add(reset) + self.show_all() - destroy = Gtk.ImageMenuItem.new_with_mnemonic(_("_Force Off")) - destroy.set_image(destroyimg) - destroy.show() - destroy.connect("activate", destroy_cb) - menu.add(destroy) + def _action_cb(self, src): + vm = self._current_vm_cb() + if not vm: + return + self._parent.emit("action-%s-domain" % src.vmm_widget_name, + vm.conn.get_uri(), vm.get_uuid()) - sep = Gtk.SeparatorMenuItem() - sep.show() - menu.add(sep) + def update_widget_states(self, vm): + statemap = { + "reboot": bool(vm and vm.is_stoppable()), + "shutdown": bool(vm and vm.is_stoppable()), + "reset": bool(vm and vm.is_stoppable()), + "save": bool(vm and vm.is_destroyable()), + "destroy": bool(vm and vm.is_destroyable()), + } - save = Gtk.ImageMenuItem.new_with_mnemonic(_("Sa_ve")) - save.set_image(saveimg) - save.show() - save.connect("activate", save_cb) - menu.add(save) + for child in self.get_children(): + name = getattr(child, "vmm_widget_name", None) + if name in statemap: + child.set_sensitive(statemap[name]) #####################################