virt-manager/virtManager/device/mediacombo.py

192 lines
5.8 KiB
Python

# Copyright (C) 2014 Red Hat, Inc.
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
from gi.repository import Gtk
from ..lib import uiutil
from ..baseclass import vmmGObject, vmmGObjectUI
class vmmMediaCombo(vmmGObjectUI):
__gsignals__ = {
"changed": (vmmGObject.RUN_FIRST, None, [object]),
"activate": (vmmGObject.RUN_FIRST, None, [object]),
}
MEDIA_TYPE_FLOPPY = "floppy"
MEDIA_TYPE_CDROM = "cdrom"
MEDIA_FIELDS_NUM = 4
(MEDIA_FIELD_PATH,
MEDIA_FIELD_LABEL,
MEDIA_FIELD_HAS_MEDIA,
MEDIA_FIELD_KEY) = range(MEDIA_FIELDS_NUM)
def __init__(self, conn, builder, topwin):
vmmGObjectUI.__init__(self, None, None, builder=builder, topwin=topwin)
self.conn = conn
self.top_box = None
self._combo = None
self._populated = False
self._init_ui()
self._iso_rows = []
self._cdrom_rows = []
self._floppy_rows = []
self._rows_inited = False
self.add_gsettings_handle(
self.config.on_iso_paths_changed(self._iso_paths_changed_cb))
def _cleanup(self):
self.conn = None
self.top_box.destroy()
self.top_box = None
##########################
# Initialization methods #
##########################
def _init_ui(self):
self.top_box = Gtk.Box()
self.top_box.set_spacing(6)
self.top_box.set_orientation(Gtk.Orientation.HORIZONTAL)
self._combo = Gtk.ComboBox(has_entry=True)
self._combo.set_entry_text_column(self.MEDIA_FIELD_LABEL)
self._combo.get_accessible().set_name("media-combo")
def separator_cb(_model, _iter):
return _model[_iter][self.MEDIA_FIELD_PATH] is None
self._combo.set_row_separator_func(separator_cb)
self._entry = self._combo.get_child()
self._entry.set_placeholder_text(_("No media selected"))
self._entry.set_hexpand(True)
self._entry.get_accessible().set_name("media-entry")
self._entry.connect("changed", self._on_entry_changed_cb)
self._entry.connect("activate", self._on_entry_activated_cb)
self._entry.connect("icon-press", self._on_entry_icon_press_cb)
self._browse = Gtk.Button()
self.top_box.add(self._combo)
self.top_box.show_all()
# [path, label, has_media?, device key]
store = Gtk.ListStore(str, str, bool, str)
self._combo.set_model(store)
def _make_row(self, path, label, has_media, key):
row = [None] * self.MEDIA_FIELDS_NUM
row[self.MEDIA_FIELD_PATH] = path
row[self.MEDIA_FIELD_LABEL] = label
row[self.MEDIA_FIELD_HAS_MEDIA] = has_media
row[self.MEDIA_FIELD_KEY] = key
return row
def _make_nodedev_rows(self, media_type):
rows = []
for nodedev in self.conn.filter_nodedevs("storage"):
if not (nodedev.xmlobj.device_type == "storage" and
nodedev.xmlobj.drive_type in ["cdrom", "floppy"]):
continue
if nodedev.xmlobj.drive_type != media_type:
continue
media_label = nodedev.xmlobj.media_label or _("Media Unknown")
if not nodedev.xmlobj.media_available:
media_label = _("No media detected")
label = "%s (%s)" % (media_label, nodedev.xmlobj.block)
row = self._make_row(nodedev.xmlobj.block, label,
nodedev.xmlobj.media_available,
nodedev.xmlobj.name)
rows.append(row)
return rows
def _make_iso_rows(self):
rows = []
for path in self.config.get_iso_paths():
row = self._make_row(path, path, True, path)
rows.append(row)
return rows
def _init_rows(self):
self._cdrom_rows = self._make_nodedev_rows("cdrom")
self._floppy_rows = self._make_nodedev_rows("floppy")
self._iso_rows = self._make_iso_rows()
self._rows_inited = True
################
# UI callbacks #
################
def _on_entry_changed_cb(self, src):
self.emit("changed", self._entry)
def _on_entry_activated_cb(self, src):
self.emit("activate", self._entry)
def _on_entry_icon_press_cb(self, src, icon_pos, event):
self._entry.set_text("")
def _iso_paths_changed_cb(self):
self._iso_rows = self._make_iso_rows()
##############
# Public API #
##############
def set_conn(self, conn):
if conn == self.conn:
return
self.conn = conn
self._init_rows()
def reset_state(self, is_floppy=False):
if not self._rows_inited:
self._init_rows()
model = self._combo.get_model()
model.clear()
for row in self._iso_rows:
model.append(row)
nodedev_rows = self._cdrom_rows
if is_floppy:
nodedev_rows = self._floppy_rows
if len(model) and nodedev_rows:
model.append(self._make_row(None, None, False, None))
for row in nodedev_rows:
model.append(row)
self._combo.set_active(-1)
def get_path(self, store_media=True):
ret = uiutil.get_list_selection(
self._combo, column=self.MEDIA_FIELD_PATH)
if store_media and not ret.startswith("/dev"):
self.config.add_iso_path(ret)
return ret
def set_path(self, path):
uiutil.set_list_selection(
self._combo, path, column=self.MEDIA_FIELD_PATH)
self._entry.set_position(-1)
def set_mnemonic_label(self, label):
label.set_mnemonic_widget(self._entry)
def show_clear_icon(self):
pos = Gtk.EntryIconPosition.SECONDARY
self._entry.set_icon_from_icon_name(pos, "edit-clear-symbolic")
self._entry.set_icon_activatable(pos, True)