Make virt-manager remember last used paths

This patch makes virt-manager remember last used paths for disk images, saved
snapshots, restored snapshots, media paths and also screenshot paths not to
bother users with changing paths from the default location per HV technology.
Useful when installing multiple domains and having all the media/image files
in non-default locations.
This commit is contained in:
Michal Novotny 2009-06-23 19:30:12 -04:00
parent f918e05d31
commit fd480885bc
10 changed files with 164 additions and 23 deletions

View File

@ -272,5 +272,70 @@
<long>Whether to install a sound device for remote VMs or not</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/paths/default-image-path</key>
<applyto>/apps/::PACKAGE::/paths/default-image-path</applyto>
<owner>::PACKAGE::</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>Default image path</short>
<long>Default path for choosing VM images</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/paths/default-media-path</key>
<applyto>/apps/::PACKAGE::/paths/default-media-path</applyto>
<owner>::PACKAGE::</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>Default media path</short>
<long>Default path for choosing media</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/paths/default-save-path</key>
<applyto>/apps/::PACKAGE::/paths/default-save-path</applyto>
<owner>::PACKAGE::</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>Default save domain path</short>
<long>Default path for saving VM snaphots</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/paths/default-restore-path</key>
<applyto>/apps/::PACKAGE::/paths/default-restore-path</applyto>
<owner>::PACKAGE::</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>Default restore path</short>
<long>Default path for stored VM snapshots</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/::PACKAGE::/paths/default-screenshot-path</key>
<applyto>/apps/::PACKAGE::/paths/default-screenshot-path</applyto>
<owner>::PACKAGE::</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>Default screenshot path</short>
<long>Default path for saving screenshots from VMs</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@ -701,14 +701,15 @@ class vmmAddHardware(gobject.GObject):
conn = self.vm.get_connection()
if self.storage_browser == None:
self.storage_browser = vmmStorageBrowser(self.config, conn)
self.storage_browser = vmmStorageBrowser(self.config, conn, False)
if self._browse_cb_id:
self.storage_browser.disconnect(self._browse_cb_id)
self._browse_cb_id = self.storage_browser.connect("storage-browse-finish", set_storage_cb)
self.storage_browser.local_args = { "dialog_name": dialog_name,
"start_folder": folder,
"confirm_func": confirm_func, }
"confirm_func": confirm_func,
"browse_reason":
self.config.CONFIG_DIR_IMAGE }
self.storage_browser.show(conn)
return None

View File

@ -149,11 +149,13 @@ class vmmChooseCD(gobject.GObject):
def _browse_file(self, dialog_name):
if self.storage_browser == None:
self.storage_browser = vmmStorageBrowser(self.config, self.conn)
#self.topwin)
self.storage_browser = vmmStorageBrowser(self.config, self.conn,
True)
self.storage_browser.connect("storage-browse-finish",
self.set_storage_path)
self.storage_browser.local_args = { "dialog_name": dialog_name }
self.storage_browser.local_args = { "dialog_name": dialog_name,
"browse_reason":
self.config.CONFIG_DIR_MEDIA }
self.storage_browser.show(self.conn)
return None

View File

@ -45,6 +45,13 @@ DEFAULT_VIRT_SAVE_DIR = "/var/lib/libvirt"
class vmmConfig:
# GConf directory names for saving last used paths
CONFIG_DIR_IMAGE = "image"
CONFIG_DIR_MEDIA = "media"
CONFIG_DIR_SAVE = "save"
CONFIG_DIR_RESTORE = "restore"
CONFIG_DIR_SCREENSHOT = "screenshot"
CONSOLE_SCALE_NEVER = 0
CONSOLE_SCALE_FULLSCREEN = 1
CONSOLE_SCALE_ALWAYS = 2
@ -261,6 +268,36 @@ class vmmConfig:
self.conf.set_bool(self.conf_dir + "/vmlist-fields/network_traffic", state)
def get_default_directory(self, conn, _type):
if not _type:
logging.error("Unknown type for get_default_directory")
return
try:
path = self.conf.get_value(self.conf_dir + "/paths/default-%s-path"
% _type)
except:
path = None
if not path:
if (_type == self.CONFIG_DIR_IMAGE or
_type == self.CONFIG_DIR_MEDIA):
path = self.get_default_image_dir(conn)
if (_type == self.CONFIG_DIR_SAVE or
_type == self.CONFIG_DIR_RESTORE):
path = self.get_default_save_dir(conn)
logging.debug("get_default_directory(%s): returning %s" % (_type, path))
return path
def set_default_directory(self, folder, _type):
if not _type:
logging.error("Unknown type for set_default_directory")
return
logging.debug("set_default_directory(%s): saving %s" % (_type, folder))
self.conf.set_value(self.conf_dir + "/paths/default-%s-path" % _type,
folder)
def on_vmlist_domain_id_visible_changed(self, callback):
self.conf.notify_add(self.conf_dir + "/vmlist-fields/domain_id", callback)

View File

@ -996,7 +996,8 @@ class vmmCreate(gobject.GObject):
def browse_iso(self, ignore1=None, ignore2=None):
self._browse_file(_("Locate ISO Image"),
self.set_iso_storage_path)
self.set_iso_storage_path,
is_media=True)
self.window.get_widget("install-local-box").activate()
def toggle_enable_storage(self, src):
@ -1004,7 +1005,8 @@ class vmmCreate(gobject.GObject):
def browse_storage(self, ignore1):
self._browse_file(_("Locate existing storage"),
self.set_disk_storage_path)
self.set_disk_storage_path,
is_media=False)
def toggle_storage_select(self, src):
act = src.get_active()
@ -1648,13 +1650,20 @@ class vmmCreate(gobject.GObject):
logging.exception("Error detecting distro.")
self.detectedDistro = (None, None)
def _browse_file(self, dialog_name, callback, folder=None):
def _browse_file(self, dialog_name, callback, folder=None, is_media=False):
if self.storage_browser == None:
self.storage_browser = vmmStorageBrowser(self.config, self.conn)
self.storage_browser = vmmStorageBrowser(self.config, self.conn,
is_media)
self.storage_browser.connect("storage-browse-finish",
callback)
if is_media:
reason = self.config.CONFIG_DIR_MEDIA
else:
reason = self.config.CONFIG_DIR_IMAGE
self.storage_browser.local_args = { "dialog_name": dialog_name,
"start_folder": folder}
"start_folder": folder,
"browse_reason": reason}
self.storage_browser.show(self.conn)
def show_help(self, ignore):

View File

@ -1410,8 +1410,10 @@ class vmmDetails(gobject.GObject):
# user to choose what image format they'd like to save in....
path = util.browse_local(self.window.get_widget("vmm-details"),
_("Save Virtual Machine Screenshot"),
_type = ("*.png", "PNG files"),
dialog_type = gtk.FILE_CHOOSER_ACTION_SAVE)
self.config, self.vm.get_connection(),
_type = ("png", "PNG files"),
dialog_type = gtk.FILE_CHOOSER_ACTION_SAVE,
browse_reason=self.config.CONFIG_DIR_SCREENSHOT)
if not path:
return

View File

@ -406,8 +406,9 @@ class vmmEngine(gobject.GObject):
path = util.browse_local(src.window.get_widget("vmm-details"),
_("Save Virtual Machine"),
self.config.get_default_save_dir(con),
dialog_type=gtk.FILE_CHOOSER_ACTION_SAVE)
self.config, self.get_connection(uri),
dialog_type=gtk.FILE_CHOOSER_ACTION_SAVE,
browse_reason=self.config.CONFIG_DIR_SAVE)
if not path:
return

View File

@ -397,7 +397,8 @@ class vmmManager(gobject.GObject):
path = util.browse_local(self.window.get_widget("vmm-manager"),
_("Restore Virtual Machine"),
self.config.get_default_save_dir(conn))
self.config, conn,
browse_reason=self.config.CONFIG_DIR_RESTORE)
if not path:
return

View File

@ -38,7 +38,7 @@ class vmmStorageBrowser(gobject.GObject):
gobject.TYPE_NONE, [str]),
}
def __init__(self, config, conn):
def __init__(self, config, conn, is_media=False):
self.__gobject_init__()
self.window = gtk.glade.XML(config.get_glade_dir() + \
"/vmm-storage-browse.glade",
@ -58,8 +58,14 @@ class vmmStorageBrowser(gobject.GObject):
# Add Volume wizard
self.addvol = None
if is_media:
reason = self.config.CONFIG_DIR_MEDIA
else:
reason = self.config.CONFIG_DIR_IMAGE
# Arguments to pass to util.browse_local for local storage
self.local_args = {"dialog_name": _("Choose local storage")}
self.local_args = {"dialog_name": _("Choose local storage"),
"browse_reason": reason, }
self.window.signal_autoconnect({
"on_vmm_storage_browse_delete_event" : self.close,
@ -232,7 +238,8 @@ class vmmStorageBrowser(gobject.GObject):
"".join(traceback.format_exc()))
def browse_local(self, src):
filename = util.browse_local(parent=self.topwin, **self.local_args)
filename = util.browse_local(parent=self.topwin, config=self.config,
conn=self.conn, **self.local_args)
if filename:
self._do_finish(path=filename)

View File

@ -21,6 +21,7 @@
import logging
import gtk
import libxml2
import os.path
import libvirt
@ -90,17 +91,24 @@ def xml_parse_wrapper(xml, parse_func, *args, **kwargs):
return ret
def browse_local(parent, dialog_name, start_folder=None, _type=None,
dialog_type=gtk.FILE_CHOOSER_ACTION_OPEN, confirm_func=None):
def browse_local(parent, dialog_name, config, conn, start_folder=None,
_type=None, dialog_type=gtk.FILE_CHOOSER_ACTION_OPEN,
confirm_func=None, browse_reason=None):
"""
Helper function for launching a filechooser
@param parent: Parent window for the filechooser
@param dialog_name: String to use in the title bar of the filechooser.
@param config: vmmConfig used by calling class
@param conn: vmmConnection used by calling class
@param start_folder: Folder the filechooser is viewing at startup
@param _type: File extension to filter by (e.g. "iso", "png")
@param dialog_type: Maps to FileChooserDialog 'action'
@param confirm_func: Optional callback function if file is chosen.
@param browse_reason: The vmmConfig.CONFIG_DIR* reason we are browsing.
If set, this will override the 'folder' parameter with the gconf
value, and store the user chosen path.
"""
overwrite_confirm = False
@ -109,6 +117,9 @@ def browse_local(parent, dialog_name, start_folder=None, _type=None,
choose_button = gtk.STOCK_SAVE
overwrite_confirm = True
if browse_reason:
start_folder = config.get_default_directory(conn, browse_reason)
fcdialog = gtk.FileChooserDialog(dialog_name, parent,
dialog_type,
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
@ -142,10 +153,15 @@ def browse_local(parent, dialog_name, start_folder=None, _type=None,
if(response == gtk.RESPONSE_ACCEPT):
filename = fcdialog.get_filename()
fcdialog.destroy()
return filename
ret = filename
else:
fcdialog.destroy()
return None
ret = None
if ret and browse_reason and not ret.startwith("/dev"):
config.set_default_directory(os.path.dirname(ret), browse_reason)
return ret
def dup_conn(config, conn, libconn=None, return_conn_class=False):