xenadmin/XenAdmin/TabPages/UsbPage.cs

306 lines
11 KiB
C#
Raw Normal View History

/* Copyright (c) Cloud Software Group, Inc.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using XenAdmin.Actions;
using XenAdmin.Dialogs;
using XenAdmin.Controls.DataGridViewEx;
using XenAPI;
namespace XenAdmin.TabPages
{
public partial class UsbPage : BaseTabPage
{
private Host _host;
public UsbPage()
{
InitializeComponent();
Text = Messages.USB;
labelGridTitle.Text = Messages.USB_DEVICES;
buttonPassthrough.Enabled = false;
buttonPassthrough.Text = Messages.USBLIST_ENABLE_PASSTHROUGH_HOTKEY;
}
public override string HelpID => "TabPageUSB";
public IXenObject XenObject
{
get
{
Program.AssertOnEventThread();
return _host;
}
set
{
Program.AssertOnEventThread();
UnregisterHandlers();
_host = value as Host;
if (_host != null)
{
_host.PropertyChanged += Host_PropertyChanged;
_host.Connection.Cache.RegisterBatchCollectionChanged<PUSB>(UsbCollectionChanged);
}
BuildList();
}
}
public bool InBuildList = false;
private void BuildList()
{
Program.AssertOnEventThread();
if (InBuildList)
return;
InBuildList = true;
try
{
if (_host == null || _host.Locked)
return;
if (!_host.Connection.CacheIsPopulated)
return;
dataGridViewUsbList.SuspendLayout();
dataGridViewUsbList.Rows.Clear();
List<PUSB> pusbs = _host.Connection.ResolveAll(_host.PUSBs);
foreach (PUSB pusb in pusbs)
{
dataGridViewUsbList.Rows.Add(new HostUsbRow(pusb));
}
}
finally
{
if (dataGridViewUsbList.SortedColumn != null)
{
dataGridViewUsbList.Sort(
dataGridViewUsbList.SortedColumn,
dataGridViewUsbList.SortOrder == SortOrder.Ascending
? ListSortDirection.Ascending : ListSortDirection.Descending);
}
dataGridViewUsbList.ResumeLayout();
InBuildList = false;
}
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
}
public override void PageHidden()
{
UnregisterHandlers();
base.PageHidden();
}
void Host_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
RefreshAllItems();
}
void UsbCollectionChanged(object sender, EventArgs e)
{
BuildList();
}
private void RefreshAllItems()
{
foreach (DataGridViewExRow row in dataGridViewUsbList.Rows)
{
var usbRow = row as HostUsbRow;
if (usbRow != null)
usbRow.UpdateDetails();
}
}
internal void UnregisterHandlers()
{
if (_host != null)
{
_host.PropertyChanged -= Host_PropertyChanged;
_host.Connection.Cache.DeregisterBatchCollectionChanged<PUSB>(UsbCollectionChanged);
}
foreach (DataGridViewExRow row in dataGridViewUsbList.Rows)
{
var usbRow = row as HostUsbRow;
if (usbRow != null)
usbRow.DeregisterEvents();
}
}
private HostUsbRow selectedRow = null;
private void dataGridViewUsbList_SelectionChanged(object sender, EventArgs e)
{
selectedRow = null;
if (dataGridViewUsbList.SelectedRows.Count > 0)
selectedRow = (HostUsbRow)dataGridViewUsbList.SelectedRows[0];
if (selectedRow == null)
{
// When none item selected, disable the button and show
// "Enable Passthrough" on the button for better experience.
buttonPassthrough.Text = Messages.USBLIST_ENABLE_PASSTHROUGH_HOTKEY;
buttonPassthrough.Enabled = false;
}
else if (selectedRow.Pusb.passthrough_enabled)
{
// Selected item has been passthrough enabled, set the availability of the button
// as per whether the device has been attached or not.
PUSB pusb = selectedRow.Pusb;
USB_group usbGroup = pusb.Connection.Resolve(pusb.USB_group);
bool attached = (usbGroup != null) && (usbGroup.VUSBs != null) && (usbGroup.VUSBs.Count > 0);
buttonPassthrough.Text = Messages.USBLIST_DISABLE_PASSTHROUGH_HOTKEY;
buttonPassthrough.Enabled = !attached;
}
else
{
// Selected item has not been passthrough enabled.
buttonPassthrough.Text = Messages.USBLIST_ENABLE_PASSTHROUGH_HOTKEY;
buttonPassthrough.Enabled = true;
}
}
private void buttonPassthrough_Click(object sender, EventArgs e)
{
if (selectedRow == null)
return;
var pusb = selectedRow.Pusb;
var message = pusb.passthrough_enabled
? Messages.DIALOG_USB_USAGE_DISABLE_PASSTHROUGH
: Messages.DIALOG_USB_USAGE_ENABLE_PASSTHROUGH;
var yesText = pusb.passthrough_enabled
? Messages.DIALOG_USB_USAGE_OKBUTTON_DISABLE
: Messages.DIALOG_USB_USAGE_OKBUTTON_ENABLE;
using (var dialog = new WarningDialog(message,
new ThreeButtonDialog.TBDButton(yesText, DialogResult.Yes, ThreeButtonDialog.ButtonType.ACCEPT, true),
ThreeButtonDialog.ButtonNo))
{
if (dialog.ShowDialog(this) == DialogResult.Yes)
new SetUsbPassthroughAction(pusb, !pusb.passthrough_enabled).RunAsync();
}
}
private class HostUsbRow : DataGridViewExRow
{
private PUSB _pusb;
private VM _vm;
private DataGridViewTextBoxCell locationCell = new DataGridViewTextBoxCell();
private DataGridViewTextBoxCell descriptionCell = new DataGridViewTextBoxCell();
private DataGridViewTextBoxCell passthroughCell = new DataGridViewTextBoxCell();
private DataGridViewTextBoxCell vmCell = new DataGridViewTextBoxCell();
public HostUsbRow(PUSB pusb)
{
_pusb = pusb;
SetVm();
_pusb.PropertyChanged += Pusb_PropertyChanged;
Cells.AddRange(locationCell,
descriptionCell,
passthroughCell,
vmCell);
UpdateDetails();
}
private void SetVm()
{
if (_pusb != null)
{
USB_group usbgroup = _pusb.Connection.Resolve(_pusb.USB_group);
VUSB vusb = (usbgroup != null && usbgroup.VUSBs != null && usbgroup.VUSBs.Count > 0) ? _pusb.Connection.Resolve(usbgroup.VUSBs[0]) : null;
_vm = vusb == null ? null : _pusb.Connection.Resolve(vusb.VM);
if (_vm != null)
_vm.PropertyChanged += Vm_PropertyChanged;
}
}
public PUSB Pusb
{
get { return _pusb; }
}
public void UpdateDetails()
{
locationCell.Value = _pusb.path;
descriptionCell.Value = _pusb.Description();
passthroughCell.Value = _pusb.passthrough_enabled ? Messages.ENABLED : Messages.DISABLED;
vmCell.Value = _vm == null ? "" : _vm.name_label;
}
public void DeregisterEvents()
{
_pusb.PropertyChanged -= Pusb_PropertyChanged;
if (_vm != null)
_vm.PropertyChanged -= Vm_PropertyChanged;
}
private void Pusb_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "attached")
{
if (_vm != null) // Remove PropertyChanged handler for old VM
_vm.PropertyChanged -= Vm_PropertyChanged;
SetVm();
}
UpdateDetails();
}
private void Vm_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "name_label")
UpdateDetails();
}
}
}
}