Merge branch 'master' of git://hg.uk.xensource.com/carbon/trunk/xenadmin

This commit is contained in:
Gabor Apati-Nagy 2013-11-19 15:52:12 +00:00
commit 8c9502e4ba
10 changed files with 234 additions and 83 deletions

View File

@ -53,6 +53,7 @@ namespace XenAdmin.Controls.MainWindowControls
}
private NavigationMode currentMode;
private NotificationsSubMode lastNotificationsMode = NotificationsSubMode.Alerts;
#region Events
@ -157,10 +158,10 @@ namespace XenAdmin.Controls.MainWindowControls
#endregion
public void UpdateNotificationsButton()
public void UpdateNotificationsButton(NotificationsSubMode mode, int entries)
{
buttonNotifyBig.Text = string.Format("Notifications ({0})", Alert.NonDismissingAlertCount);
notificationsView.UpdateEntries(NotificationsSubMode.Alerts, Alert.NonDismissingAlertCount);
notificationsView.UpdateEntries(mode, entries);
buttonNotifyBig.Text = string.Format("Notifications ({0})", notificationsView.GetTotalEntries());
}
public void XenConnectionCollectionChanged(CollectionChangeEventArgs e)
@ -203,12 +204,20 @@ namespace XenAdmin.Controls.MainWindowControls
navigationView.MajorChange(() => navigationView.SaveAndRestoreTreeViewFocus(f));
}
public void SwitchToNotificationsView(NotificationsSubMode subMode)
public void SwitchToInfrastructureMode()
{
if (!buttonInfraBig.Checked)
buttonInfraBig.Checked = true;
}
private void SwitchToNotificationsView(NotificationsSubMode subMode)
{
//check the button if switching has been requested programmatically
if (!buttonNotifyBig.Checked)
buttonNotifyBig.Checked = true;
//show the notificationsView first and then hide the navigationView
//to avoid instantaneous appearance of empty panels
notificationsView.Visible = true;
notificationsView.SelectNotificationsSubMode(subMode);
navigationView.Visible = false;
@ -263,19 +272,24 @@ namespace XenAdmin.Controls.MainWindowControls
{
if (currentMode == NavigationMode.Notifications)
{
SwitchToNotificationsView(NotificationsSubMode.Alerts);
//restore the last selected view
SwitchToNotificationsView(lastNotificationsMode);
}
else
{
notificationsView.Visible = false;
//show the navigationView first and then hide the notificationsView
//to avoid instantaneous appearance of empty panels
navigationView.Visible = true;
notificationsView.Visible = false;
navigationView.CurrentSearch = Search;
navigationView.NavigationMode = currentMode;
navigationView.ResetSeachBox();
navigationView.RequestRefreshTreeView();
navigationView.FocusTreeView();
navigationView.SelectObject(null, false);
if (navigationView.SelectionManager.Selection.Count < 1)
navigationView.SelectObject(null, false);
}
if (NavigationModeChanged != null)
@ -371,6 +385,8 @@ namespace XenAdmin.Controls.MainWindowControls
private void notificationsView_NotificationsSubModeChanged(NotificationsSubModeItem subModeItem)
{
lastNotificationsMode = subModeItem.SubMode;
if (NotificationsSubModeChanged != null)
NotificationsSubModeChanged(subModeItem);
}

View File

@ -54,6 +54,19 @@ namespace XenAdmin.Controls.MainWindowControls
Items.Add(new NotificationsSubModeItem(NotificationsSubMode.Events));
}
public int GetTotalEntries()
{
int total = 0;
foreach (var item in Items)
{
var subModeItem = item as NotificationsSubModeItem;
if (subModeItem != null)
total += subModeItem.UnreadEntries;
}
return total;
}
public void UpdateEntries(NotificationsSubMode subMode, int entries)
{
foreach (var item in Items)
@ -78,7 +91,12 @@ namespace XenAdmin.Controls.MainWindowControls
if (subModeItem != null && subModeItem.SubMode == subMode)
{
var lastSelected = SelectedItem;
SelectedItem = item;
if (lastSelected == SelectedItem)
OnSelectedIndexChanged(EventArgs.Empty);
break;
}
}
@ -150,45 +168,52 @@ namespace XenAdmin.Controls.MainWindowControls
public Image Image
{
get
{
switch (SubMode)
{
case NotificationsSubMode.Alerts:
return Properties.Resources._000_Alert2_h32bit_16;
case NotificationsSubMode.Updates:
return Properties.Resources.tempUpdates;
case NotificationsSubMode.Events:
return UnreadEntries == 0
? Properties.Resources._000_date_h32bit_16
: Properties.Resources.tempErrorEvents;
default:
return null;
}
}
get { return GetImage(SubMode, UnreadEntries); }
}
public string Text
{
get
get { return GetText(SubMode, UnreadEntries); }
}
public static Image GetImage(NotificationsSubMode submode, int unreadEntries)
{
switch (submode)
{
switch (SubMode)
{
case NotificationsSubMode.Alerts:
return UnreadEntries == 0
? Messages.NOTIFICATIONS_SUBMODE_ALERTS_READ
: string.Format(Messages.NOTIFICATIONS_SUBMODE_ALERTS_UNREAD, UnreadEntries);
case NotificationsSubMode.Updates:
return UnreadEntries == 0
? Messages.NOTIFICATIONS_SUBMODE_UPDATES_READ
: string.Format(Messages.NOTIFICATIONS_SUBMODE_UPDATES_UNREAD, UnreadEntries);
case NotificationsSubMode.Events:
return UnreadEntries == 0
? Messages.NOTIFICATIONS_SUBMODE_EVENTS_READ
: string.Format(Messages.NOTIFICATIONS_SUBMODE_EVENTS_UNREAD, UnreadEntries);
default:
return "";
}
case NotificationsSubMode.Alerts:
return Properties.Resources._000_Alert2_h32bit_16;
case NotificationsSubMode.Updates:
return Properties.Resources.tempUpdates;
case NotificationsSubMode.Events:
return unreadEntries == 0
? Properties.Resources._000_date_h32bit_16
: Properties.Resources.tempErrorEvents;
default:
return null;
}
}
public static string GetText(NotificationsSubMode submode, int unreadEntries)
{
switch (submode)
{
case NotificationsSubMode.Alerts:
return unreadEntries == 0
? Messages.NOTIFICATIONS_SUBMODE_ALERTS_READ
: string.Format(Messages.NOTIFICATIONS_SUBMODE_ALERTS_UNREAD, unreadEntries);
case NotificationsSubMode.Updates:
return unreadEntries == 0
? Messages.NOTIFICATIONS_SUBMODE_UPDATES_READ
: string.Format(Messages.NOTIFICATIONS_SUBMODE_UPDATES_UNREAD, unreadEntries);
case NotificationsSubMode.Events:
if (unreadEntries == 0)
return Messages.NOTIFICATIONS_SUBMODE_EVENTS_READ;
else if (unreadEntries == 1)
return Messages.NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_ONE;
else
return string.Format(Messages.NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_MANY, unreadEntries);
default:
return "";
}
}
}

View File

@ -190,6 +190,8 @@ namespace XenAdmin
pluginManager.LoadPlugins();
contextMenuBuilder = new ContextMenuBuilder(pluginManager, commandInterface);
updatesPage.UpdatesCollectionChanged += updatesPage_UpdatesCollectionChanged;
eventsPage.GoToXenObjectRequested += eventsPage_GoToXenObjectRequested;
SearchPage.SearchChanged += SearchPanel_SearchChanged;
Alert.XenCenterAlerts.CollectionChanged += XenCenterAlerts_CollectionChanged;
@ -365,26 +367,48 @@ namespace XenAdmin
return;
Program.BeginInvoke(Program.MainWindow, () =>
{
ActionBase action = (ActionBase)e.Element;
if (action == null)
return;
{
ActionBase action = (ActionBase)e.Element;
if (action == null)
return;
var meddlingAction = action as MeddlingAction;
if (meddlingAction == null)
{
SetStatusBar(null, null);
if (statusBarAction != null)
{
statusBarAction.Changed -= actionChanged;
statusBarAction.Completed -= actionChanged;
}
statusBarAction = action;
}
action.Changed += actionChanged;
action.Completed += actionChanged;
actionChanged(action);
});
switch (e.Action)
{
case CollectionChangeAction.Add:
{
var meddlingAction = action as MeddlingAction;
if (meddlingAction == null)
{
SetStatusBar(null, null);
if (statusBarAction != null)
{
statusBarAction.Changed -= actionChanged;
statusBarAction.Completed -= actionChanged;
}
statusBarAction = action;
}
action.Changed += actionChanged;
action.Completed += actionChanged;
actionChanged(action);
break;
}
case CollectionChangeAction.Remove:
{
action.Changed -= actionChanged;
action.Completed -= actionChanged;
int errors = ConnectionsManager.History.Count(a => a.IsCompleted && !a.Succeeded);
navigationPane.UpdateNotificationsButton(NotificationsSubMode.Events, errors);
if (eventsPage.Visible)
{
TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Events, errors);
TitleIcon.Image = NotificationsSubModeItem.GetImage(NotificationsSubMode.Events, errors);
}
break;
}
}
});
}
void actionChanged(ActionBase action)
@ -435,6 +459,15 @@ namespace XenAdmin
!string.IsNullOrEmpty(action.Title) ? action.Title :
null);
}
int errors = ConnectionsManager.History.Count(a => a.IsCompleted && !a.Succeeded);
navigationPane.UpdateNotificationsButton(NotificationsSubMode.Events, errors);
if (eventsPage.Visible)
{
TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Events, errors);
TitleIcon.Image = NotificationsSubModeItem.GetImage(NotificationsSubMode.Events, errors);
}
}
public void SetStatusBar(Image image, string message)
@ -2362,6 +2395,23 @@ namespace XenAdmin
return navigationPane.SelectObject(o);
}
private void eventsPage_GoToXenObjectRequested(IXenObject obj)
{
navigationPane.SwitchToInfrastructureMode();
navigationPane.SelectObject(obj);
}
private void updatesPage_UpdatesCollectionChanged(int updatesCount)
{
navigationPane.UpdateNotificationsButton(NotificationsSubMode.Updates, updatesCount);
if (updatesPage.Visible)
{
TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Updates, updatesCount);
TitleIcon.Image = NotificationsSubModeItem.GetImage(NotificationsSubMode.Updates, updatesCount);
}
}
private void CloseWhenActionsCanceled(object o)
{
int i = 0;
@ -2608,10 +2658,10 @@ namespace XenAdmin
private void navigationPane_NotificationsSubModeChanged(NotificationsSubModeItem submodeItem)
{
TheTabControl.Visible = false;
alertPage.Visible = submodeItem.SubMode == NotificationsSubMode.Alerts;
updatesPage.Visible = submodeItem.SubMode == NotificationsSubMode.Updates;
eventsPage.Visible = submodeItem.SubMode == NotificationsSubMode.Events;
TheTabControl.Visible = false;
if (alertPage.Visible)
alertPage.RefreshAlertList();
@ -2694,7 +2744,17 @@ namespace XenAdmin
void XenCenterAlerts_CollectionChanged(object sender, CollectionChangeEventArgs e)
{
Program.BeginInvoke(Program.MainWindow, navigationPane.UpdateNotificationsButton);
Program.BeginInvoke(Program.MainWindow, () =>
{
navigationPane.UpdateNotificationsButton(
NotificationsSubMode.Alerts, Alert.NonDismissingAlertCount);
if (alertPage.Visible)
{
TitleLabel.Text = NotificationsSubModeItem.GetText(NotificationsSubMode.Alerts, Alert.NonDismissingAlertCount);
TitleIcon.Image = NotificationsSubModeItem.GetImage(NotificationsSubMode.Alerts, Alert.NonDismissingAlertCount);
}
});
}
private void backButton_Click(object sender, EventArgs e)

View File

@ -449,11 +449,14 @@ namespace XenAdmin.TabPages
private void ToolStripMenuItemDismiss_Click(object sender, EventArgs e)
{
if (new ThreeButtonDialog(
using (var dlog = new ThreeButtonDialog(
new ThreeButtonDialog.Details(null, Messages.ALERT_DISMISS_CONFIRM, Messages.XENCENTER),
ThreeButtonDialog.ButtonYes,
ThreeButtonDialog.ButtonNo).ShowDialog(this) != DialogResult.Yes)
return;
ThreeButtonDialog.ButtonNo))
{
if (dlog.ShowDialog(this) != DialogResult.Yes)
return;
}
Alert[] selectedAlerts = new Alert[GridViewAlerts.SelectedRows.Count];
for (int i = 0; i < selectedAlerts.Length; i++)

View File

@ -51,6 +51,8 @@ namespace XenAdmin.TabPages
private const int MAX_HISTORY_ITEM = 1000;
internal event Action<IXenObject> GoToXenObjectRequested;
public HistoryPage()
{
InitializeComponent();
@ -292,7 +294,8 @@ namespace XenAdmin.TabPages
private void row_GoToXenObjectRequested(IXenObject obj)
{
throw new NotImplementedException();
if (GoToXenObjectRequested != null)
GoToXenObjectRequested(obj);
}
@ -338,7 +341,25 @@ namespace XenAdmin.TabPages
private void tsmiDismissSelected_Click(object sender, EventArgs e)
{
using (var dlog = new ThreeButtonDialog(
new ThreeButtonDialog.Details(null, Messages.MESSAGEBOX_LOGS_DELETE_SELECTED, Messages.MESSAGEBOX_LOGS_DELETE_TITLE),
ThreeButtonDialog.ButtonYes,
ThreeButtonDialog.ButtonNo))
{
if (dlog.ShowDialog(this) != DialogResult.Yes)
return;
}
var actions = new List<ActionBase>();
foreach (var row in dataGridView.SelectedRows)
{
var actionRow = row as DataGridViewActionRow;
if (actionRow != null)
actions.Add(actionRow.Action);
}
ConnectionsManager.History.RemoveAll(actions.Contains);
}

View File

@ -66,6 +66,8 @@ namespace XenAdmin.TabPages
Dictionary<string, bool> expandedState = new Dictionary<string, bool>();
public event Action<int> UpdatesCollectionChanged;
private void CheckForUpdates_CheckForUpdatesCompleted(object sender, CheckForUpdatesCompletedEventArgs e)
{
Program.Invoke(this, delegate
@ -74,7 +76,12 @@ namespace XenAdmin.TabPages
ShowProgress(false);
checkForUpdatesSucceeded = e.Succeeded;
if (checkForUpdatesSucceeded)
{
Rebuild();
if (UpdatesCollectionChanged != null)
UpdatesCollectionChanged(updateAlerts.Count);
}
else
{
pictureBox.Image = SystemIcons.Error.ToBitmap();

View File

@ -78,17 +78,12 @@ namespace XenAdminTests.TabsAndMenus
protected void VerifyContextMenu(object ixmo, ExpectedMenuItem[] expectedItems)
{
string ixmoString = (ixmo == null ? "XenCenter node" : ixmo.ToString());
// The easiest way to generate the context menu is to call TreeView_NodeMouseClick_ ourselves.
// So construct fake click event data.
Assert.IsTrue(SelectInTree(ixmo), "Couldn't find a node for " + ixmoString + " in the tree");
// Generate the TreeContextMenu
MW(() =>
{
var tree = TestUtils.GetFlickerFreeTreeView(MainWindowWrapper.Item, "navigationPane.navigationView.treeView");
// Generate the TreeContextMenu
var e = new VirtualTreeNodeMouseClickEventArgs(tree.SelectedNode, MouseButtons.Right, 1, 0, 0);
var view = TestUtils.GetNavigationView(MainWindowWrapper.Item, "navigationPane.navigationView");
TestUtils.ExecuteMethod(view, "HandleNodeRightClick", new object[] { e });

View File

@ -19666,7 +19666,7 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Clear log entry.
/// Looks up a localized string similar to Clear entry.
/// </summary>
public static string MESSAGEBOX_LOG_DELETE_TITLE {
get {
@ -19692,6 +19692,15 @@ namespace XenAdmin {
}
}
/// <summary>
/// Looks up a localized string similar to Do you wish to delete the selected entries?.
/// </summary>
public static string MESSAGEBOX_LOGS_DELETE_SELECTED {
get {
return ResourceManager.GetString("MESSAGEBOX_LOGS_DELETE_SELECTED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Clear entries.
/// </summary>
@ -23012,11 +23021,20 @@ namespace XenAdmin {
}
/// <summary>
/// Looks up a localized string similar to Events ({0}).
/// Looks up a localized string similar to Events ({0} errors).
/// </summary>
public static string NOTIFICATIONS_SUBMODE_EVENTS_UNREAD {
public static string NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_MANY {
get {
return ResourceManager.GetString("NOTIFICATIONS_SUBMODE_EVENTS_UNREAD", resourceCulture);
return ResourceManager.GetString("NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_MANY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Events (1 error).
/// </summary>
public static string NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_ONE {
get {
return ResourceManager.GetString("NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_ONE", resourceCulture);
}
}

View File

@ -6856,6 +6856,9 @@ This action is final and unrecoverable.</value>
<data name="MESSAGEBOX_LOGS_DELETE" xml:space="preserve">
<value>This will clear all non-active entries in the current view. Do you wish to continue?</value>
</data>
<data name="MESSAGEBOX_LOGS_DELETE_SELECTED" xml:space="preserve">
<value>Do you wish to delete the selected entries?</value>
</data>
<data name="MESSAGEBOX_LOGS_DELETE_TITLE" xml:space="preserve">
<value>Clear entries</value>
</data>
@ -6863,7 +6866,7 @@ This action is final and unrecoverable.</value>
<value>Are you sure you want to delete this entry?</value>
</data>
<data name="MESSAGEBOX_LOG_DELETE_TITLE" xml:space="preserve">
<value>Clear log entry</value>
<value>Clear entry</value>
</data>
<data name="MESSAGEBOX_MOVING_VDI_TITLE" xml:space="preserve">
<value>Moving Virtual Disk</value>
@ -7943,8 +7946,11 @@ It is strongly recommended that you Cancel and apply the latest version of the p
<data name="NOTIFICATIONS_SUBMODE_EVENTS_READ" xml:space="preserve">
<value>Events</value>
</data>
<data name="NOTIFICATIONS_SUBMODE_EVENTS_UNREAD" xml:space="preserve">
<value>Events ({0})</value>
<data name="NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_MANY" xml:space="preserve">
<value>Events ({0} errors)</value>
</data>
<data name="NOTIFICATIONS_SUBMODE_EVENTS_UNREAD_ONE" xml:space="preserve">
<value>Events (1 error)</value>
</data>
<data name="NOTIFICATIONS_SUBMODE_UPDATES_READ" xml:space="preserve">
<value>Updates</value>
@ -10936,9 +10942,9 @@ To learn more about the XenServer Dynamic Workload Balancing feature or to start
</data>
<data name="VERSION_NUMBER" xml:space="preserve">
<value>XenCenter version {0} (build {1}) {2}-bit</value>
</data>
<data name="VGPU_DESCRIPTION" xml:space="preserve">
<value>{0} vGPU ({1} per GPU, {2}, {3} displays)</value>
</data>
<data name="VGPU_DESCRIPTION" xml:space="preserve">
<value>{0} vGPU ({1} per GPU, {2}, {3} displays)</value>
</data>
<data name="VGPU_PASSTHRU_TOSTRING" xml:space="preserve">
<value>Pass-through whole GPU</value>

View File

@ -47,7 +47,7 @@ cp ${OUTPUT_DIR}/XenAdminTests.tgz ${TEST_DIR}
cd ${TEST_DIR} && tar xzf XenAdminTests.tgz && chmod -R 777 Release
set +e
"/cygdrive/c/Program Files/NUnit 2.5.10/bin/net-2.0/nunit-console.exe" /process=separate /noshadow /err="C:\cygwin\tmp\error.nunit.log" /timeout=40000 /output="C:\cygwin\tmp\output.nunit.log" /xml="C:\cygwin\tmp\XenAdminTests.xml" "C:\cygwin\tmp\Release\XenAdminTests.dll" &
"/cygdrive/c/Program Files/NUnit 2.5.10/bin/net-2.0/nunit-console.exe" /process=separate /noshadow /labels /err="C:\cygwin\tmp\error.nunit.log" /timeout=40000 /output="C:\cygwin\tmp\output.nunit.log" /xml="C:\cygwin\tmp\XenAdminTests.xml" "C:\cygwin\tmp\Release\XenAdminTests.dll" &
pid=$!
(sleep 2000 ; kill $pid 2>/dev/null ) &
sleeperpid=$!