mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-02-25 18:55:27 -06:00
manager: Simplify row management a bit
Drop the self.rows dict, use more pygobject row[] convenience helpers, add some helper properties for VM
This commit is contained in:
parent
7de9028221
commit
97db1ac18a
@ -107,10 +107,6 @@ class vmmManager(vmmGObjectUI):
|
|||||||
vmmGObjectUI.__init__(self, "manager.ui", "vmm-manager")
|
vmmGObjectUI.__init__(self, "manager.ui", "vmm-manager")
|
||||||
self._cleanup_on_app_close()
|
self._cleanup_on_app_close()
|
||||||
|
|
||||||
# Mapping of rowkey -> tree model rows to
|
|
||||||
# allow O(1) access instead of O(n)
|
|
||||||
self.rows = {}
|
|
||||||
|
|
||||||
w, h = self.config.get_manager_window_size()
|
w, h = self.config.get_manager_window_size()
|
||||||
self.topwin.set_default_size(w or 550, h or 550)
|
self.topwin.set_default_size(w or 550, h or 550)
|
||||||
self.prev_position = None
|
self.prev_position = None
|
||||||
@ -222,8 +218,6 @@ class vmmManager(vmmGObjectUI):
|
|||||||
|
|
||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
self.rows = None
|
|
||||||
|
|
||||||
self.diskcol = None
|
self.diskcol = None
|
||||||
self.guestcpucol = None
|
self.guestcpucol = None
|
||||||
self.memcol = None
|
self.memcol = None
|
||||||
@ -417,10 +411,15 @@ class vmmManager(vmmGObjectUI):
|
|||||||
model.set_sort_func(COL_NETWORK, self.vmlist_network_usage_sorter)
|
model.set_sort_func(COL_NETWORK, self.vmlist_network_usage_sorter)
|
||||||
model.set_sort_column_id(COL_NAME, Gtk.SortType.ASCENDING)
|
model.set_sort_column_id(COL_NAME, Gtk.SortType.ASCENDING)
|
||||||
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Helper methods #
|
# Helper methods #
|
||||||
##################
|
##################
|
||||||
|
|
||||||
|
@property
|
||||||
|
def model(self):
|
||||||
|
return self.widget("vm-list").get_model()
|
||||||
|
|
||||||
def current_row(self):
|
def current_row(self):
|
||||||
return uiutil.get_list_selected_row(self.widget("vm-list"))
|
return uiutil.get_list_selected_row(self.widget("vm-list"))
|
||||||
|
|
||||||
@ -431,21 +430,30 @@ class vmmManager(vmmGObjectUI):
|
|||||||
|
|
||||||
return row[ROW_HANDLE]
|
return row[ROW_HANDLE]
|
||||||
|
|
||||||
def current_conn(self, choose_default=False):
|
def current_conn(self):
|
||||||
row = self.current_row()
|
row = self.current_row()
|
||||||
if row:
|
if not row:
|
||||||
handle = row[ROW_HANDLE]
|
return None
|
||||||
if row[ROW_IS_CONN]:
|
handle = row[ROW_HANDLE]
|
||||||
return handle
|
if row[ROW_IS_CONN]:
|
||||||
return handle.conn
|
return handle
|
||||||
|
return handle.conn
|
||||||
|
|
||||||
if choose_default:
|
def get_row(self, conn_or_vm):
|
||||||
# Nothing selected, use first connection row
|
def _walk(rowiter):
|
||||||
vmlist = self.widget("vm-list")
|
while rowiter:
|
||||||
model = vmlist.get_model()
|
row = self.model[rowiter]
|
||||||
for row in model:
|
if row[ROW_HANDLE] == conn_or_vm:
|
||||||
if row[ROW_IS_CONN]:
|
return row
|
||||||
return row[ROW_HANDLE]
|
if self.model.iter_has_child(rowiter):
|
||||||
|
ret = _walk(self.model.iter_nth_child(rowiter, 0))
|
||||||
|
if ret:
|
||||||
|
return ret
|
||||||
|
rowiter = self.model.iter_next(rowiter)
|
||||||
|
|
||||||
|
if not len(self.model):
|
||||||
|
return None
|
||||||
|
return _walk(self.model.get_iter_first())
|
||||||
|
|
||||||
|
|
||||||
####################
|
####################
|
||||||
@ -479,7 +487,7 @@ class vmmManager(vmmGObjectUI):
|
|||||||
|
|
||||||
def show_host(self, _src):
|
def show_host(self, _src):
|
||||||
from .host import vmmHost
|
from .host import vmmHost
|
||||||
conn = self.current_conn(choose_default=True)
|
conn = self.current_conn()
|
||||||
vmmHost.show_instance(self, conn)
|
vmmHost.show_instance(self, conn)
|
||||||
|
|
||||||
def show_vm(self, _src):
|
def show_vm(self, _src):
|
||||||
@ -562,42 +570,29 @@ class vmmManager(vmmGObjectUI):
|
|||||||
# VM add/remove management methods #
|
# VM add/remove management methods #
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
def vm_row_key(self, vm):
|
|
||||||
return vm.get_uuid() + ":" + vm.conn.get_uri()
|
|
||||||
|
|
||||||
def vm_added(self, conn, connkey):
|
def vm_added(self, conn, connkey):
|
||||||
vm = conn.get_vm(connkey)
|
vm = conn.get_vm(connkey)
|
||||||
if not vm:
|
if not vm:
|
||||||
return
|
return
|
||||||
|
|
||||||
row_key = self.vm_row_key(vm)
|
vm_row = self._build_row(None, vm)
|
||||||
if row_key in self.rows:
|
conn_row = self.get_row(conn)
|
||||||
return
|
self.model.append(conn_row.iter, vm_row)
|
||||||
|
|
||||||
row = self._build_row(None, vm)
|
|
||||||
parent = self.rows[conn.get_uri()].iter
|
|
||||||
model = self.widget("vm-list").get_model()
|
|
||||||
_iter = model.append(parent, row)
|
|
||||||
path = model.get_path(_iter)
|
|
||||||
self.rows[row_key] = model[path]
|
|
||||||
|
|
||||||
vm.connect("state-changed", self.vm_changed)
|
vm.connect("state-changed", self.vm_changed)
|
||||||
vm.connect("resources-sampled", self.vm_row_updated)
|
vm.connect("resources-sampled", self.vm_row_updated)
|
||||||
vm.connect("inspection-changed", self.vm_inspection_changed)
|
vm.connect("inspection-changed", self.vm_inspection_changed)
|
||||||
|
|
||||||
# Expand a connection when adding a vm to it
|
# Expand a connection when adding a vm to it
|
||||||
self.widget("vm-list").expand_row(model.get_path(parent), False)
|
self.widget("vm-list").expand_row(conn_row.path, False)
|
||||||
|
|
||||||
def vm_removed(self, conn, connkey):
|
def vm_removed(self, conn, connkey):
|
||||||
vmlist = self.widget("vm-list")
|
parent = self.get_row(conn).iter
|
||||||
model = vmlist.get_model()
|
for rowidx in range(self.model.iter_n_children(parent)):
|
||||||
|
rowiter = self.model.iter_nth_child(parent, rowidx)
|
||||||
parent = self.rows[conn.get_uri()].iter
|
vm = self.model[rowiter][ROW_HANDLE]
|
||||||
for row in range(model.iter_n_children(parent)):
|
|
||||||
vm = model[model.iter_nth_child(parent, row)][ROW_HANDLE]
|
|
||||||
if vm.get_connkey() == connkey:
|
if vm.get_connkey() == connkey:
|
||||||
model.remove(model.iter_nth_child(parent, row))
|
self.model.remove(rowiter)
|
||||||
del self.rows[self.vm_row_key(vm)]
|
|
||||||
break
|
break
|
||||||
|
|
||||||
def _build_conn_hint(self, conn):
|
def _build_conn_hint(self, conn):
|
||||||
@ -667,15 +662,11 @@ class vmmManager(vmmGObjectUI):
|
|||||||
def _conn_added(self, _src, conn):
|
def _conn_added(self, _src, conn):
|
||||||
# Make sure error page isn't showing
|
# Make sure error page isn't showing
|
||||||
self.widget("vm-notebook").set_current_page(0)
|
self.widget("vm-notebook").set_current_page(0)
|
||||||
|
if self.get_row(conn):
|
||||||
if conn.get_uri() in self.rows:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
model = self.widget("vm-list").get_model()
|
conn_row = self._build_row(conn, None)
|
||||||
row = self._build_row(conn, None)
|
self.model.append(None, conn_row)
|
||||||
_iter = model.append(None, row)
|
|
||||||
path = model.get_path(_iter)
|
|
||||||
self.rows[conn.get_uri()] = model[path]
|
|
||||||
|
|
||||||
conn.connect("vm-added", self.vm_added)
|
conn.connect("vm-added", self.vm_added)
|
||||||
conn.connect("vm-removed", self.vm_removed)
|
conn.connect("vm-removed", self.vm_removed)
|
||||||
@ -686,20 +677,19 @@ class vmmManager(vmmGObjectUI):
|
|||||||
self.vm_added(conn, vm.get_connkey())
|
self.vm_added(conn, vm.get_connkey())
|
||||||
|
|
||||||
def _conn_removed(self, _src, uri):
|
def _conn_removed(self, _src, uri):
|
||||||
model = self.widget("vm-list").get_model()
|
conn_row = None
|
||||||
parent = self.rows[uri].iter
|
for row in self.model:
|
||||||
|
if row[ROW_IS_CONN] and row[ROW_HANDLE].get_uri() == uri:
|
||||||
if parent is None:
|
conn_row = row
|
||||||
|
break
|
||||||
|
if conn_row is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
child = model.iter_children(parent)
|
child = self.model.iter_children(conn_row.iter)
|
||||||
while child is not None:
|
while child is not None:
|
||||||
del self.rows[self.vm_row_key(model[child][ROW_HANDLE])]
|
self.model.remove(child)
|
||||||
model.remove(child)
|
child = self.model.iter_children(conn_row.iter)
|
||||||
child = model.iter_children(parent)
|
self.model.remove(conn_row.iter)
|
||||||
model.remove(parent)
|
|
||||||
|
|
||||||
del self.rows[uri]
|
|
||||||
|
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
@ -707,13 +697,13 @@ class vmmManager(vmmGObjectUI):
|
|||||||
#############################
|
#############################
|
||||||
|
|
||||||
def vm_row_updated(self, vm):
|
def vm_row_updated(self, vm):
|
||||||
row = self.rows.get(self.vm_row_key(vm), None)
|
row = self.get_row(vm)
|
||||||
if row is None:
|
if row is None:
|
||||||
return
|
return
|
||||||
self.widget("vm-list").get_model().row_changed(row.path, row.iter)
|
self.model.row_changed(row.path, row.iter)
|
||||||
|
|
||||||
def vm_changed(self, vm):
|
def vm_changed(self, vm):
|
||||||
row = self.rows.get(self.vm_row_key(vm), None)
|
row = self.get_row(vm)
|
||||||
if row is None:
|
if row is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -739,7 +729,7 @@ class vmmManager(vmmGObjectUI):
|
|||||||
self.vm_row_updated(vm)
|
self.vm_row_updated(vm)
|
||||||
|
|
||||||
def vm_inspection_changed(self, vm):
|
def vm_inspection_changed(self, vm):
|
||||||
row = self.rows.get(self.vm_row_key(vm), None)
|
row = self.get_row(vm)
|
||||||
if row is None:
|
if row is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -749,30 +739,22 @@ class vmmManager(vmmGObjectUI):
|
|||||||
self.vm_row_updated(vm)
|
self.vm_row_updated(vm)
|
||||||
|
|
||||||
def set_initial_selection(self, uri):
|
def set_initial_selection(self, uri):
|
||||||
vmlist = self.widget("vm-list")
|
"""
|
||||||
model = vmlist.get_model()
|
Select the passed URI in the UI. Called from engine.py via
|
||||||
it = model.get_iter_first()
|
cli --connect $URI
|
||||||
selected = None
|
"""
|
||||||
while it:
|
sel = self.widget("vm-list").get_selection()
|
||||||
key = model.get_value(it, ROW_HANDLE)
|
for row in self.model:
|
||||||
|
if not row[ROW_IS_CONN]:
|
||||||
|
continue
|
||||||
|
conn = row[ROW_HANDLE]
|
||||||
|
|
||||||
if key.get_uri() == uri:
|
if conn.get_uri() == uri:
|
||||||
vmlist.get_selection().select_iter(it)
|
sel.select_iter(row.iter)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not selected:
|
|
||||||
vmlist.get_selection().select_iter(it)
|
|
||||||
selected = key
|
|
||||||
elif key.get_autoconnect() and not selected.get_autoconnect():
|
|
||||||
vmlist.get_selection().select_iter(it)
|
|
||||||
selected = key
|
|
||||||
if not uri:
|
|
||||||
return
|
|
||||||
|
|
||||||
it = model.iter_next(it)
|
|
||||||
|
|
||||||
def conn_state_changed(self, conn):
|
def conn_state_changed(self, conn):
|
||||||
row = self.rows[conn.get_uri()]
|
row = self.get_row(conn)
|
||||||
row[ROW_SORT_KEY] = conn.get_pretty_desc()
|
row[ROW_SORT_KEY] = conn.get_pretty_desc()
|
||||||
row[ROW_MARKUP] = self._build_conn_markup(conn, row[ROW_SORT_KEY])
|
row[ROW_MARKUP] = self._build_conn_markup(conn, row[ROW_SORT_KEY])
|
||||||
row[ROW_IS_CONN_CONNECTED] = not conn.is_disconnected()
|
row[ROW_IS_CONN_CONNECTED] = not conn.is_disconnected()
|
||||||
@ -780,28 +762,22 @@ class vmmManager(vmmGObjectUI):
|
|||||||
row[ROW_HINT] = self._build_conn_hint(conn)
|
row[ROW_HINT] = self._build_conn_hint(conn)
|
||||||
|
|
||||||
if not conn.is_active():
|
if not conn.is_active():
|
||||||
# Connection went inactive, delete any VM child nodes
|
child = self.model.iter_children(row.iter)
|
||||||
parent = row.iter
|
while child is not None:
|
||||||
if parent is not None:
|
self.model.remove(child)
|
||||||
model = self.widget("vm-list").get_model()
|
child = self.model.iter_children(row.iter)
|
||||||
child = model.iter_children(parent)
|
|
||||||
while child is not None:
|
|
||||||
vm = model[child][ROW_HANDLE]
|
|
||||||
del self.rows[self.vm_row_key(vm)]
|
|
||||||
model.remove(child)
|
|
||||||
child = model.iter_children(parent)
|
|
||||||
|
|
||||||
self.conn_row_updated(conn)
|
self.conn_row_updated(conn)
|
||||||
self.update_current_selection()
|
self.update_current_selection()
|
||||||
|
|
||||||
def conn_row_updated(self, conn):
|
def conn_row_updated(self, conn):
|
||||||
row = self.rows[conn.get_uri()]
|
row = self.get_row(conn)
|
||||||
|
|
||||||
self.max_disk_rate = max(self.max_disk_rate, conn.disk_io_max_rate())
|
self.max_disk_rate = max(self.max_disk_rate, conn.disk_io_max_rate())
|
||||||
self.max_net_rate = max(self.max_net_rate,
|
self.max_net_rate = max(self.max_net_rate,
|
||||||
conn.network_traffic_max_rate())
|
conn.network_traffic_max_rate())
|
||||||
|
|
||||||
self.widget("vm-list").get_model().row_changed(row.path, row.iter)
|
self.model.row_changed(row.path, row.iter)
|
||||||
|
|
||||||
def change_run_text(self, can_restore):
|
def change_run_text(self, can_restore):
|
||||||
if can_restore:
|
if can_restore:
|
||||||
@ -859,18 +835,16 @@ class vmmManager(vmmGObjectUI):
|
|||||||
self.popup_vm_menu(model, treeiter, event)
|
self.popup_vm_menu(model, treeiter, event)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def popup_vm_menu_button(self, widget, event):
|
def popup_vm_menu_button(self, vmlist, event):
|
||||||
if event.button != 3:
|
if event.button != 3:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
tup = widget.get_path_at_pos(int(event.x), int(event.y))
|
tup = vmlist.get_path_at_pos(int(event.x), int(event.y))
|
||||||
if tup is None:
|
if tup is None:
|
||||||
return False
|
return False
|
||||||
path = tup[0]
|
path = tup[0]
|
||||||
model = widget.get_model()
|
|
||||||
_iter = model.get_iter(path)
|
|
||||||
|
|
||||||
self.popup_vm_menu(model, _iter, event)
|
self.popup_vm_menu(self.model, self.model.get_iter(path), event)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def popup_vm_menu(self, model, _iter, event):
|
def popup_vm_menu(self, model, _iter, event):
|
||||||
|
Loading…
Reference in New Issue
Block a user