mirror of
https://github.com/virt-manager/virt-manager.git
synced 2025-01-11 05:17:59 +03:00
Add libvirt storage aware file browser.
Hook it up to the New VM and Add Hardware wizards, all storage browsing.
This commit is contained in:
parent
c83113e79b
commit
b1f69cffd8
@ -31,6 +31,7 @@ import virtManager.util as vmmutil
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
from virtManager.error import vmmErrorDialog
|
||||
from virtManager.createmeter import vmmCreateMeter
|
||||
from virtManager.storagebrowse import vmmStorageBrowser
|
||||
|
||||
VM_STORAGE_PARTITION = 1
|
||||
VM_STORAGE_FILE = 2
|
||||
@ -64,6 +65,9 @@ class vmmAddHardware(gobject.GObject):
|
||||
self.install_error = ""
|
||||
self.install_details = ""
|
||||
|
||||
self.storage_browser = None
|
||||
self._browse_cb_id = None
|
||||
|
||||
self.topwin.hide()
|
||||
self.window.signal_autoconnect({
|
||||
"on_create_pages_switch_page" : self.page_changed,
|
||||
@ -401,8 +405,6 @@ class vmmAddHardware(gobject.GObject):
|
||||
self.populate_target_device_model(target.get_model())
|
||||
target.set_active(0)
|
||||
|
||||
self.window.get_widget("storage-partition-address-browse").set_sensitive(not remote)
|
||||
self.window.get_widget("storage-file-address-browse").set_sensitive(not remote)
|
||||
|
||||
elif page_number == PAGE_NETWORK:
|
||||
netmodel = self.window.get_widget("net-model")
|
||||
@ -631,25 +633,47 @@ class vmmAddHardware(gobject.GObject):
|
||||
|
||||
|
||||
def browse_storage_partition_address(self, src, ignore=None):
|
||||
part = self._browse_file(_("Locate Storage Partition"), "/dev")
|
||||
textent = self.window.get_widget("storage-partition-address")
|
||||
part = self._browse_file(_("Locate Storage Partition"), textent,
|
||||
"/dev")
|
||||
if part != None:
|
||||
self.window.get_widget("storage-partition-address").set_text(part)
|
||||
textent.set_text(part)
|
||||
|
||||
def browse_storage_file_address(self, src, ignore=None):
|
||||
textent = self.window.get_widget("storage-file-address")
|
||||
folder = self.config.get_default_image_dir(self.vm.get_connection())
|
||||
filename = self._browse_file(_("Locate or Create New Storage File"), \
|
||||
folder=folder, confirm_overwrite=True)
|
||||
filename = self._browse_file(_("Locate or Create New Storage File"),
|
||||
textent, folder=folder,
|
||||
confirm_overwrite=True)
|
||||
if filename != None:
|
||||
self.window.get_widget("storage-file-address").set_text(filename)
|
||||
textent.set_text(filename)
|
||||
|
||||
def _browse_file(self, dialog_name, folder=None, _type=None,
|
||||
def _browse_file(self, dialog_name, textent, folder=None,
|
||||
confirm_overwrite=False):
|
||||
|
||||
confirm_func = None
|
||||
if confirm_overwrite:
|
||||
confirm_func = self.confirm_overwrite_callback
|
||||
return vmmutil.browse_local(self.topwin, dialog_name, folder, _type,
|
||||
confirm_func=confirm_func)
|
||||
|
||||
if folder and not os.access(folder, os.R_OK):
|
||||
folder = None
|
||||
|
||||
def set_storage_cb(src, path):
|
||||
if path:
|
||||
textent.set_text(path)
|
||||
|
||||
conn = self.vm.get_connection()
|
||||
if self.storage_browser == None:
|
||||
self.storage_browser = vmmStorageBrowser(self.config, conn)
|
||||
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, }
|
||||
self.storage_browser.show(conn)
|
||||
return None
|
||||
|
||||
def toggle_storage_size(self, ignore1=None, ignore2=None):
|
||||
filename = self.get_config_disk_image()
|
||||
|
@ -36,6 +36,7 @@ from virtManager.error import vmmErrorDialog
|
||||
from virtManager.asyncjob import vmmAsyncJob
|
||||
from virtManager.createmeter import vmmCreateMeter
|
||||
from virtManager.opticalhelper import vmmOpticalDriveHelper
|
||||
from virtManager.storagebrowse import vmmStorageBrowser
|
||||
|
||||
OS_GENERIC = "generic"
|
||||
|
||||
@ -381,7 +382,6 @@ class vmmCreate(gobject.GObject):
|
||||
|
||||
# Install local
|
||||
self.window.get_widget("install-local-cdrom-box").set_sensitive(is_local)
|
||||
self.window.get_widget("install-local-browse").set_sensitive(is_local)
|
||||
if not is_local:
|
||||
self.window.get_widget("install-local-iso").set_active(True)
|
||||
|
||||
@ -434,7 +434,6 @@ class vmmCreate(gobject.GObject):
|
||||
|
||||
use_storage = self.window.get_widget("config-storage-select")
|
||||
storage_area = self.window.get_widget("config-storage-area")
|
||||
self.window.get_widget("config-storage-browse").set_sensitive(is_local)
|
||||
|
||||
storage_area.set_sensitive(have_storage)
|
||||
if not have_storage:
|
||||
@ -971,7 +970,7 @@ class vmmCreate(gobject.GObject):
|
||||
nodetect_label.show()
|
||||
|
||||
def browse_iso(self, ignore1=None, ignore2=None):
|
||||
f = self._browse_file(_("Locate ISO Image"))
|
||||
f = self._browse_file(_("Locate ISO Image"), is_media=True)
|
||||
if f != None:
|
||||
self.window.get_widget("install-local-entry").set_text(f)
|
||||
self.window.get_widget("install-local-entry").activate()
|
||||
@ -980,7 +979,7 @@ class vmmCreate(gobject.GObject):
|
||||
self.window.get_widget("config-storage-box").set_sensitive(src.get_active())
|
||||
|
||||
def browse_storage(self, ignore1):
|
||||
f = self._browse_file(_("Locate existing storage."))
|
||||
f = self._browse_file(_("Locate existing storage"))
|
||||
if f != None:
|
||||
self.window.get_widget("config-storage-entry").set_text(f)
|
||||
|
||||
@ -992,7 +991,12 @@ class vmmCreate(gobject.GObject):
|
||||
self.window.get_widget("config-macaddr").set_sensitive(src.get_active())
|
||||
|
||||
def set_storage_path(self, src, path):
|
||||
self.window.get_widget("config-storage-entry").set_text(path)
|
||||
notebook = self.window.get_widget("create-pages")
|
||||
curpage = notebook.get_current_page()
|
||||
if curpage == PAGE_INSTALL:
|
||||
self.window.get_widget("install-local-entry").set_text(path)
|
||||
elif curpage == PAGE_STORAGE:
|
||||
self.window.get_widget("config-storage-entry").set_text(path)
|
||||
|
||||
# Navigation methods
|
||||
def set_install_page(self):
|
||||
@ -1624,14 +1628,20 @@ class vmmCreate(gobject.GObject):
|
||||
logging.exception("Error detecting distro.")
|
||||
self.detectedDistro = (None, None)
|
||||
|
||||
def _browse_file(self, dialog_name, folder=None, _type=None):
|
||||
def _browse_file(self, dialog_name, folder=None, is_media=False):
|
||||
|
||||
if self.conn.is_remote() or True:
|
||||
# FIXME: This will eventually call a special storage browser
|
||||
pass
|
||||
if self.conn.is_remote() or not is_media:
|
||||
if self.storage_browser == None:
|
||||
self.storage_browser = vmmStorageBrowser(self.config,
|
||||
self.conn)
|
||||
self.storage_browser.connect("storage-browse-finish",
|
||||
self.set_storage_path)
|
||||
self.storage_browser.local_args = { "dialog_name": dialog_name,
|
||||
"start_folder": folder}
|
||||
self.storage_browser.show(self.conn)
|
||||
return None
|
||||
|
||||
# FIXME: Pass local browse fun to storage_browser
|
||||
return util.browse_local(self.topwin, dialog_name, folder, _type)
|
||||
return util.browse_local(self.topwin, dialog_name, folder)
|
||||
|
||||
def show_help(self, ignore):
|
||||
# No help available yet.
|
||||
|
282
src/virtManager/storagebrowse.py
Normal file
282
src/virtManager/storagebrowse.py
Normal file
@ -0,0 +1,282 @@
|
||||
#
|
||||
# Copyright (C) 2009 Red Hat, Inc.
|
||||
# Copyright (C) 2009 Cole Robinson <crobinso@redhat.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA.
|
||||
#
|
||||
|
||||
import gobject
|
||||
import gtk.glade
|
||||
|
||||
import traceback
|
||||
import logging
|
||||
|
||||
import virtinst
|
||||
|
||||
import virtManager.host
|
||||
import virtManager.util as util
|
||||
from virtManager.createvol import vmmCreateVolume
|
||||
from virtManager.error import vmmErrorDialog
|
||||
|
||||
class vmmStorageBrowser(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
#"vol-created": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, [])
|
||||
"storage-browse-finish": (gobject.SIGNAL_RUN_FIRST,
|
||||
gobject.TYPE_NONE, [str]),
|
||||
}
|
||||
|
||||
def __init__(self, config, conn):
|
||||
self.__gobject_init__()
|
||||
self.window = gtk.glade.XML(config.get_glade_dir() + \
|
||||
"/vmm-storage-browse.glade",
|
||||
"vmm-storage-browse",
|
||||
domain="virt-manager")
|
||||
self.config = config
|
||||
self.conn = conn
|
||||
self.conn_signal_ids = []
|
||||
|
||||
self.topwin = self.window.get_widget("vmm-storage-browse")
|
||||
self.err = vmmErrorDialog(self.topwin,
|
||||
0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
|
||||
_("Unexpected Error"),
|
||||
_("An unexpected error occurred"))
|
||||
self.topwin.hide()
|
||||
|
||||
# Add Volume wizard
|
||||
self.addvol = None
|
||||
|
||||
# Arguments to pass to util.browse_local for local storage
|
||||
self.local_args = {"dialog_name": _("Choose local storage")}
|
||||
|
||||
self.window.signal_autoconnect({
|
||||
"on_vmm_storage_browse_delete_event" : self.close,
|
||||
"on_browse_cancel_clicked" : self.close,
|
||||
"on_browse_local_clicked" : self.browse_local,
|
||||
"on_new_volume_clicked" : self.new_volume,
|
||||
"on_choose_volume_clicked" : self.finish,
|
||||
"on_vol_list_row_activated" : self.finish,
|
||||
})
|
||||
|
||||
self.set_initial_state()
|
||||
|
||||
def show(self, conn=None):
|
||||
self.reset_state(conn)
|
||||
self.topwin.show()
|
||||
self.topwin.present()
|
||||
|
||||
def close(self, ignore1=None, ignore2=None):
|
||||
self.topwin.hide()
|
||||
if self.addvol:
|
||||
self.addvol.close()
|
||||
return 1
|
||||
|
||||
def set_initial_state(self):
|
||||
pool_list = self.window.get_widget("pool-list")
|
||||
virtManager.host.init_pool_list(pool_list, self.pool_selected)
|
||||
|
||||
# (Key, Name, Cap, Format, Used By)
|
||||
vol_list = self.window.get_widget("vol-list")
|
||||
volListModel = gtk.ListStore(str, str, str, str, str)
|
||||
vol_list.set_model(volListModel)
|
||||
|
||||
vol_list.get_selection().connect("changed", self.vol_selected)
|
||||
volCol = gtk.TreeViewColumn(_("Name"))
|
||||
vol_txt1 = gtk.CellRendererText()
|
||||
volCol.pack_start(vol_txt1, True)
|
||||
volCol.add_attribute(vol_txt1, 'text', 1)
|
||||
volCol.set_sort_column_id(1)
|
||||
vol_list.append_column(volCol)
|
||||
|
||||
volSizeCol = gtk.TreeViewColumn(_("Size"))
|
||||
vol_txt2 = gtk.CellRendererText()
|
||||
volSizeCol.pack_start(vol_txt2, False)
|
||||
volSizeCol.add_attribute(vol_txt2, 'text', 2)
|
||||
volSizeCol.set_sort_column_id(2)
|
||||
vol_list.append_column(volSizeCol)
|
||||
|
||||
volPathCol = gtk.TreeViewColumn(_("Format"))
|
||||
vol_txt4 = gtk.CellRendererText()
|
||||
volPathCol.pack_start(vol_txt4, False)
|
||||
volPathCol.add_attribute(vol_txt4, 'text', 3)
|
||||
volPathCol.set_sort_column_id(3)
|
||||
vol_list.append_column(volPathCol)
|
||||
|
||||
volUseCol = gtk.TreeViewColumn(_("Used By"))
|
||||
vol_txt5 = gtk.CellRendererText()
|
||||
volUseCol.pack_start(vol_txt5, False)
|
||||
volUseCol.add_attribute(vol_txt5, 'text', 4)
|
||||
volUseCol.set_sort_column_id(4)
|
||||
vol_list.append_column(volUseCol)
|
||||
|
||||
volListModel.set_sort_column_id(1, gtk.SORT_ASCENDING)
|
||||
|
||||
|
||||
def reset_state(self, conn=None):
|
||||
if conn and conn != self.conn:
|
||||
for i in self.conn_signal_ids:
|
||||
self.conn.disconnect(i)
|
||||
self.conn = conn
|
||||
|
||||
pool_list = self.window.get_widget("pool-list")
|
||||
virtManager.host.populate_storage_pools(pool_list, self.conn)
|
||||
|
||||
ids = []
|
||||
ids.append(self.conn.connect("pool-added",
|
||||
self.repopulate_storage_pools))
|
||||
ids.append(self.conn.connect("pool-removed",
|
||||
self.repopulate_storage_pools))
|
||||
ids.append(self.conn.connect("pool-started",
|
||||
self.refresh_storage_pool))
|
||||
ids.append(self.conn.connect("pool-stopped",
|
||||
self.refresh_storage_pool))
|
||||
self.conn_signal_ids = ids
|
||||
|
||||
# FIXME: Need a connection specific "vol-added" function?
|
||||
# Won't be able to pick that change up from outside?
|
||||
|
||||
# Manually trigger vol_selected, so buttons are in the correct state
|
||||
self.vol_selected()
|
||||
|
||||
tooltip = None
|
||||
is_remote = self.conn.is_remote()
|
||||
self.window.get_widget("browse-local").set_sensitive(not is_remote)
|
||||
if is_remote:
|
||||
tooltip = _("Cannot use local storage on remote connection.")
|
||||
util.tooltip_wrapper(self.window.get_widget("browse-local"),
|
||||
tooltip)
|
||||
|
||||
# Convenience helpers
|
||||
def current_pool(self):
|
||||
sel = self.window.get_widget("pool-list").get_selection()
|
||||
active = sel.get_selected()
|
||||
if active[1] != None:
|
||||
curruuid = active[0].get_value(active[1], 0)
|
||||
return self.conn.get_pool(curruuid)
|
||||
return None
|
||||
|
||||
def current_vol(self):
|
||||
pool = self.current_pool()
|
||||
if not pool:
|
||||
return None
|
||||
sel = self.window.get_widget("vol-list").get_selection()
|
||||
active = sel.get_selected()
|
||||
if active[1] != None:
|
||||
curruuid = active[0].get_value(active[1], 0)
|
||||
return pool.get_volume(curruuid)
|
||||
return None
|
||||
|
||||
def refresh_storage_pool(self, src, uri, uuid):
|
||||
pool_list = self.window.get_widget("pool-list")
|
||||
virtManager.host.refresh_pool_in_list(pool_list, self.conn, uuid)
|
||||
curpool = self.current_pool()
|
||||
if curpool.uuid != uuid:
|
||||
return
|
||||
|
||||
# Currently selected pool changed state: force a 'pool_selected' to
|
||||
# update vol list
|
||||
self.pool_selected(self.window.get_widget("pool-list").get_selection())
|
||||
|
||||
def repopulate_storage_pools(self, src, uri, uuid):
|
||||
pool_list = self.window.get_widget("pool-list")
|
||||
virtManager.host.populate_storage_pools(pool_list, self.conn)
|
||||
|
||||
|
||||
# Listeners
|
||||
|
||||
def pool_selected(self, src):
|
||||
pool = self.current_pool()
|
||||
self.window.get_widget("new-volume").set_sensitive(bool(pool))
|
||||
if pool:
|
||||
self.window.get_widget("new-volume").set_sensitive(pool.is_active())
|
||||
self.populate_storage_volumes()
|
||||
|
||||
def vol_selected(self, ignore=None):
|
||||
vol = self.current_vol()
|
||||
self.window.get_widget("choose-volume").set_sensitive(bool(vol))
|
||||
|
||||
def refresh_current_pool(self, ignore):
|
||||
cp = self.current_pool()
|
||||
if cp is None:
|
||||
return
|
||||
cp.refresh()
|
||||
self.refresh_storage_pool(None, None, cp.get_uuid())
|
||||
|
||||
def new_volume(self, src):
|
||||
pool = self.current_pool()
|
||||
if pool is None:
|
||||
return
|
||||
|
||||
try:
|
||||
if self.addvol is None:
|
||||
self.addvol = vmmCreateVolume(self.config, self.conn, pool)
|
||||
self.addvol.connect("vol-created", self.refresh_current_pool)
|
||||
else:
|
||||
self.addvol.set_parent_pool(pool)
|
||||
self.addvol.set_modal(True)
|
||||
self.addvol.show()
|
||||
except Exception, e:
|
||||
self.show_err(_("Error launching volume wizard: %s") % str(e),
|
||||
"".join(traceback.format_exc()))
|
||||
|
||||
def browse_local(self, src):
|
||||
filename = util.browse_local(parent=self.topwin, **self.local_args)
|
||||
if filename:
|
||||
self._do_finish(path=filename)
|
||||
|
||||
def finish(self, ignore=None, ignore1=None, ignore2=None):
|
||||
self._do_finish()
|
||||
|
||||
def _do_finish(self, path=None):
|
||||
if not path:
|
||||
path = self.current_vol().get_path()
|
||||
self.emit("storage-browse-finish", path)
|
||||
self.close()
|
||||
|
||||
# Do stuff!
|
||||
def populate_storage_volumes(self):
|
||||
model = self.window.get_widget("vol-list").get_model()
|
||||
model.clear()
|
||||
|
||||
pool = self.current_pool()
|
||||
if not pool:
|
||||
return
|
||||
|
||||
vols = pool.get_volumes()
|
||||
for key in vols.keys():
|
||||
vol = vols[key]
|
||||
|
||||
path = vol.get_target_path()
|
||||
namestr = None
|
||||
try:
|
||||
if path:
|
||||
disk = virtinst.VirtualDisk(conn=self.conn.vmm, path=path,
|
||||
size=.001)
|
||||
names = disk.is_conflict_disk(self.conn.vmm,
|
||||
return_names=True)
|
||||
namestr = ", ".join(names)
|
||||
if not namestr:
|
||||
namestr = None
|
||||
except:
|
||||
logging.exception("Failed to determine if storage volume in "
|
||||
"use.")
|
||||
|
||||
model.append([key, vol.get_name(), vol.get_pretty_capacity(),
|
||||
vol.get_format() or "", namestr])
|
||||
|
||||
def show_err(self, info, details):
|
||||
self.show_err(info, details, async=False)
|
||||
|
||||
gobject.type_register(vmmStorageBrowser)
|
@ -31,6 +31,8 @@ DEFAULT_POOL_PATH = "/var/lib/libvirt/images"
|
||||
|
||||
def build_default_pool(conn):
|
||||
"""Helper to build the 'default' storage pool"""
|
||||
# FIXME: This should use config.get_default_image_path ?
|
||||
|
||||
if not virtinst.util.is_storage_capable(conn):
|
||||
# VirtualDisk will raise an error for us
|
||||
return
|
||||
|
241
src/vmm-storage-browse.glade
Normal file
241
src/vmm-storage-browse.glade
Normal file
@ -0,0 +1,241 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
|
||||
<!--Generated with glade3 3.4.5 on Sat Mar 7 19:17:19 2009 -->
|
||||
<glade-interface>
|
||||
<widget class="GtkWindow" id="vmm-storage-browse">
|
||||
<property name="border_width">10</property>
|
||||
<property name="title" translatable="yes">Choose Volume</property>
|
||||
<property name="modal">True</property>
|
||||
<property name="default_width">750</property>
|
||||
<property name="default_height">500</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<signal name="delete_event" handler="on_vmm_storage_browse_delete_event"/>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">15</property>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="pool-list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">3</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="browse-local">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_browse_local_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment4">
|
||||
<property name="visible">True</property>
|
||||
<property name="top_padding">2</property>
|
||||
<property name="bottom_padding">2</property>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Browse Local</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">browse-local</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment2">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow2">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="vol-list">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_clickable">True</property>
|
||||
<signal name="row_activated" handler="on_vol_list_row_activated"/>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<widget class="GtkButton" id="new-volume">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_new_volume_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox6">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">3</property>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-new</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1234">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_New Volume</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">new-volume</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="browse-cancel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="label" translatable="yes">gtk-cancel</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_browse_cancel_clicked"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkButton" id="choose-volume">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="response_id">0</property>
|
||||
<signal name="clicked" handler="on_choose_volume_clicked"/>
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="spacing">4</property>
|
||||
<child>
|
||||
<widget class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-open</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Choose _Volume</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="mnemonic_widget">choose-volume</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
@ -21,6 +21,7 @@ EMIT_VAR="has no 'emit' member"
|
||||
ERROR_VBOX="vmmErrorDialog.__init__.*Class 'vbox' has no 'pack_start' member"
|
||||
EXCEPTHOOK="no '__excepthook__' member"
|
||||
CONNECT_VAR="no 'connect' member"
|
||||
DISCONNECT_VAR="no 'disconnect' member"
|
||||
|
||||
# os._exit is needed for forked processes.
|
||||
OS_EXIT="protected member _exit of a client class"
|
||||
@ -84,6 +85,7 @@ pylint --ignore=IPy.py $FILES \
|
||||
-ve "$GOBJECT_VAR" \
|
||||
-ve "$EMIT_VAR" \
|
||||
-ve "$CONNECT_VAR" \
|
||||
-ve "$DISCONNECT_VAR" \
|
||||
-ve "$GETTEXT_VAR" \
|
||||
-ve "$OS_EXIT" \
|
||||
-ve "$BUILTIN_TYPE" \
|
||||
|
Loading…
Reference in New Issue
Block a user