mirror of
https://github.com/xcp-ng/xenadmin.git
synced 2024-12-29 23:30:10 +01:00
3c051654d6
- Suppress reporting of success and failure for sub-actions: The suppress history flag is set when the action is created and if is false (by default) the action is added to the history (the Events list). In order to suppress history for the subactions, we need change all actions used in Edit pages so their constructor can set the SuppressHistory flag and then use these constructors with suppressHistory = true on all the implementations of IEditPage.SaveSettings() where an action is created (then we need to remember to do the same everytime we introduce a new page and / or "save" action). Signed-off-by: Mihaela Stoica <mihaela.stoica@citrix.com>
341 lines
12 KiB
C#
341 lines
12 KiB
C#
/* Copyright (c) Citrix Systems Inc.
|
|
* All rights reserved.
|
|
*
|
|
* 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.ComponentModel;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
using XenAdmin.Actions;
|
|
using XenAdmin.Commands;
|
|
using XenAdmin.Controls;
|
|
using XenAdmin.Core;
|
|
using XenAdmin.SettingsPanels;
|
|
using XenAPI;
|
|
|
|
namespace XenAdmin.Wizards.GenericPages
|
|
{
|
|
// This design for this class is in NewVMGroupVMsPageBase: see notes there.
|
|
|
|
public class NewVMGroupVMsPage<T> : NewVMGroupVMsPageBase where T : XenObject<T>
|
|
{
|
|
private Pool _pool;
|
|
public Pool Pool
|
|
{
|
|
get { return _pool; }
|
|
set
|
|
{
|
|
_pool = value;
|
|
if (_pool != null)
|
|
label1.Text = string.Format(Helpers.IsPool(_pool.Connection) ? Messages.VMS_IN_POOL : Messages.VMS_IN_SERVER,
|
|
_pool.Name.Ellipsise(60));
|
|
label2.Text = VMGroup<T>.ChooseVMsPage_Rubric;
|
|
dataGridView1.Columns["ColumnCurrentGroup"].HeaderText = VMGroup<T>.ChooseVMsPage_CurrentGroup;
|
|
}
|
|
}
|
|
|
|
public NewVMGroupVMsPage()
|
|
{
|
|
SelectedVMs = new List<VM>();
|
|
dataGridView1.SortCompare += dataGridView1_SortCompare;
|
|
}
|
|
|
|
public override string Text
|
|
{
|
|
get { return VMGroup<T>.ChooseVMsPage_Text; }
|
|
}
|
|
|
|
public override string SubText
|
|
{
|
|
get { return labelCounterVMs.Text; }
|
|
}
|
|
|
|
public override string HelpID
|
|
{
|
|
get { return VMGroup<T>.ChooseVMsPage_HelpID; }
|
|
}
|
|
|
|
public override Image Image
|
|
{
|
|
get { return Properties.Resources._000_VM_h32bit_16; }
|
|
}
|
|
|
|
public override string PageTitle
|
|
{
|
|
get { return VMGroup<T>.ChooseVMsPage_Title; }
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
internal List<VM> SelectedVMs { get; set; }
|
|
|
|
public string GroupName { private get; set; }
|
|
|
|
public List<XenRef<VM>> SelectedVMsRefs
|
|
{
|
|
get { return SelectedVMs.ConvertAll<XenRef<VM>>(converter); }
|
|
}
|
|
|
|
private static XenRef<VM> converter(VM vm)
|
|
{
|
|
return new XenRef<VM>(vm.opaque_ref);
|
|
}
|
|
|
|
protected override void searchTextBox1_TextChanged(object sender, System.EventArgs e)
|
|
{
|
|
if (Pool != null)
|
|
{
|
|
var sortedColumn = dataGridView1.SortedColumn;
|
|
var sortOrder = dataGridView1.SortOrder;
|
|
|
|
dataGridView1.Rows.Clear();
|
|
foreach (var vm in Pool.Connection.Cache.VMs)
|
|
{
|
|
if (searchTextBox1.Matches(vm.Name) && vm.is_a_real_vm)
|
|
dataGridView1.Rows.Add(new VMDataGridViewRow(SelectedVMs.Contains(vm), vm));
|
|
}
|
|
|
|
if (sortOrder != SortOrder.None && sortedColumn != null)
|
|
dataGridView1.Sort(sortedColumn, (sortOrder == SortOrder.Ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending);
|
|
UpdateCounterLabelAndButtons();
|
|
}
|
|
}
|
|
|
|
private void UpdateCounterLabelAndButtons()
|
|
{
|
|
labelCounterVMs.Text = SelectedVMs.Count == 1 ? Messages.ONE_VM_SELECTED : string.Format(Messages.MOREONE_VM_SELECTED, SelectedVMs.Count);
|
|
buttonClearAll.Enabled = SelectedVMs.Count > 0;
|
|
buttonSelectAll.Enabled = SelectedVMs.Count < dataGridView1.RowCount;
|
|
}
|
|
|
|
// How to sort the VMs in the grid view: CA-69817
|
|
void dataGridView1_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
|
|
{
|
|
e.Handled = false;
|
|
|
|
bool sortByName = false;
|
|
|
|
if (e.Column == ColumnCheckBox)
|
|
{
|
|
// Sort by check mark first, then by name
|
|
int checked1 = (bool)e.CellValue1 ? 1 : 0;
|
|
int checked2 = (bool)e.CellValue2 ? 1 : 0;
|
|
if (checked1 != checked2)
|
|
{
|
|
e.SortResult = checked2 - checked1;
|
|
e.Handled = true;
|
|
}
|
|
else
|
|
sortByName = true;
|
|
}
|
|
|
|
if (e.Column == ColumnName || sortByName)
|
|
{
|
|
// In order to sort by name, we actually use the built-in VM sort.
|
|
// This ensures we use the correct name sorting, and gives a consistent tie-breaker.
|
|
VM vm1 = ((VMDataGridViewRow)dataGridView1.Rows[e.RowIndex1]).Vm;
|
|
VM vm2 = ((VMDataGridViewRow)dataGridView1.Rows[e.RowIndex2]).Vm;
|
|
e.SortResult = vm1.CompareTo(vm2);
|
|
e.Handled = true;
|
|
}
|
|
|
|
// For any other column, we fall off the end of this function with e.Handled still false,
|
|
// and let the framework handle it.
|
|
}
|
|
|
|
private class VMDataGridViewRow : DataGridViewRow
|
|
{
|
|
private DataGridViewCheckBoxCell _selectedCell = new DataGridViewCheckBoxCell();
|
|
private DataGridViewTextBoxCell _nameCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell _descriptionCell = new DataGridViewTextBoxCell();
|
|
private DataGridViewTextBoxCell _currentGroupCell = new DataGridViewTextBoxCell();
|
|
public readonly VM Vm;
|
|
public VMDataGridViewRow(bool selected, VM vm)
|
|
{
|
|
Vm = vm;
|
|
Cells.Add(_selectedCell);
|
|
Cells.Add(_nameCell);
|
|
Cells.Add(_descriptionCell);
|
|
Cells.Add(_currentGroupCell);
|
|
Refresh(selected);
|
|
}
|
|
|
|
void Refresh(bool selected)
|
|
{
|
|
_selectedCell.Value = selected;
|
|
_nameCell.Value = Vm.Name;
|
|
_descriptionCell.Value = Vm.Description;
|
|
T group = Vm.Connection.Resolve(VMGroup<T>.VmToGroup(Vm));
|
|
_currentGroupCell.Value = group == null ? Messages.NONE : group.Name;
|
|
}
|
|
}
|
|
|
|
public override void PageLoaded(PageLoadedDirection direction)
|
|
{
|
|
base.PageLoaded(direction);
|
|
RefreshTab(null);
|
|
}
|
|
|
|
private T _group = null;
|
|
private void RefreshTab(T group)
|
|
{
|
|
_group = group;
|
|
if (Pool != null)
|
|
{
|
|
dataGridView1.Rows.Clear();
|
|
foreach (var vm in Pool.Connection.Cache.VMs)
|
|
{
|
|
int index = 0;
|
|
if (vm.is_a_real_vm && vm.Show(Properties.Settings.Default.ShowHiddenVMs))
|
|
{
|
|
bool selected = group != null && VMGroup<T>.GroupToVMs(group).Contains(new XenRef<VM>(vm.opaque_ref));
|
|
index = dataGridView1.Rows.Add(new VMDataGridViewRow(selected, vm));
|
|
|
|
if (SelectedVMs.Contains(vm))
|
|
dataGridView1.Rows[index].Cells[0].Value = true;
|
|
else if (selected && !SelectedVMs.Contains(vm))
|
|
SelectedVMs.Add(vm);
|
|
}
|
|
}
|
|
|
|
dataGridView1.Sort(ColumnCheckBox, ListSortDirection.Ascending);
|
|
dataGridView1.AutoResizeColumns();
|
|
}
|
|
UpdateCounterLabelAndButtons();
|
|
}
|
|
|
|
protected override void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (e.ColumnIndex == 0 && e.RowIndex >= 0)
|
|
{
|
|
dataGridView1.Rows[e.RowIndex].Cells[0].Value = !(bool)dataGridView1.Rows[e.RowIndex].Cells[0].Value;
|
|
}
|
|
}
|
|
|
|
protected override void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
if (e.ColumnIndex != 0 || e.RowIndex < 0 && e.RowIndex >= dataGridView1.RowCount)
|
|
return;
|
|
|
|
var row = dataGridView1.Rows[e.RowIndex] as VMDataGridViewRow;
|
|
|
|
if (row != null)
|
|
{
|
|
if ((bool)row.Cells[0].Value)
|
|
{
|
|
if (!SelectedVMs.Contains(row.Vm))
|
|
SelectedVMs.Add(row.Vm);
|
|
}
|
|
else
|
|
SelectedVMs.Remove(row.Vm);
|
|
}
|
|
|
|
UpdateCounterLabelAndButtons();
|
|
}
|
|
|
|
protected override void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
|
|
{
|
|
if ((e.Row.State & DataGridViewElementStates.Selected) != 0)
|
|
e.Row.Selected = false;
|
|
}
|
|
|
|
public override void PageLeave(PageLoadedDirection direction, ref bool cancel)
|
|
{
|
|
if (direction == PageLoadedDirection.Back)
|
|
return;
|
|
|
|
if (!userAcceptsWarning())
|
|
cancel = true;
|
|
|
|
base.PageLeave(direction, ref cancel);
|
|
}
|
|
|
|
private bool userAcceptsWarning()
|
|
{
|
|
string groupName = (_group != null) ? _group.Name : GroupName;
|
|
return AssignGroupToolStripMenuItem<T>.AssignGroupToVMCommand.ChangesOK(SelectedVMs, _group, groupName);
|
|
}
|
|
|
|
protected override void buttonClearAll_Click(object sender, EventArgs e)
|
|
{
|
|
foreach (DataGridViewRow dataGridViewRow in dataGridView1.Rows)
|
|
{
|
|
dataGridViewRow.Cells[0].Value = false;
|
|
}
|
|
}
|
|
|
|
protected override void buttonSelectAll_Click(object sender, EventArgs e)
|
|
{
|
|
foreach (DataGridViewRow dataGridViewRow in dataGridView1.Rows)
|
|
{
|
|
dataGridViewRow.Cells[0].Value = true;
|
|
}
|
|
}
|
|
|
|
#region IEditPage implementation
|
|
public override AsyncAction SaveSettings()
|
|
{
|
|
return VMGroup<T>.AssignVMsToGroupAction(_clone, SelectedVMsRefs, true);
|
|
}
|
|
|
|
private T _clone;
|
|
public override void SetXenObjects(IXenObject orig, IXenObject clone)
|
|
{
|
|
_clone = (T)clone;
|
|
Pool = Helpers.GetPoolOfOne(_clone.Connection);
|
|
RefreshTab(_clone);
|
|
}
|
|
|
|
public override bool ValidToSave
|
|
{
|
|
get { return userAcceptsWarning(); }
|
|
}
|
|
|
|
public override void ShowLocalValidationMessages()
|
|
{
|
|
}
|
|
|
|
public override void Cleanup()
|
|
{
|
|
dataGridView1.Rows.Clear();
|
|
}
|
|
|
|
public override bool HasChanged
|
|
{
|
|
get
|
|
{
|
|
return (!Helpers.CompareLists(SelectedVMsRefs, VMGroup<T>.GroupToVMs(_clone)));
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|