Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLluis Sanchez Gual <lluis@novell.com>2011-06-29 00:17:21 +0400
committerLluis Sanchez Gual <lluis@novell.com>2011-06-29 00:17:21 +0400
commit8a7d129bfeb656c33ad754b61af3cba283f5da4a (patch)
tree9b12a245e8c4a66b38fbd388b8d462c6a922f1df
parentd05a0b53a51e77966a1575377ec113df86f6dbd6 (diff)
Added basic updater service
The new core updater service handles scheduled update checks. It can be configured using the Updates option panel. Updater system can be plugged into it using the IUpdateHandler interface.
-rw-r--r--main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml6
-rw-r--r--main/src/core/MonoDevelop.Ide/Makefile.am5
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs3
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/AddInsOptionsPanel.cs69
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AddinUpdateHandler.cs147
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs117
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/DownloadService.cs447
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateRank.cs)13
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/InstallDialog.cs78
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCheckHandler.cs (renamed from main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateTagExtensionNode.cs)18
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCommands.cs59
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateDialog.cs218
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateInfoExtensionNode.cs42
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateResult.cs117
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs522
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj5
-rw-r--r--main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget.cs231
-rw-r--r--main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic256
18 files changed, 592 insertions, 1761 deletions
diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
index bb7e18dbdb..7d3972ea3e 100644
--- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
+++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MonoDevelop.Ide.addin.xml
@@ -145,6 +145,10 @@
<Description>Reference finder.</Description>
<ExtensionNode name="ReferenceFinder" type="MonoDevelop.Ide.FindInFiles.ReferenceFinderCodon"/>
</ExtensionPoint>
+
+ <ExtensionPoint path = "/MonoDevelop/Ide/Updater/UpdateHandlers" name = "Update handlers">
+ <ExtensionNode name="Type" />
+ </ExtensionPoint>
<!-- Extensions -->
@@ -160,7 +164,7 @@
</Extension>
<Extension path = "/MonoDevelop/Ide/StartupHandlers">
- <Class class = "MonoDevelop.Ide.Gui.AddinUpdateHandler"/>
+ <Class class = "MonoDevelop.Ide.Updater.UpdateCheckHandler"/>
<Class class = "MonoDevelop.Ide.Gui.Dialogs.TipOfTheDayStartup"/>
</Extension>
diff --git a/main/src/core/MonoDevelop.Ide/Makefile.am b/main/src/core/MonoDevelop.Ide/Makefile.am
index afaca0c2bf..7ff5f9fcea 100644
--- a/main/src/core/MonoDevelop.Ide/Makefile.am
+++ b/main/src/core/MonoDevelop.Ide/Makefile.am
@@ -536,7 +536,6 @@ FILES = \
MonoDevelop.Ide.Gui/AbstractBaseViewContent.cs \
MonoDevelop.Ide.Gui/AbstractPadContent.cs \
MonoDevelop.Ide.Gui/AbstractViewContent.cs \
- MonoDevelop.Ide.Gui/AddinUpdateHandler.cs \
MonoDevelop.Ide.Gui/AsyncDispatchAttribute.cs \
MonoDevelop.Ide.Gui/BackgroundProgressMonitor.cs \
MonoDevelop.Ide.Gui/ConfigurationComboBox.cs \
@@ -670,6 +669,10 @@ FILES = \
MonoDevelop.Ide.Templates/SolutionDescriptor.cs \
MonoDevelop.Ide.Templates/SolutionItemDescriptor.cs \
MonoDevelop.Ide.Templates/TextFileDescriptionTemplate.cs \
+ MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs \
+ MonoDevelop.Ide.Updater/IUpdateHandler.cs \
+ MonoDevelop.Ide.Updater/UpdateCheckHandler.cs \
+ MonoDevelop.Ide.Updater/UpdateService.cs \
MonoDevelop.Ide.WebBrowser/IWebBrowser.cs \
MonoDevelop.Ide.WebBrowser/IWebBrowserLoader.cs \
MonoDevelop.Ide.WebBrowser/LoadingProgressChangedEventArgs.cs \
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs
index 429749f285..9bc0a15227 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs
@@ -31,6 +31,7 @@ using MonoDevelop.Core;
using MonoDevelop.Core.Execution;
using MonoDevelop.Ide.Gui;
using System;
+using MonoDevelop.Ide.Updater;
namespace MonoDevelop.Ide.Commands
{
@@ -45,7 +46,7 @@ namespace MonoDevelop.Ide.Commands
{
protected override void Run ()
{
- AddinUpdateHandler.ShowManager ();
+ AddinsUpdateHandler.Instance.ShowManager ();
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/AddInsOptionsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/AddInsOptionsPanel.cs
index 7517fcb4a5..75efff3730 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/AddInsOptionsPanel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/AddInsOptionsPanel.cs
@@ -37,6 +37,8 @@ using MonoDevelop.Projects;
using Gtk;
using MonoDevelop.Components;
+using MonoDevelop.Core.Setup;
+using MonoDevelop.Ide.Updater;
namespace MonoDevelop.Ide.Gui.OptionPanels
{
@@ -57,48 +59,59 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
internal partial class AddInsPanelWidget : Gtk.Bin
{
- public AddInsPanelWidget ()
+ public AddInsPanelWidget ()
{
Build ();
- bool checkForUpdates = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.CkeckForUpdates", true);
- int updateSpan = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateSpanValue", 1);
- string unit = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateSpanUnit", "D");
+ if (!UpdateService.AutoCheckForUpdates)
+ radioNever.Active = true;
+ else if (UpdateService.UpdateSpanUnit == UpdateSpanUnit.Hour)
+ radioHour.Active = true;
+ else if (UpdateService.UpdateSpanUnit == UpdateSpanUnit.Day)
+ radioDay.Active = true;
+ else if (UpdateService.UpdateSpanUnit == UpdateSpanUnit.Month)
+ radioMonth.Active = true;
- lookCheck.Active = checkForUpdates;
- valueSpin.Value = (double) updateSpan;
-
- if (unit == "D")
- periodCombo.Active = 0;
- else
- periodCombo.Active = 1;
- UpdateStatus ();
+ switch (UpdateService.UpdateLevel) {
+ case UpdateLevel.Beta: radioBeta.Active = true; checkUnstable.Active = true; break;
+ case UpdateLevel.Alpha: radioAlpha.Active = true; checkUnstable.Active = true; break;
+ case UpdateLevel.Test: radioTest.Visible = true; radioTest.Active = true; checkUnstable.Active = true; break;
+ default: checkUnstable.Active = false; break;
+ }
}
public void Store ()
{
- if (periodCombo.Active == 0)
- PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.UpdateSpanUnit", "D");
- else
- PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.UpdateSpanUnit", "M");
+ UpdateService.AutoCheckForUpdates = !radioNever.Active;
+ UpdateService.UpdateSpanValue = 1;
- PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.UpdateSpanValue", (int) valueSpin.Value);
- PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.CkeckForUpdates", lookCheck.Active);
- }
-
- void UpdateStatus ()
- {
- valueSpin.Sensitive = periodCombo.Sensitive = lookCheck.Active;
+ if (radioHour.Active)
+ UpdateService.UpdateSpanUnit = UpdateSpanUnit.Hour;
+ else if (radioDay.Active)
+ UpdateService.UpdateSpanUnit = UpdateSpanUnit.Day;
+ else if (radioMonth.Active)
+ UpdateService.UpdateSpanUnit = UpdateSpanUnit.Month;
+
+ if (checkUnstable.Active) {
+ if (radioBeta.Active)
+ UpdateService.UpdateLevel = UpdateLevel.Beta;
+ else if (radioAlpha.Active)
+ UpdateService.UpdateLevel = UpdateLevel.Alpha;
+ else if (radioTest.Active)
+ UpdateService.UpdateLevel = UpdateLevel.Test;
+ } else
+ UpdateService.UpdateLevel = UpdateLevel.Stable;
+
}
- public void OnManageClicked (object s, EventArgs a)
+ protected void OnCheckUnstableToggled (object sender, System.EventArgs e)
{
- AddinUpdateHandler.ShowManager ();
+ boxUnstable.Visible = checkUnstable.Active;
}
-
- public void OnCheckToggled (object s, EventArgs a)
+
+ protected void OnButtonUpdateNowClicked (object sender, System.EventArgs e)
{
- UpdateStatus ();
+ UpdateService.CheckForUpdates ();
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AddinUpdateHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AddinUpdateHandler.cs
deleted file mode 100644
index 58c5acd5e0..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/AddinUpdateHandler.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// AddinUpdateHandler.cs
-//
-// Author:
-// Lluis Sanchez Gual
-//
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to
-// permit persons to whom the Software is furnished to do so, subject to
-// the following conditions:
-//
-// The above copyright notice and this permission notice shall be
-// included in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Linq;
-using System.Threading;
-
-using Gtk;
-
-using MonoDevelop.Core;
-using Mono.Addins.Setup;
-using Mono.Addins.Gui;
-using MonoDevelop.Components.Commands;
-using MonoDevelop.Core.ProgressMonitoring;
-using MonoDevelop.Ide.ProgressMonitoring;
-
-namespace MonoDevelop.Ide.Gui
-{
- class AddinUpdateHandler: CommandHandler
- {
- public static AggregatedProgressMonitor UpdateMonitor;
- AddinRepositoryEntry[] updates;
- static StatusBarIcon updateIcon;
-
- public static void HideAlert ()
- {
- if (updateIcon != null) {
- updateIcon.Dispose ();
- updateIcon = null;
- }
- }
-
- protected override void Run ()
- {
- bool checkForUpdates = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.CkeckForUpdates", true);
- if (!checkForUpdates)
- return;
-
- DateTime lastUpdate = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.LastCheck", DateTime.MinValue);
- int updateSpan = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateSpanValue", 1);
- string unit = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateSpanUnit", "D");
-
- bool check = false;
- if (unit == "D") {
- lastUpdate = lastUpdate.Date;
- check = (DateTime.Now - lastUpdate).TotalDays >= updateSpan;
- } else if (unit == "M") {
- lastUpdate = new DateTime (lastUpdate.Year, lastUpdate.Month, 1, 0, 0, 0);
- check = DateTime.Now >= lastUpdate.AddMonths (updateSpan);
- }
-
- if (check) {
- IProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor ("Looking for add-in updates", "md-software-update");
- UpdateMonitor = new AggregatedProgressMonitor (mon);
-
- Thread t = new Thread (new ThreadStart (UpdateAddins));
- t.Name = "Addin updater";
- t.Start ();
-/* } else {
- updates = Runtime.AddinSetupService.Repositories.GetAvailableUpdates ();
- if (updates.Any (u => UpdateRank.Minor != UpdateService.GetUpdateRank (u.Addin.Properties.GetPropertyValue ("UpdateRank"))))
- WarnAvailableUpdates ();*/
- }
- }
-
- void UpdateAddins ()
- {
- PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.LastCheck", DateTime.Now);
- using (UpdateMonitor) {
- using (ProgressStatusMonitor pm = new ProgressStatusMonitor (UpdateMonitor)) {
- Runtime.AddinSetupService.Repositories.UpdateAllRepositories (pm);
- updates = Runtime.AddinSetupService.Repositories.GetAvailableUpdates ();
- if (updates.Length > 0)
- DispatchService.GuiDispatch (new MessageHandler (WarnAvailableUpdates));
- }
- }
- }
-
- void WarnAvailableUpdates ()
- {
- updateIcon = IdeApp.Workbench.StatusBar.ShowStatusIcon (ImageService.GetPixbuf ("md-software-update", IconSize.Menu));
- string s = GettextCatalog.GetString ("New add-in updates are available:");
- for (int n=0; n<updates.Length && n < 10; n++)
- s += "\n" + updates [n].Addin.Name;
-
- if (updates.Length > 10)
- s += "\n...";
-
- updateIcon.ToolTip = s;
- updateIcon.SetAlertMode (20);
- updateIcon.EventBox.ButtonPressEvent += new ButtonPressEventHandler (OnUpdateClicked);
- }
-
- void OnUpdateClicked (object s, ButtonPressEventArgs args)
- {
- if (args.Event.Button == 1) {
- HideAlert ();
- AddinManagerWindow.Run (IdeApp.Workbench.RootWindow);
- }
- }
-
- public static void ShowManager ()
- {
- AggregatedProgressMonitor monitor = UpdateMonitor;
- if (monitor != null && !monitor.IsCompleted) {
- monitor.AddSlaveMonitor (new MessageDialogProgressMonitor (true, true, false));
- monitor.AsyncOperation.WaitForCompleted ();
- }
- HideAlert ();
-
- AddinManagerWindow.Run (IdeApp.Workbench.RootWindow);
- }
-
- internal static void QueryAddinUpdates ()
- {
- AggregatedProgressMonitor monitor = UpdateMonitor;
- if (monitor != null)
- monitor.AsyncOperation.WaitForCompleted ();
- }
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs
new file mode 100644
index 0000000000..6d6f9efaeb
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/AddinsUpdateHandler.cs
@@ -0,0 +1,117 @@
+//
+// AddinsUpdateHandler.cs
+//
+// Author:
+// Lluis Sanchez <lluis@xamarin.com>
+//
+// Copyright (c) 2011 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using MonoDevelop.Core;
+using Mono.Addins.Setup;
+using Gtk;
+using MonoDevelop.Core.ProgressMonitoring;
+using Mono.Addins.Gui;
+using MonoDevelop.Ide.ProgressMonitoring;
+using Mono.Addins;
+
+namespace MonoDevelop.Ide.Updater
+{
+ [Extension("/MonoDevelop/Ide/Updater/UpdateHandlers")]
+ public class AddinsUpdateHandler: IUpdateHandler
+ {
+ AddinRepositoryEntry[] updates;
+ static StatusBarIcon updateIcon;
+ internal static AddinsUpdateHandler Instance;
+ IProgressMonitor updateMonitor;
+
+ public AddinsUpdateHandler ()
+ {
+ Instance = this;
+ }
+
+ public void CheckUpdates (IProgressMonitor monitor)
+ {
+ updateMonitor = monitor;
+ try {
+ using (ProgressStatusMonitor pm = new ProgressStatusMonitor (monitor)) {
+ Runtime.AddinSetupService.Repositories.UpdateAllRepositories (pm);
+ updates = Runtime.AddinSetupService.Repositories.GetAvailableUpdates ();
+ if (updates.Length > 0)
+ DispatchService.GuiDispatch (new MessageHandler (WarnAvailableUpdates));
+ }
+ } finally {
+ updateMonitor = null;
+ }
+ }
+
+ void WarnAvailableUpdates ()
+ {
+ updateIcon = IdeApp.Workbench.StatusBar.ShowStatusIcon (ImageService.GetPixbuf ("md-software-update", IconSize.Menu));
+ string s = GettextCatalog.GetString ("New add-in updates are available:");
+ for (int n=0; n<updates.Length && n < 10; n++)
+ s += "\n" + updates [n].Addin.Name;
+
+ if (updates.Length > 10)
+ s += "\n...";
+
+ updateIcon.ToolTip = s;
+ updateIcon.SetAlertMode (20);
+ updateIcon.EventBox.ButtonPressEvent += new ButtonPressEventHandler (OnUpdateClicked);
+ }
+
+ void OnUpdateClicked (object s, ButtonPressEventArgs args)
+ {
+ if (args.Event.Button == 1) {
+ HideAlert ();
+ AddinManagerWindow.Run (IdeApp.Workbench.RootWindow);
+ }
+ }
+
+ public void ShowManager ()
+ {
+ IProgressMonitor m = updateMonitor;
+ if (m != null && !m.AsyncOperation.IsCompleted) {
+ AggregatedProgressMonitor monitor = new AggregatedProgressMonitor (m);
+ monitor.AddSlaveMonitor (new MessageDialogProgressMonitor (true, true, false));
+ monitor.AsyncOperation.WaitForCompleted ();
+ }
+ HideAlert ();
+
+ AddinManagerWindow.Run (IdeApp.Workbench.RootWindow);
+ }
+
+ internal void QueryAddinUpdates ()
+ {
+ IProgressMonitor monitor = updateMonitor;
+ if (monitor != null)
+ monitor.AsyncOperation.WaitForCompleted ();
+ }
+
+ public static void HideAlert ()
+ {
+ if (updateIcon != null) {
+ updateIcon.Dispose ();
+ updateIcon = null;
+ }
+ }
+ }
+}
+
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/DownloadService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/DownloadService.cs
deleted file mode 100644
index d4a310feb6..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/DownloadService.cs
+++ /dev/null
@@ -1,447 +0,0 @@
-//
-// DownloadService.cs
-//
-// Author:
-// lluis <${AuthorEmail}>
-//
-// Copyright (c) 2011 lluis
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Linq;
-using MonoDevelop.Core;
-using System.IO;
-using System.Collections.Generic;
-using System.Xml.Serialization;
-using System.Threading;
-using System.Net;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace MonoDevelop.Ide.Updater
-{
- static class DownloadService
- {
- static DownloaderStatus status = DownloaderStatus.Stopped;
- static string statusMessage;
- static object serviceLock = new object ();
- static bool pauseRequested;
- static Stream globalLock;
-
- static Gdk.Pixbuf runningIcon;
- static Gdk.Pixbuf pausedIcon;
- static StatusBarIcon statusBarIcon;
-
- public static event EventHandler StatusChanged;
-
- public static event EventHandler DownloadFinished;
-
- public static bool Enabled {
- get; private set;
- }
-
- public static FilePath DownloadDir {
- get { return PropertyService.Locations.Cache.Combine ("TempDownload"); }
- }
-
- public static FilePath DownloadIndex {
- get { return DownloadDir.Combine ("index.xml"); }
- }
-
- public static DownloaderStatus Status {
- get { return status; }
- set {
- status = value;
- if (value == DownloaderStatus.Paused)
- statusMessage = GettextCatalog.GetString ("Download paused");
- else
- statusMessage = string.Empty;
- OnStatusChanged ();
- Monitor.Pulse (serviceLock);
- }
- }
-
- public static string StatusMessage {
- get { return statusMessage; }
- private set {
- if (value != statusMessage) {
- statusMessage = value;
- Gtk.Application.Invoke (delegate {
- if (statusBarIcon != null)
- statusBarIcon.ToolTip = statusMessage;
- });
- }
- }
- }
-
- internal static void Initialize ()
- {
- runningIcon = Gdk.Pixbuf.LoadFromResource ("downloader-running.png");
- pausedIcon = Gdk.Pixbuf.LoadFromResource ("downloader-paused.png");
-
- if (!Directory.Exists (DownloadDir))
- Directory.CreateDirectory (DownloadDir);
- try {
- string lockFile = DownloadDir.Combine ("downloader-lock");
- globalLock = new FileStream (lockFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
- } catch (IOException) {
- // File is locked
- Enabled = false;
- }
- IdeApp.Exiting += HandleIdeAppExiting;
- }
-
- static void HandleIdeAppExiting (object sender, ExitEventArgs args)
- {
- lock (serviceLock) {
- // Stop the downloader
- ForcePause (4);
- }
- }
-
- static bool ForcePause (int timeoutSeconds)
- {
- PauseDownloader ();
- DateTime t = DateTime.Now + TimeSpan.FromSeconds (timeoutSeconds);
- while (Status == DownloaderStatus.Running) {
- DateTime now = DateTime.Now;
- if (now >= t)
- return false;
- Monitor.Wait (serviceLock, t - now);
- }
- return true;
- }
-
- static void Shutdown ()
- {
- if (globalLock != null) {
- globalLock.Close ();
- globalLock = null;
- }
- }
-
- public static void SetUpdates (IEnumerable<Update> targets)
- {
- lock (serviceLock) {
- // Stop the downloader
- if (!ForcePause (10))
- return;
-
- var currentDownloads = ReadDownloads ();
-
- // Remove downloads which don't exist in the new set
- foreach (var d in currentDownloads.ToArray ().Where (d => !targets.Any (t => t.Id == d.Id && t.VersionId == d.VersionId))) {
- currentDownloads.Remove (d);
- DeleteDownloadedFile (d);
- }
-
- // Add new downloads
- foreach (var d in targets.Where (t => !currentDownloads.Any (c => c.Id == t.Id && c.VersionId == t.VersionId))) {
- currentDownloads.Add (d);
- d.Status = UpdateStatus.PendingDownload;
- }
-
- // Restart failed downloads and reset pending install flag
- foreach (var d in currentDownloads) {
- if (d.Status == UpdateStatus.Failed) {
- d.Status = UpdateStatus.PendingDownload;
- DeleteDownloadedFile (d);
- }
- else if (d.Status == UpdateStatus.PendingInstall)
- d.Status = UpdateStatus.Downloaded;
- }
-
- SaveDownloads (currentDownloads);
- StartDownloader ();
- }
- }
-
- public static void Remove (Update dt)
- {
- lock (serviceLock) {
- var currentDownloads = ReadDownloads ();
- currentDownloads.Remove (currentDownloads.First (u => u.Id == dt.Id && u.VersionId == dt.VersionId));
- DeleteDownloadedFile (dt);
- SaveDownloads (currentDownloads);
- }
- }
-
- public static void MarkForInstallation (IEnumerable<Update> updates)
- {
- lock (serviceLock) {
- var currentDownloads = ReadDownloads ();
- foreach (Update u in currentDownloads.Where (dt => updates.Any (u => u.Id == dt.Id && u.VersionId == dt.VersionId)))
- u.Status = UpdateStatus.PendingInstall;
- SaveDownloads (currentDownloads);
- }
- }
-
- static void DeleteDownloadedFile (Update t)
- {
- try {
- if (!string.IsNullOrEmpty (t.File) && File.Exists (t.File))
- File.Delete (t.File);
- } catch (Exception ex) {
- LoggingService.LogError ("Downloaded file could not be deleted: " + t.File, ex);
- }
- }
-
- public static bool AllDownloaded {
- get {
- var currentDownloads = ReadDownloads ();
- return currentDownloads.All (d => d.Status == UpdateStatus.Downloaded);
- }
- }
-
- public static IEnumerable<Update> GetAllDownloads ()
- {
- return ReadDownloads ();
- }
-
- public static void PauseDownloader ()
- {
- lock (serviceLock) {
- if (Status == DownloaderStatus.Running && !pauseRequested)
- pauseRequested = true;
- }
- }
-
- public static void StartDownloader ()
- {
- lock (serviceLock) {
- if (Status != DownloaderStatus.Running) {
- Status = DownloaderStatus.Running;
- ThreadPool.QueueUserWorkItem (Download);
- }
- else if (pauseRequested) {
- pauseRequested = false;
- Status = DownloaderStatus.Running;
- }
- }
- }
-
- static void Download (object o)
- {
- byte[] buffer = new byte [16384];
- var list = ReadDownloads ();
- bool allDone = false;
-
- while (!pauseRequested)
- {
- var next = list.FirstOrDefault (d => d.Status == UpdateStatus.Downloading);
- if (next == null)
- next = list.FirstOrDefault (d => d.Status == UpdateStatus.PendingDownload);
- if (next == null) {
- lock (serviceLock) {
- pauseRequested = true;
- }
- allDone = true;
- break;
- }
- next.Status = UpdateStatus.Downloading;
- SaveDownloads (list);
-
- StatusMessage = GettextCatalog.GetString ("Downloading {0}", next.Name);
-
- HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create (next.Url);
-
- FileStream fs = null;
- long lenDownloaded = 0;
-
- try {
- if (!string.IsNullOrEmpty (next.File) && File.Exists (next.File)) {
- FileInfo fi = new FileInfo (next.File);
- lenDownloaded = fi.Length;
- req.AddRange ((int)fi.Length);
- fs = new FileStream (next.File, FileMode.Open, FileAccess.Write);
- fs.Seek (0,SeekOrigin.End);
- }
-
- using (var resp = req.GetResponse ()) {
-
- if (fs != null && resp.ContentLength == -1) {
- // Not resumable
- fs.Close ();
- fs = null;
- lenDownloaded = 0;
- }
-
- if (fs == null) {
- next.File = GetFileName (next, resp);
- SaveDownloads (list);
- fs = new FileStream (next.File, FileMode.Create, FileAccess.Write);
- }
-
- long totalLen = next.Size;
- var s = resp.GetResponseStream ();
- int nr = -1;
- while (!pauseRequested && (nr = s.Read (buffer, 0, buffer.Length)) > 0) {
- fs.Write (buffer, 0, nr);
- lenDownloaded += nr;
- if (totalLen != -1)
- StatusMessage = GettextCatalog.GetString ("Downloading {0} ({1}%)", next.Name, (lenDownloaded * 100) / totalLen);
- else
- StatusMessage = GettextCatalog.GetString ("Downloading {0}", next.Name);
- }
- fs.Flush ();
- Console.WriteLine ("READ " + lenDownloaded);
- if (nr == 0) {
- fs.Close ();
- if (next.Hash != CalcHash (next.File))
- throw new Exception ("MD5 hashes don't match");
- next.Status = UpdateStatus.Downloaded;
- }
- }
- }
- catch (Exception ex) {
- next.Status = UpdateStatus.Failed;
- LoggingService.LogError ("File download failed: " + next.Url, ex);
- }
- finally {
- fs.Dispose ();
- SaveDownloads (list);
- }
- }
- lock (serviceLock) {
- if (!pauseRequested) {
- // Service has been resumed
- ThreadPool.QueueUserWorkItem (Download);
- }
- else if (allDone) {
- Status = DownloaderStatus.Stopped;
- OnDownloadFinished ();
- }
- else
- Status = DownloaderStatus.Paused;
- pauseRequested = false;
- }
- }
-
- static void SaveDownloads (List<Update> list)
- {
- XmlSerializer ser = new XmlSerializer (typeof(List<Update>));
- using (var sr = new StreamWriter (DownloadIndex)) {
- ser.Serialize (sr, list);
- }
- }
-
- static List<Update> ReadDownloads ()
- {
- if (File.Exists (DownloadIndex)) {
- try {
- XmlSerializer ser = new XmlSerializer (typeof(List<Update>));
- using (var sr = new StreamReader (DownloadIndex)) {
- return (List<Update>) ser.Deserialize (sr);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Could not load download index", ex);
- }
- }
- return new List<Update> ();
- }
-
- static FilePath GetFileName (Update t, WebResponse resp)
- {
- string disp = resp.Headers.Get ("Content-Disposition");
- if (disp != null) {
- foreach (string v in disp.Split (';')) {
- if (v != null && v.Trim ().StartsWith ("filename")) {
- int i = v.IndexOf ('=');
- if (i != -1) {
- string n = v.Substring (i+1).Trim ();
- return DownloadDir.Combine (t.Id + Path.GetExtension (n));
- }
- break;
- }
- }
- }
- int j = t.Url.LastIndexOf ('/');
- string file = t.Url.Substring (j+1);
- j = file.LastIndexOf ('?');
- if (j != -1)
- file = file.Substring (0, j);
- return DownloadDir.Combine (t.Id + Path.GetExtension (file));
- }
-
- static string CalcHash (string file)
- {
- using (var fs = File.OpenRead (file)) {
- MD5CryptoServiceProvider x = new MD5CryptoServiceProvider();
- var data = x.ComputeHash (fs);
- StringBuilder sb = new StringBuilder ();
- for (int i = 0; i < data.Length; i++)
- sb.Append (data[i].ToString("x2").ToLower());
- return sb.ToString ();
- }
- }
-
- static void OnStatusChanged ()
- {
- Gtk.Application.Invoke (delegate {
- if (statusBarIcon != null) {
- statusBarIcon.Dispose ();
- statusBarIcon = null;
- }
- switch (Status) {
- case DownloaderStatus.Paused: statusBarIcon = IdeApp.Workbench.StatusBar.ShowStatusIcon (pausedIcon); break;
- case DownloaderStatus.Running: statusBarIcon = IdeApp.Workbench.StatusBar.ShowStatusIcon (runningIcon); break;
- }
-
- if (statusBarIcon != null)
- statusBarIcon.EventBox.ButtonPressEvent += HandleStatusBarIconEventBoxButtonPressEvent;
-
- if (StatusChanged != null)
- StatusChanged (null, EventArgs.Empty);
- });
- }
-
- static void HandleStatusBarIconEventBoxButtonPressEvent (object o, Gtk.ButtonPressEventArgs args)
- {
- if (Status == DownloaderStatus.Running)
- PauseDownloader ();
- else if (Status == DownloaderStatus.Paused)
- StartDownloader ();
- }
-
- static void OnDownloadFinished ()
- {
- Gtk.Application.Invoke (delegate {
- if (DownloadFinished != null)
- DownloadFinished (null, EventArgs.Empty);
- });
- }
- }
-
- public enum DownloaderStatus
- {
- Running,
- Stopped,
- Paused
- }
-
- public enum UpdateStatus
- {
- PendingDownload,
- Downloading,
- Downloaded,
- Failed,
- PendingInstall
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateRank.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs
index 5abdd25336..d2c348ecd9 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateRank.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/IUpdateHandler.cs
@@ -1,10 +1,10 @@
//
-// UpdateRank.cs
+// IUpdateHandler.cs
//
// Author:
-// Lluis Sanchez Gual <lluis@novell.com>
+// Lluis Sanchez <lluis@xamarin.com>
//
-// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2011 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -24,14 +24,13 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
+using MonoDevelop.Core;
namespace MonoDevelop.Ide.Updater
{
- enum UpdateRank
+ public interface IUpdateHandler
{
- Important,
- Normal,
- Minor
+ void CheckUpdates (IProgressMonitor monitor);
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/InstallDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/InstallDialog.cs
deleted file mode 100644
index ae1ea2b516..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/InstallDialog.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// InstallDialog.cs
-//
-// Author:
-// Lluis Sanchez <lluis@xamarin.com>
-//
-// Copyright (c) 2011 Xamarin Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace MonoDevelop.Ide.Updater
-{
- public partial class InstallDialog : Gtk.Dialog
- {
- List<Update> toInstall = new List<Update> ();
-
- public InstallDialog (IEnumerable<Update> updates)
- {
- this.Build ();
- toInstall.AddRange (updates);
-
- var coreUpdates = updates.Where (u => !u.IsThirdParty);
- var extraUpdates = updates.Where (u => u.IsThirdParty);
-
- if (coreUpdates.Any ())
- AddUpdates (tableUpdates, coreUpdates);
- else
- boxUpdates.Hide ();
-
- if (extraUpdates.Any ())
- AddUpdates (tableUpdatesExtra, extraUpdates);
- else
- boxUpdatesExtra.Hide ();
- }
-
- void AddUpdates (Gtk.Table table, IEnumerable<Update> updates)
- {
- uint r = 0;
- foreach (var up in updates) {
- var cb = new Gtk.CheckButton (up.Name);
- var cup = up;
- cb.Active = true;
- cb.Toggled += delegate {
- if (cb.Active)
- toInstall.Add (cup);
- else
- toInstall.Remove (cup);
- };
- table.Attach (cb, 0, 1, r, r + 1);
- }
- table.ShowAll ();
- }
-
- public IEnumerable<Update> UpdatesToInstall {
- get { return toInstall; }
- }
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateTagExtensionNode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCheckHandler.cs
index be461f0922..59ad48c4ed 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateTagExtensionNode.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCheckHandler.cs
@@ -1,10 +1,10 @@
//
-// UpdateTagExtensionNode.cs
+// UpdateCheckHandler.cs
//
// Author:
-// Lluis Sanchez Gual <lluis@novell.com>
+// Lluis Sanchez <lluis@xamarin.com>
//
-// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
+// Copyright (c) 2011 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -23,13 +23,19 @@
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
-using Mono.Addins;
+
+
+using MonoDevelop.Components.Commands;
+using MonoDevelop.Ide.Updater;
namespace MonoDevelop.Ide.Updater
{
- class UpdateTagExtensionNode: ExtensionNode
+ class UpdateCheckHandler: CommandHandler
{
+ protected override void Run ()
+ {
+ UpdateService.ScheduledCheckForUpdates ();
+ }
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCommands.cs
deleted file mode 100644
index ce6f48fa2b..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateCommands.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// UpdateCommands.cs
-//
-// Author:
-// Michael Hutchinson <mhutchinson@novell.com>
-//
-// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using MonoDevelop.Components.Commands;
-
-namespace MonoDevelop.Ide.Updater
-{
- public enum UpdateCommands
- {
- CheckForUpdates,
- }
-
- class CheckForUpdatesHandler : CommandHandler
- {
- protected override void Run ()
- {
- UpdateService.RunCheckDialog (false);
- }
-
- protected override void Update (CommandInfo info)
- {
- info.Visible = info.Enabled = UpdateService.CanUpdate;
- }
- }
-
- class CheckForUpdatesOnStartUpHandler : CommandHandler
- {
- protected override void Run()
- {
- if (UpdateService.CanUpdate)
- UpdateService.RunCheckDialog (true);
- }
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateDialog.cs
deleted file mode 100644
index 17511065a3..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateDialog.cs
+++ /dev/null
@@ -1,218 +0,0 @@
-//
-// UpdateDialog.cs
-//
-// Author:
-// Michael Hutchinson <mhutchinson@novell.com>
-//
-// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using System.Linq;
-using System.Collections.Generic;
-using System.Text;
-
-using Gtk;
-using MonoDevelop.Core;
-using MonoDevelop.Core.Setup;
-using MonoDevelop.Ide;
-using MonoDevelop.Ide.ProgressMonitoring;
-
-namespace MonoDevelop.Ide.Updater
-{
- partial class UpdateDialog : Gtk.Dialog
- {
- const int PAGE_MESSAGE = 0;
- const int PAGE_UPDATES = 1;
-
- List<UpdateResult> results = new List<UpdateResult> ();
- bool installing;
- Queue<System.Action> installQueue = new Queue<System.Action> ();
-
- public UpdateDialog ()
- {
- this.Build ();
- notebook1.ShowTabs = false;
- notebook1.ShowBorder = false;
-
- checkAutomaticallyCheck.Active = UpdateService.CheckAutomatically;
- checkAutomaticallyCheck.Toggled += delegate {
- UpdateService.CheckAutomatically = checkAutomaticallyCheck.Active;
- };
-
- updateLevelCombo.AppendText (GettextCatalog.GetString ("Stable")); // index = UpdateLevel.Stable
- updateLevelCombo.AppendText (GettextCatalog.GetString ("Beta (unstable)")); // index = UpdateLevel.Beta
- updateLevelCombo.AppendText (GettextCatalog.GetString ("Alpha (experimental)"));// index = UpdateLevel.Alpha
-
- updateLevelCombo.Active = (int) UpdateService.UpdateLevel;
-
- updateLevelCombo.Changed += delegate {
- var level = (UpdateLevel) updateLevelCombo.Active;
- UpdateService.UpdateLevel = level;
-
- var cachedResult = results.Where (r => r.Level == level).FirstOrDefault ();
-
- if (cachedResult != null && !cachedResult.HasError) {
- LoadUpdates (cachedResult.Updates);
- } else {
- SetMessage (GettextCatalog.GetString ("Checking for updates..."));
- UpdateService.QueryUpdateServer (UpdateService.DefaultUpdateInfos, level, delegate (UpdateResult result) {
- Application.Invoke (delegate {
- LoadResult (result);
- });
- });
- }
- };
-
- SetMessage (GettextCatalog.GetString ("Checking for updates..."));
- }
-
- public void LoadResult (UpdateResult result)
- {
- bool replaced = false;
- for (int i = 0; i < results.Count; i++) {
- if (result.Level == results[i].Level) {
- results[i] = result;
- replaced = true;
- break;
- }
- }
- if (!replaced)
- results.Add (result);
-
- if (result.HasError) {
- SetMessage (result.ErrorMessage);
- } else {
- LoadUpdates (result.Updates);
- }
- }
-
- void SetMessage (string message)
- {
- notebook1.CurrentPage = PAGE_MESSAGE;
- messageLabel.Text = message;
- }
-
- void LoadUpdates (List<Update> updates)
- {
- if (updates == null || updates.Count == 0) {
- SetMessage (GettextCatalog.GetString ("No updates available"));
- return;
- }
-
- foreach (var c in productBox.Children) {
- productBox.Remove (c);
- c.Destroy ();
- }
-
- productBox.Spacing = 0;
-
- foreach (var update in updates) {
- var updateBox = new VBox () { Spacing = 2 };
- var labelBox = new HBox () { Spacing = 3 };
- updateBox.PackStart (labelBox, false, false, 0);
-
- string warning = null;
- switch (update.Level) {
- case UpdateLevel.Alpha:
- warning = GettextCatalog.GetString ("ALPHA");
- break;
- case UpdateLevel.Beta:
- warning = GettextCatalog.GetString ("BETA");
- break;
- case UpdateLevel.Test:
- warning = GettextCatalog.GetString ("TEST");
- break;
- }
- if (warning != null)
- warning = "<b><span color=\"#DD1111\">" + warning + "</span></b>";
-
- var updateExpander = new Expander ("");
- updateExpander.LabelWidget = new Label () {
- Markup = string.Format ("<b>{0}</b>\n{1} ({2:yyyy-MM-dd}) {3}", update.Name, update.Version, update.Date,
- warning ?? ""),
- };
- labelBox.PackStart (updateExpander, true, true, 0);
-
- var commandBox = new Gtk.Alignment (0, 0.5f, 0, 0);
- labelBox.PackStart (commandBox, false, false, 0);
-
- var downloadButton = new Button () {
- Label = GettextCatalog.GetString ("Download")
- };
-
- //NOTE: grab the variable from the loop var so the closure captures it
- var updateVal = update;
- downloadButton.Clicked += delegate {
- Install (commandBox, downloadButton, updateVal);
- };
- commandBox.Add (downloadButton);
-
- var sb = new StringBuilder ();
- for (int i = 0; i < update.Releases.Count; i++) {
- var release = update.Releases[i];
- if (i > 0) {
- if (i == 1) {
- sb.AppendLine ();
- sb.AppendLine ("This release also includes previous updates:");
- }
- sb.AppendLine ();
- sb.AppendFormat ("{0} ({1:yyyy-MM-dd})\n", release.Version, release.Date);
- sb.AppendLine ();
- }
- sb.Append (release.Notes.Trim ('\t', ' ', '\n', '\r'));
- sb.AppendLine ();
- }
- var buffer = new TextBuffer (null);
- buffer.Text = sb.ToString ();
- var textView = new TextView (buffer);
- textView.WrapMode = WrapMode.Word;
- textView.Editable = false;
- textView.LeftMargin = textView.RightMargin = 4;
- updateBox.PackStart (textView, false, false, 0);
-
- bool startsExpanded = false;
- updateExpander.Expanded = startsExpanded;
- updateExpander.Activated += delegate {
- textView.Visible = updateExpander.Expanded;
- };
-
- updateBox.BorderWidth = 4;
-
- productBox.PackStart (updateBox, false, false, 0);
- updateBox.ShowAll ();
- //this has to be set false after the ShowAll
- textView.Visible = startsExpanded;
-
-
- var sep = new HSeparator ();
- productBox.PackStart (sep, false, false, 0);
- sep.Show ();
- }
-
- notebook1.CurrentPage = PAGE_UPDATES;
- }
-
- void Install (Gtk.Alignment commandBox, Button installButton, Update update)
- {
- DesktopService.ShowUrl (update.Url);
- }
- }
-}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateInfoExtensionNode.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateInfoExtensionNode.cs
deleted file mode 100644
index f03865ccf1..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateInfoExtensionNode.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// UpdateInfoExtensionNode.cs
-//
-// Author:
-// Michael Hutchinson <mhutchinson@novell.com>
-//
-// Copyright (c) 2010 Novell, Inc.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using Mono.Addins;
-
-namespace MonoDevelop.Ide.Updater
-{
- class UpdateInfoExtensionNode : ExtensionNode
- {
- [NodeAttribute (Required=true)]
- protected string file = null;
-
- public string File {
- get { return this.Addin.GetFilePath (file); }
- }
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateResult.cs
deleted file mode 100644
index c7cce6af28..0000000000
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateResult.cs
+++ /dev/null
@@ -1,117 +0,0 @@
-//
-// UpdateResult.cs
-//
-// Author:
-// Michael Hutchinson <mhutchinson@novell.com>
-//
-// Copyright (c) 2010 Novell, Inc. (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using System.Linq;
-using System.IO;
-using System.Text;
-using MonoDevelop.Core;
-using MonoDevelop.Core.Setup;
-using System.Net;
-using System.Collections.Generic;
-using System.Xml.Serialization;
-
-namespace MonoDevelop.Ide.Updater
-{
- public class Update
- {
- public string Name;
- public string Id;
- public int VersionId;
- public string Dependencies;
- public string Url;
- public string Version;
- public int Size;
- public string Hash;
- public bool IsThirdParty;
- public DateTime Date;
- public List<Release> Releases;
- public UpdateLevel Level;
-
- public string File { get; set; }
- public UpdateStatus Status { get; set; }
- public string UpdateInfoFile { get; set; }
- }
-
- public class Release
- {
- public string Version;
- public DateTime Date;
- public string Notes;
- }
-
- class UpdateInfo
- {
- UpdateInfo ()
- {
- }
-
- public UpdateInfo (string file, string appId, long versionId)
- {
- this.File = file;
- this.AppId = appId;
- this.VersionId = versionId;
- }
-
- public readonly string File;
- public readonly string AppId;
- public readonly long VersionId;
-
- public static UpdateInfo FromFile (string fileName)
- {
- using (var f = System.IO.File.OpenText (fileName)) {
- var s = f.ReadLine ();
- var parts = s.Split (' ');
- return new UpdateInfo (fileName, parts[0], long.Parse (parts[1]));
- }
- }
- }
-
- class UpdateResult
- {
- public UpdateResult (List<Update> updates, UpdateLevel level, string errorMessage, Exception errorDetail)
- {
- this.Updates = updates;
- this.Level = level;
- this.ErrorMessage = errorMessage;
- this.ErrorDetail = errorDetail;
- }
-
- public List<Update> Updates { get; private set; }
- public UpdateLevel Level { get; private set; }
- public string ErrorMessage { get; private set; }
- public Exception ErrorDetail { get; private set; }
-
- public bool HasError {
- get { return !string.IsNullOrEmpty (ErrorMessage); }
- }
-
- public bool HasUpdates {
- get { return Updates != null && Updates.Count > 0; }
- }
- }
-}
-
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs
index 1b1699b2bd..1ee46bb8a4 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Updater/UpdateService.cs
@@ -1,10 +1,10 @@
//
-// MacUpdater.cs
+// UpdateService.cs
//
// Author:
-// Michael Hutchinson <mhutchinson@novell.com>
+// Lluis Sanchez <lluis@xamarin.com>
//
-// Copyright (c) 2009 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2011 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -24,506 +24,112 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-//#define ENABLE_UPDATER
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Text;
-using System.Linq;
-using MonoDevelop.Core;
using MonoDevelop.Core.Setup;
-using MonoDevelop.Ide;
-using MonoDevelop.Ide.Gui;
-using System.Globalization;
+using MonoDevelop.Core;
+using System;
using Mono.Addins;
-using Mono.Addins.Setup;
using MonoDevelop.Core.ProgressMonitoring;
-
+using System.Threading;
namespace MonoDevelop.Ide.Updater
{
- static class UpdateService
+ public static class UpdateService
{
- const int formatVersion = 1;
- const string updateAutoPropertyKey = "AppUpdater.CheckAutomatically";
- const string updateLevelKey = "AppUpdate.UpdateLevel";
-
- static UpdateInfo[] updateInfos;
- static List<string> tags = new List<string> ();
-
- static UpdateInfo[] LoadUpdateInfos ()
- {
- if (string.IsNullOrEmpty (DesktopService.GetUpdaterUrl ()))
- return new UpdateInfo[0];
-
- var list = new List<UpdateInfo> ();
- foreach (var node in Mono.Addins.AddinManager.GetExtensionNodes ("/MonoDevelop/Ide/Updater")) {
- var n = node as UpdateInfoExtensionNode;
- if (n == null)
- continue;
- string file = n.File;
- if (!File.Exists (file))
- continue;
-
- try {
- var uinfo = UpdateInfo.FromFile (file);
- if (uinfo.AppId == InstallerUpdateId) {
- // If there is an updated installer, get the update info for that one
- var installerUpdateInfo = UpdatedInstallerPath.Combine (InstallerUpdateId + ".updateinfo");
- if (File.Exists (installerUpdateInfo)) {
- var localuinfo = UpdateInfo.FromFile (installerUpdateInfo);
- if (localuinfo.VersionId > uinfo.VersionId)
- uinfo = localuinfo;
- }
- }
- list.Add (uinfo);
- } catch (Exception ex) {
- LoggingService.LogError ("Error reading update info file '" + file + "'", ex);
- }
+ public static bool AutoCheckForUpdates {
+ get {
+ return PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.CkeckForUpdates", true);
+ }
+ set {
+ PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.CkeckForUpdates", value);
}
- return list.ToArray ();
- }
-
- static FilePath UpdatedInstallerPath {
- get { return PropertyService.Locations.Data.Combine ("Installer"); }
}
- static UpdateService ()
- {
-#if ENABLE_UPDATER
- updateInfos = LoadUpdateInfos ();
- AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Ide/UpdateTags", OnTagExtensionChanged);
-
- DownloadService.Initialize ();
- DownloadService.DownloadFinished += HandleDownloadServiceDownloadFinished;
-#endif
- }
-
- static void HandleDownloadServiceDownloadFinished (object sender, EventArgs e)
- {
- if (!DownloadService.AllDownloaded)
- return;
- var downloads = DownloadService.GetAllDownloads ();
-
- // Check if there is an update for the installer
- var installer = downloads.FirstOrDefault (d => d.Id == InstallerUpdateId);
- if (installer != null) {
- string file = InstallerUpdateId + Path.GetExtension (installer.File);
- if (Directory.Exists (UpdatedInstallerPath))
- Directory.Delete (UpdatedInstallerPath, true);
- Directory.CreateDirectory (UpdatedInstallerPath);
-
- // Copy the updated installer to a local directory
- var installerPath = UpdatedInstallerPath.Combine (file);
- var updateInfoPath = UpdatedInstallerPath.Combine (InstallerUpdateId + ".updateinfo");
- File.Copy (installer.File, installerPath, true);
- File.WriteAllText (updateInfoPath, InstallerUpdateId + " " + installer.VersionId);
- DownloadService.Remove (installer);
- downloads = DownloadService.GetAllDownloads ();
-
- // Update hte updateInfos list, and replace the old update info with the new updater
- var ui = updateInfos.FirstOrDefault (u => u.AppId == InstallerUpdateId);
- if (ui != null)
- updateInfos [Array.IndexOf (updateInfos, ui)] = new UpdateInfo (updateInfoPath, InstallerUpdateId, installer.VersionId);
+ public static UpdateSpanUnit UpdateSpanUnit {
+ get {
+ return PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateSpanUnit", UpdateSpanUnit.Day);
}
- if (downloads.Any ()) {
- InstallDialog dlg = new InstallDialog (downloads);
- if (MessageService.RunCustomDialog (dlg) == (int) Gtk.ResponseType.Ok) {
- DownloadService.MarkForInstallation (dlg.UpdatesToInstall);
- var installerPath = Directory.GetFiles (UpdatedInstallerPath).FirstOrDefault (f => Path.GetExtension (f) != ".updateinfo");
- DesktopService.StartUpdatesInstaller (DownloadService.DownloadIndex, installerPath);
- }
- dlg.Destroy ();
+ set {
+ PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.UpdateSpanUnit", value);
}
}
- static void OnTagExtensionChanged (object sender, ExtensionNodeEventArgs args)
- {
- if (args.Change == ExtensionChange.Add)
- tags.Add (args.ExtensionNode.Id);
- else
- tags.Remove (args.ExtensionNode.Id);
- }
-
- public static void AddUpdateTag (string tag)
- {
- tags.Add (tag);
- }
-
- public static void RemoteUpdateTag (string tag)
- {
- tags.Remove (tag);
- }
-
- public static bool CanUpdate {
- get { return true; }
- }
-
- public static UpdateInfo[] DefaultUpdateInfos {
- get { return updateInfos; }
- }
-
- public static bool CheckAutomatically {
+ public static int UpdateSpanValue {
get {
- return PropertyService.Get<bool> (updateAutoPropertyKey, true);
+ return PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateSpanValue", 1);
}
set {
- PropertyService.Set (updateAutoPropertyKey, value);
+ PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.UpdateSpanValue", value);
}
}
public static UpdateLevel UpdateLevel {
get {
- return PropertyService.Get<UpdateLevel> (updateLevelKey, UpdateLevel.Stable);
+ return PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.UpdateLevel", UpdateLevel.Stable);
}
set {
- PropertyService.Set (updateLevelKey, value);
+ PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.UpdateLevel", value);
}
}
- internal static string InstallerUpdateId {
- get { return "updater-" + DesktopService.PlatformName; }
- }
-
- public static void RunCheckDialog (bool automatic)
- {
- RunCheckDialog (DefaultUpdateInfos, automatic);
- }
-
- public static void RunCheckDialog (UpdateInfo[] updateInfos, bool automatic)
+ internal static void ScheduledCheckForUpdates ()
{
- if (!CanUpdate || (automatic && !CheckAutomatically))
+ if (!AutoCheckForUpdates)
return;
- if (!automatic) {
- ShowUpdateDialog ();
- QueryUpdateServer (updateInfos, UpdateLevel, delegate (UpdateResult result) {
- ShowUpdateResult (result);
- });
- } else {
- QueryUpdateServer (updateInfos, UpdateLevel, delegate (UpdateResult result) {
- if (result.HasError || !result.HasUpdates)
- return;
- ShowUpdateDialog ();
- ShowUpdateResult (result);
- });
- }
- }
-
- #region Singleton dialog management. Methods are threadsafe, field is not
-
- static UpdateDialog visibleDialog;
-
- static void ShowUpdateDialog ()
- {
-/* Gtk.Application.Invoke (delegate {
- if (visibleDialog == null) {
- visibleDialog = new UpdateDialog ();
- MessageService.ShowCustomDialog (visibleDialog);
- visibleDialog = null;
- } else {
- visibleDialog.GdkWindow.Focus (0);
- }
- });
- SetupDownloader (result);*/
- }
-
- static void ShowUpdateResult (UpdateResult result)
- {
-/* Gtk.Application.Invoke (delegate {
- if (visibleDialog != null)
- visibleDialog.LoadResult (result);
- });*/
- SetupDownloader (result);
- }
-
- static void SetupDownloader (UpdateResult result)
- {
- DownloadService.SetUpdates (result.Updates);
- }
-
- #endregion
-
- public static void QueryUpdateServer (UpdateInfo[] updateInfos, UpdateLevel level, Action<UpdateResult> callback)
- {
- if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("MONODEVELOP_UPDATER_TEST")))
- level = UpdateLevel.Test;
-
- if (updateInfos == null || updateInfos.Length == 0) {
- QueryAddinUpdates (level, callback);
- return;
- }
-
- var query = new StringBuilder (DesktopService.GetUpdaterUrl ());
- query.Append ("?v=");
- query.Append (formatVersion);
-
- foreach (var info in updateInfos)
- query.AppendFormat ("&pv{0}={1}", info.AppId, info.VersionId);
-
- if (level != UpdateLevel.Stable) {
- query.Append ("&level=");
- query.Append (level.ToString ());
- }
-
- bool hasEnv = false;
- foreach (string flag in DesktopService.GetUpdaterEnvironmentFlags ()) {
- if (!hasEnv) {
- hasEnv = true;
- query.Append ("&env=");
- query.Append (flag);
- } else {
- query.Append (",");
- query.Append (flag);
- }
- }
-
- var requestUrl = query.ToString ();
- var request = (HttpWebRequest) WebRequest.Create (requestUrl);
-
- LoggingService.LogDebug ("Checking for updates: {0}", requestUrl);
-
- //FIXME: use IfModifiedSince, with a cached value
- //request.IfModifiedSince = somevalue;
+ DateTime lastUpdate = PropertyService.Get ("MonoDevelop.Ide.AddinUpdater.LastCheck", DateTime.MinValue);
- request.BeginGetResponse (delegate (IAsyncResult ar) {
- ReceivedResponse (request, ar, level, callback);
- }, null);
- }
-
- static void ReceivedResponse (HttpWebRequest request, IAsyncResult ar, UpdateLevel level, Action<UpdateResult> callback)
- {
- List<Update> updates = null;
- string error = null;
- Exception errorDetail = null;
-
- try {
- using (var response = (HttpWebResponse) request.EndGetResponse (ar)) {
- var encoding = !string.IsNullOrEmpty (response.CharacterSet) ? Encoding.GetEncoding (response.CharacterSet) : Encoding.UTF8;
- using (var reader = new StreamReader (response.GetResponseStream(), encoding)) {
- var doc = System.Xml.Linq.XDocument.Load (reader);
- updates = (from x in doc.Root.Elements ("Application")
- let first = x.Elements ("Update").First ()
- select new Update () {
- Name = x.Attribute ("name").Value,
- Id = x.Attribute ("id").Value,
- VersionId = int.Parse (first.Attribute ("versionId").Value),
- Dependencies = x.Attribute ("dependencies").Value,
- Url = first.Attribute ("url").Value,
- Version = first.Attribute ("version").Value,
- Size = int.Parse (first.Attribute ("size").Value),
- Hash = first.Attribute ("hash").Value,
- Level = first.Attribute ("level") != null
- ? (UpdateLevel)Enum.Parse (typeof(UpdateLevel), (string)first.Attribute ("level"))
- : UpdateLevel.Stable,
- Date = DateTime.Parse (first.Attribute ("date").Value),
- UpdateInfoFile = updateInfos.Where (u => u.AppId == x.Attribute ("id").Value).Select (u => u.File).FirstOrDefault (),
- Releases = x.Elements ("Update").Select (y => new Release () {
- Version = y.Attribute ("version").Value,
- Date = DateTime.Parse (y.Attribute ("date").Value),
- Notes = y.Value
- }).ToList ()
- }).ToList ();
- }
- }
-
- CheckAddinUpdates (updates, level);
-
- } catch (Exception ex) {
- LoggingService.LogError ("Could not retrieve update information", ex);
- error = GettextCatalog.GetString ("Error retrieving update information");
- errorDetail = ex;
+ bool check = false;
+ if (UpdateSpanUnit == UpdateSpanUnit.Hour) {
+ lastUpdate = lastUpdate.Date;
+ check = (DateTime.Now - lastUpdate).TotalHours >= UpdateSpanValue;
+ } else if (UpdateSpanUnit == UpdateSpanUnit.Day) {
+ lastUpdate = lastUpdate.Date;
+ check = (DateTime.Now - lastUpdate).TotalDays >= UpdateSpanValue;
+ } else {
+ lastUpdate = new DateTime (lastUpdate.Year, lastUpdate.Month, 1, 0, 0, 0);
+ check = DateTime.Now >= lastUpdate.AddMonths (UpdateSpanValue);
}
-
- callback (new UpdateResult (updates, level, error, errorDetail));
- }
-
- public static void QueryAddinUpdates (UpdateLevel level, Action<UpdateResult> callback)
- {
- System.Threading.ThreadPool.QueueUserWorkItem (delegate {
- List<Update> updates = new List<Update> ();
- string error = null;
- Exception errorDetail = null;
-
- try {
- CheckAddinUpdates (updates, level);
-
- } catch (Exception ex) {
- LoggingService.LogError ("Could not retrieve update information", ex);
- error = GettextCatalog.GetString ("Error retrieving update information");
- errorDetail = ex;
- }
- callback (new UpdateResult (updates, level, error, errorDetail));
- });
+ if (check)
+ CheckForUpdates ();
}
- static void CheckAddinUpdates (List<Update> updates, UpdateLevel level)
+ public static void CheckForUpdates ()
{
- for (UpdateLevel n=UpdateLevel.Stable; n<=level; n++)
- Runtime.AddinSetupService.RegisterMainRepository ((UpdateLevel)n, true);
+ PropertyService.Set ("MonoDevelop.Ide.AddinUpdater.LastCheck", DateTime.Now);
+ PropertyService.SaveProperties ();
+ var handlers = AddinManager.GetExtensionObjects ("/MonoDevelop/Ide/Updater/UpdateHandlers");
- AddinUpdateHandler.QueryAddinUpdates ();
-
- updates.AddRange (GetAddinUpdates (UpdateLevel.Stable));
- if (level >= UpdateLevel.Beta)
- updates.AddRange (GetAddinUpdates (UpdateLevel.Beta));
- if (level >= UpdateLevel.Alpha)
- updates.AddRange (GetAddinUpdates (UpdateLevel.Alpha));
- if (level == UpdateLevel.Test)
- updates.AddRange (GetAddinUpdates (UpdateLevel.Test));
- }
-
- static IEnumerable<Update> GetAddinUpdates (UpdateLevel level)
- {
- List<Update> res = new List<Update> ();
- string url = Runtime.AddinSetupService.GetMainRepositoryUrl (level);
- List<AddinRepositoryEntry> list = new List<AddinRepositoryEntry> ();
- list.AddRange (Runtime.AddinSetupService.Repositories.GetAvailableUpdates (url));
- FilterOldVersions (list);
- foreach (var ventry in list) {
- var entry = ventry;
- UpdateRank rank = GetUpdateRank (entry.Addin.Properties.GetPropertyValue ("UpdateRank"));
- if (rank != UpdateRank.Important)
- continue;
- string sdate = entry.Addin.Properties.GetPropertyValue ("ReleaseDate");
- DateTime date;
- if (!string.IsNullOrEmpty (sdate))
- date = DateTime.Parse (sdate, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
- else
- date = DateTime.Now;
- res.Add (new Update () {
- Name = entry.Addin.Name,
- Url = entry.Url,
- Version = entry.Addin.Version,
- Level = level,
- Date = date,
- Releases = ParseReleases (entry.Addin.Id, entry).ToList ()
- });
- }
- return res;
- }
-
- static void FilterOldVersions (List<AddinRepositoryEntry> addins)
- {
- Dictionary<string,string> versions = new Dictionary<string, string> ();
- foreach (AddinRepositoryEntry a in addins) {
- string last;
- string id, version;
- Addin.GetIdParts (a.Addin.Id, out id, out version);
- if (!versions.TryGetValue (id, out last) || Addin.CompareVersions (last, version) > 0)
- versions [id] = version;
- }
- for (int n=0; n<addins.Count; n++) {
- AddinRepositoryEntry a = addins [n];
- string id, version;
- Addin.GetIdParts (a.Addin.Id, out id, out version);
- if (versions [id] != version)
- addins.RemoveAt (n--);
- }
+ IProgressMonitor mon = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor ("Looking for updates", "md-software-update");
+
+ Thread t = new Thread (delegate () {
+ CheckUpdates (mon, handlers);
+ });
+ t.Name = "Addin updater";
+ t.Start ();
}
- static IEnumerable<Release> ParseReleases (string addinId, AddinRepositoryEntry entry)
+ static void CheckUpdates (IProgressMonitor monitor, object[] handlers)
{
- // Format of release notes is:
- // {{version1,date1}} release note text {{version2,date2}} release note text ...
- // Releases msyu
- // for example:
- // {{1.1,2011-01-10}} Release notes for 1.1 {{1.2,2011-03-22}} Release notes for 2.3
-
- string releaseNotes = entry.Addin.Properties.GetPropertyValue ("ReleaseNotes");
- if (releaseNotes.Length == 0) {
- string file = entry.Addin.Properties.GetPropertyValue ("ReleaseNotesFile");
- if (file.Length > 0) {
- IAsyncResult res = entry.BeginDownloadSupportFile (file, null, null);
- res.AsyncWaitHandle.WaitOne ();
+ using (monitor) {
+ monitor.BeginTask ("Looking for updates", handlers.Length);
+ foreach (IUpdateHandler uh in handlers) {
try {
- using (Stream s = entry.EndDownloadSupportFile (res)) {
- StreamReader sr = new StreamReader (s);
- releaseNotes = sr.ReadToEnd ();
- }
+ uh.CheckUpdates (monitor);
} catch (Exception ex) {
- LoggingService.LogError ("Could not download release notes", ex);
+ LoggingService.LogError ("Updates check failed for handler of type '" + uh.GetType () + "'", ex);
}
+ monitor.Step (1);
}
+ monitor.EndTask ();
}
-
- if (releaseNotes.Length == 0)
- yield break;
-
- var addin = AddinManager.Registry.GetAddin (Addin.GetIdName (addinId));
- string currentVersion = addin != null ? addin.Version : null;
-
- int i = releaseNotes.IndexOf ("{{");
- while (i != -1) {
- int j = releaseNotes.IndexOf ("}}", i + 2);
- if (j == -1)
- break;
- string[] h = releaseNotes.Substring (i + 2, j - i - 2).Trim ().Split (',');
- if (h.Length != 2)
- break;
- DateTime date;
- if (!DateTime.TryParse (h[1].Trim (), CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out date))
- break;
- int k = releaseNotes.IndexOf ("{{", j + 2);
- string version = h[0].Trim ();
- if (currentVersion == null || Addin.CompareVersions (currentVersion, version) > 0) {
- string txt = k != -1 ? releaseNotes.Substring (j + 2, k - j - 2) : releaseNotes.Substring (j + 2);
- yield return new Release () {
- Version = version,
- Date = date,
- Notes = txt.Trim (' ','\t','\r','\n')
- };
- }
- i = k;
- }
- }
-
- static IAsyncOperation InstallAddin (IProgressMonitor monitor, AddinRepositoryEntry addin)
- {
- // Add-in engine changes must be done in the gui thread since mono.addins is not thread safe
- DispatchService.GuiDispatch (delegate {
- using (monitor) {
- Runtime.AddinSetupService.Install (new ProgressStatusMonitor (monitor), addin);
- }
- });
- return monitor.AsyncOperation;
- }
-
- /// <summary>
- /// Parses an update rank string
- /// </summary>
- /// <returns>
- /// The update rank
- /// </returns>
- /// <param name='updateRankString'>
- /// Update rank string.
- /// </param>
- /// <remarks>
- /// This method parses an update rank string. If the rank is conditioned to an update tag, it will
- /// check the presence of the tag
- /// </remarks>
- internal static UpdateRank GetUpdateRank (string updateRankString)
- {
- string slevel = null;
- foreach (string cond in updateRankString.Split (new char[] {' '}, StringSplitOptions.RemoveEmptyEntries)) {
- int i = cond.IndexOf (':');
- if (i == -1) {
- slevel = cond;
- break;
- }
- if (tags.Contains (cond.Substring (0, i))) {
- slevel = cond.Substring (i+1);
- break;
- }
- }
- UpdateRank level;
- if (slevel != null && Enum.TryParse<UpdateRank> (slevel, out level))
- return level;
- else
- return UpdateRank.Normal;
}
}
+
+ public enum UpdateSpanUnit
+ {
+ Hour,
+ Day,
+ Month
+ }
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
index 8748748948..ff5a3816de 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
@@ -875,7 +875,6 @@
<Compile Include="MonoDevelop.Ide.Gui\Workbench.cs" />
<Compile Include="MonoDevelop.Ide.Gui\StartupInfo.cs" />
<Compile Include="MonoDevelop.Ide.Gui\ProgressMonitors.cs" />
- <Compile Include="MonoDevelop.Ide.Gui\AddinUpdateHandler.cs" />
<Compile Include="MonoDevelop.Ide\Services.cs" />
<Compile Include="MonoDevelop.Ide.Gui.OptionPanels\TasksOptionsPanel.cs" />
<Compile Include="MonoDevelop.Ide.Gui\FileViewer.cs" />
@@ -1450,6 +1449,10 @@
<Compile Include="MonoDevelop.Components.PropertyGrid.Editors\FilePathEditor.cs" />
<Compile Include="MonoDevelop.Ide.Gui.Dialogs\FeedbackDialog.cs" />
<Compile Include="MonoDevelop.Ide\FeedbackService.cs" />
+ <Compile Include="MonoDevelop.Ide.Updater\UpdateService.cs" />
+ <Compile Include="MonoDevelop.Ide.Updater\IUpdateHandler.cs" />
+ <Compile Include="MonoDevelop.Ide.Updater\AddinsUpdateHandler.cs" />
+ <Compile Include="MonoDevelop.Ide.Updater\UpdateCheckHandler.cs" />
</ItemGroup>
<ItemGroup>
<None Include="ChangeLog" />
diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget.cs b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget.cs
index 3f4668a93c..31259fb3a8 100644
--- a/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget.cs
+++ b/main/src/core/MonoDevelop.Ide/gtk-gui/MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget.cs
@@ -5,15 +5,22 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
internal partial class AddInsPanelWidget
{
private global::Gtk.VBox vbox72;
- private global::Gtk.CheckButton lookCheck;
- private global::Gtk.HBox hbox46;
- private global::Gtk.Label label104;
- private global::Gtk.Label label105;
- private global::Gtk.SpinButton valueSpin;
- private global::Gtk.ComboBox periodCombo;
- private global::Gtk.HSeparator hseparator1;
+ private global::Gtk.Label label2;
+ private global::Gtk.Alignment alignment3;
+ private global::Gtk.VBox vbox5;
+ private global::Gtk.RadioButton radioHour;
+ private global::Gtk.RadioButton radioDay;
+ private global::Gtk.RadioButton radioMonth;
+ private global::Gtk.RadioButton radioNever;
+ private global::Gtk.CheckButton checkUnstable;
private global::Gtk.HBox hbox47;
- private global::Gtk.Button managerButton;
+ private global::Gtk.Alignment boxUnstable;
+ private global::Gtk.VBox vbox6;
+ private global::Gtk.RadioButton radioBeta;
+ private global::Gtk.RadioButton radioAlpha;
+ private global::Gtk.RadioButton radioTest;
+ private global::Gtk.HBox hbox3;
+ private global::Gtk.Button buttonUpdateNow;
protected virtual void Build ()
{
@@ -26,102 +33,176 @@ namespace MonoDevelop.Ide.Gui.OptionPanels
this.vbox72.Name = "vbox72";
this.vbox72.Spacing = 6;
// Container child vbox72.Gtk.Box+BoxChild
- this.lookCheck = new global::Gtk.CheckButton ();
- this.lookCheck.Name = "lookCheck";
- this.lookCheck.Label = global::MonoDevelop.Core.GettextCatalog.GetString ("Look for add-in updates at startup, with the following periodicity:");
- this.lookCheck.DrawIndicator = true;
- this.lookCheck.UseUnderline = true;
- this.vbox72.Add (this.lookCheck);
- global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.lookCheck]));
+ this.label2 = new global::Gtk.Label ();
+ this.label2.Name = "label2";
+ this.label2.Xalign = 0F;
+ this.label2.LabelProp = global::MonoDevelop.Core.GettextCatalog.GetString ("Automatically check for updates:");
+ this.vbox72.Add (this.label2);
+ global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.label2]));
w1.Position = 0;
w1.Expand = false;
w1.Fill = false;
// Container child vbox72.Gtk.Box+BoxChild
- this.hbox46 = new global::Gtk.HBox ();
- this.hbox46.Name = "hbox46";
- this.hbox46.Spacing = 6;
- // Container child hbox46.Gtk.Box+BoxChild
- this.label104 = new global::Gtk.Label ();
- this.label104.WidthRequest = 24;
- this.label104.Name = "label104";
- this.label104.Xalign = 0F;
- this.label104.Yalign = 0F;
- this.hbox46.Add (this.label104);
- global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox46 [this.label104]));
+ this.alignment3 = new global::Gtk.Alignment (0.5F, 0.5F, 1F, 1F);
+ this.alignment3.Name = "alignment3";
+ this.alignment3.LeftPadding = ((uint)(24));
+ this.alignment3.BottomPadding = ((uint)(6));
+ // Container child alignment3.Gtk.Container+ContainerChild
+ this.vbox5 = new global::Gtk.VBox ();
+ this.vbox5.Name = "vbox5";
+ this.vbox5.Spacing = 6;
+ // Container child vbox5.Gtk.Box+BoxChild
+ this.radioHour = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Every hour"));
+ this.radioHour.CanFocus = true;
+ this.radioHour.Name = "radioHour";
+ this.radioHour.DrawIndicator = true;
+ this.radioHour.UseUnderline = true;
+ this.radioHour.Group = new global::GLib.SList (global::System.IntPtr.Zero);
+ this.vbox5.Add (this.radioHour);
+ global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.vbox5 [this.radioHour]));
w2.Position = 0;
w2.Expand = false;
w2.Fill = false;
- // Container child hbox46.Gtk.Box+BoxChild
- this.label105 = new global::Gtk.Label ();
- this.label105.Name = "label105";
- this.label105.Xalign = 0F;
- this.label105.LabelProp = global::MonoDevelop.Core.GettextCatalog.GetString ("Every");
- this.hbox46.Add (this.label105);
- global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox46 [this.label105]));
+ // Container child vbox5.Gtk.Box+BoxChild
+ this.radioDay = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Every day"));
+ this.radioDay.CanFocus = true;
+ this.radioDay.Name = "radioDay";
+ this.radioDay.DrawIndicator = true;
+ this.radioDay.UseUnderline = true;
+ this.radioDay.Group = this.radioHour.Group;
+ this.vbox5.Add (this.radioDay);
+ global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.vbox5 [this.radioDay]));
w3.Position = 1;
w3.Expand = false;
w3.Fill = false;
- // Container child hbox46.Gtk.Box+BoxChild
- this.valueSpin = new global::Gtk.SpinButton (0, 100, 1);
- this.valueSpin.Name = "valueSpin";
- this.valueSpin.Adjustment.PageIncrement = 10;
- this.valueSpin.ClimbRate = 1;
- this.valueSpin.Numeric = true;
- this.valueSpin.Value = 1;
- this.hbox46.Add (this.valueSpin);
- global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox46 [this.valueSpin]));
+ // Container child vbox5.Gtk.Box+BoxChild
+ this.radioMonth = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Every month"));
+ this.radioMonth.CanFocus = true;
+ this.radioMonth.Name = "radioMonth";
+ this.radioMonth.DrawIndicator = true;
+ this.radioMonth.UseUnderline = true;
+ this.radioMonth.Group = this.radioHour.Group;
+ this.vbox5.Add (this.radioMonth);
+ global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.vbox5 [this.radioMonth]));
w4.Position = 2;
w4.Expand = false;
w4.Fill = false;
- // Container child hbox46.Gtk.Box+BoxChild
- this.periodCombo = global::Gtk.ComboBox.NewText ();
- this.periodCombo.AppendText (global::MonoDevelop.Core.GettextCatalog.GetString ("Days"));
- this.periodCombo.AppendText (global::MonoDevelop.Core.GettextCatalog.GetString ("Months"));
- this.periodCombo.Name = "periodCombo";
- this.periodCombo.Active = 0;
- this.hbox46.Add (this.periodCombo);
- global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.hbox46 [this.periodCombo]));
+ // Container child vbox5.Gtk.Box+BoxChild
+ this.radioNever = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Never"));
+ this.radioNever.CanFocus = true;
+ this.radioNever.Name = "radioNever";
+ this.radioNever.DrawIndicator = true;
+ this.radioNever.UseUnderline = true;
+ this.radioNever.Group = this.radioHour.Group;
+ this.vbox5.Add (this.radioNever);
+ global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.vbox5 [this.radioNever]));
w5.Position = 3;
w5.Expand = false;
w5.Fill = false;
- this.vbox72.Add (this.hbox46);
- global::Gtk.Box.BoxChild w6 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.hbox46]));
- w6.Position = 1;
- w6.Expand = false;
- w6.Fill = false;
- // Container child vbox72.Gtk.Box+BoxChild
- this.hseparator1 = new global::Gtk.HSeparator ();
- this.hseparator1.Name = "hseparator1";
- this.vbox72.Add (this.hseparator1);
- global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.hseparator1]));
- w7.Position = 2;
+ this.alignment3.Add (this.vbox5);
+ this.vbox72.Add (this.alignment3);
+ global::Gtk.Box.BoxChild w7 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.alignment3]));
+ w7.Position = 1;
w7.Expand = false;
w7.Fill = false;
// Container child vbox72.Gtk.Box+BoxChild
+ this.checkUnstable = new global::Gtk.CheckButton ();
+ this.checkUnstable.CanFocus = true;
+ this.checkUnstable.Name = "checkUnstable";
+ this.checkUnstable.Label = global::MonoDevelop.Core.GettextCatalog.GetString ("Install unstable developer updates");
+ this.checkUnstable.Active = true;
+ this.checkUnstable.DrawIndicator = true;
+ this.checkUnstable.UseUnderline = true;
+ this.vbox72.Add (this.checkUnstable);
+ global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.checkUnstable]));
+ w8.Position = 2;
+ w8.Expand = false;
+ w8.Fill = false;
+ // Container child vbox72.Gtk.Box+BoxChild
this.hbox47 = new global::Gtk.HBox ();
this.hbox47.Name = "hbox47";
// Container child hbox47.Gtk.Box+BoxChild
- this.managerButton = new global::Gtk.Button ();
- this.managerButton.Name = "managerButton";
- this.managerButton.UseUnderline = true;
- this.managerButton.Label = global::MonoDevelop.Core.GettextCatalog.GetString ("Add-in Manager...");
- this.hbox47.Add (this.managerButton);
- global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.hbox47 [this.managerButton]));
- w8.Position = 0;
- w8.Expand = false;
- w8.Fill = false;
- this.vbox72.Add (this.hbox47);
- global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.hbox47]));
- w9.Position = 3;
+ this.boxUnstable = new global::Gtk.Alignment (0.5F, 0.5F, 1F, 1F);
+ this.boxUnstable.Name = "boxUnstable";
+ this.boxUnstable.LeftPadding = ((uint)(24));
+ // Container child boxUnstable.Gtk.Container+ContainerChild
+ this.vbox6 = new global::Gtk.VBox ();
+ this.vbox6.Name = "vbox6";
+ this.vbox6.Spacing = 6;
+ // Container child vbox6.Gtk.Box+BoxChild
+ this.radioBeta = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Beta updates (weekly)"));
+ this.radioBeta.CanFocus = true;
+ this.radioBeta.Name = "radioBeta";
+ this.radioBeta.DrawIndicator = true;
+ this.radioBeta.UseUnderline = true;
+ this.radioBeta.Group = new global::GLib.SList (global::System.IntPtr.Zero);
+ this.vbox6.Add (this.radioBeta);
+ global::Gtk.Box.BoxChild w9 = ((global::Gtk.Box.BoxChild)(this.vbox6 [this.radioBeta]));
+ w9.Position = 0;
w9.Expand = false;
w9.Fill = false;
+ // Container child vbox6.Gtk.Box+BoxChild
+ this.radioAlpha = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Alpha updates (very often, very unstable)"));
+ this.radioAlpha.CanFocus = true;
+ this.radioAlpha.Name = "radioAlpha";
+ this.radioAlpha.DrawIndicator = true;
+ this.radioAlpha.UseUnderline = true;
+ this.radioAlpha.Group = this.radioBeta.Group;
+ this.vbox6.Add (this.radioAlpha);
+ global::Gtk.Box.BoxChild w10 = ((global::Gtk.Box.BoxChild)(this.vbox6 [this.radioAlpha]));
+ w10.Position = 1;
+ w10.Expand = false;
+ w10.Fill = false;
+ // Container child vbox6.Gtk.Box+BoxChild
+ this.radioTest = new global::Gtk.RadioButton (global::MonoDevelop.Core.GettextCatalog.GetString ("Test"));
+ this.radioTest.CanFocus = true;
+ this.radioTest.Name = "radioTest";
+ this.radioTest.DrawIndicator = true;
+ this.radioTest.UseUnderline = true;
+ this.radioTest.Group = this.radioBeta.Group;
+ this.vbox6.Add (this.radioTest);
+ global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.vbox6 [this.radioTest]));
+ w11.Position = 2;
+ w11.Expand = false;
+ w11.Fill = false;
+ this.boxUnstable.Add (this.vbox6);
+ this.hbox47.Add (this.boxUnstable);
+ global::Gtk.Box.BoxChild w13 = ((global::Gtk.Box.BoxChild)(this.hbox47 [this.boxUnstable]));
+ w13.Position = 0;
+ this.vbox72.Add (this.hbox47);
+ global::Gtk.Box.BoxChild w14 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.hbox47]));
+ w14.Position = 3;
+ w14.Expand = false;
+ w14.Fill = false;
+ // Container child vbox72.Gtk.Box+BoxChild
+ this.hbox3 = new global::Gtk.HBox ();
+ this.hbox3.Name = "hbox3";
+ this.hbox3.Spacing = 6;
+ this.hbox3.BorderWidth = ((uint)(12));
+ // Container child hbox3.Gtk.Box+BoxChild
+ this.buttonUpdateNow = new global::Gtk.Button ();
+ this.buttonUpdateNow.CanFocus = true;
+ this.buttonUpdateNow.Name = "buttonUpdateNow";
+ this.buttonUpdateNow.UseUnderline = true;
+ this.buttonUpdateNow.Label = global::MonoDevelop.Core.GettextCatalog.GetString ("Check for Updates Now");
+ this.hbox3.Add (this.buttonUpdateNow);
+ global::Gtk.Box.BoxChild w15 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.buttonUpdateNow]));
+ w15.Position = 0;
+ w15.Expand = false;
+ w15.Fill = false;
+ this.vbox72.Add (this.hbox3);
+ global::Gtk.Box.BoxChild w16 = ((global::Gtk.Box.BoxChild)(this.vbox72 [this.hbox3]));
+ w16.Position = 4;
+ w16.Expand = false;
+ w16.Fill = false;
this.Add (this.vbox72);
if ((this.Child != null)) {
this.Child.ShowAll ();
}
+ this.radioTest.Hide ();
this.Show ();
- this.lookCheck.Clicked += new global::System.EventHandler (this.OnCheckToggled);
- this.managerButton.Clicked += new global::System.EventHandler (this.OnManageClicked);
+ this.checkUnstable.Toggled += new global::System.EventHandler (this.OnCheckUnstableToggled);
+ this.buttonUpdateNow.Clicked += new global::System.EventHandler (this.OnButtonUpdateNowClicked);
}
}
}
diff --git a/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic b/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic
index 59dbc570d0..c8efc1d00c 100644
--- a/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic
+++ b/main/src/core/MonoDevelop.Ide/gtk-gui/gui.stetic
@@ -2283,7 +2283,7 @@ Diagnostic</property>
</widget>
</child>
</widget>
- <widget class="Gtk.Bin" id="MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget" design-size="408 100">
+ <widget class="Gtk.Bin" id="MonoDevelop.Ide.Gui.OptionPanels.AddInsPanelWidget" design-size="473 300">
<property name="MemberName" />
<property name="GeneratePublic">False</property>
<child>
@@ -2291,99 +2291,120 @@ Diagnostic</property>
<property name="MemberName" />
<property name="Spacing">6</property>
<child>
- <widget class="Gtk.CheckButton" id="lookCheck">
+ <widget class="Gtk.Label" id="label2">
<property name="MemberName" />
- <property name="Label" translatable="yes">Look for add-in updates at startup, with the following periodicity:</property>
- <property name="DrawIndicator">True</property>
- <property name="HasLabel">True</property>
- <property name="UseUnderline">True</property>
- <signal name="Clicked" handler="OnCheckToggled" />
+ <property name="Xalign">0</property>
+ <property name="LabelProp" translatable="yes">Automatically check for updates:</property>
</widget>
<packing>
<property name="Position">0</property>
- <property name="AutoSize">False</property>
+ <property name="AutoSize">True</property>
<property name="Expand">False</property>
<property name="Fill">False</property>
</packing>
</child>
<child>
- <widget class="Gtk.HBox" id="hbox46">
+ <widget class="Gtk.Alignment" id="alignment3">
<property name="MemberName" />
- <property name="Spacing">6</property>
- <child>
- <widget class="Gtk.Label" id="label104">
- <property name="MemberName" />
- <property name="WidthRequest">24</property>
- <property name="Xalign">0</property>
- <property name="Yalign">0</property>
- </widget>
- <packing>
- <property name="Position">0</property>
- <property name="AutoSize">False</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.Label" id="label105">
- <property name="MemberName" />
- <property name="Xalign">0</property>
- <property name="LabelProp" translatable="yes">Every</property>
- </widget>
- <packing>
- <property name="Position">1</property>
- <property name="AutoSize">False</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="Gtk.SpinButton" id="valueSpin">
- <property name="MemberName" />
- <property name="Upper">100</property>
- <property name="PageIncrement">10</property>
- <property name="StepIncrement">1</property>
- <property name="ClimbRate">1</property>
- <property name="Numeric">True</property>
- <property name="Value">1</property>
- </widget>
- <packing>
- <property name="Position">2</property>
- <property name="AutoSize">False</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
- </child>
+ <property name="LeftPadding">24</property>
+ <property name="BottomPadding">6</property>
<child>
- <widget class="Gtk.ComboBox" id="periodCombo">
+ <widget class="Gtk.VBox" id="vbox5">
<property name="MemberName" />
- <property name="IsTextCombo">True</property>
- <property name="Items" translatable="yes">Days
-Months</property>
- <property name="Active">0</property>
+ <property name="Spacing">6</property>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioHour">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Every hour</property>
+ <property name="Active">True</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group1</property>
+ </widget>
+ <packing>
+ <property name="Position">0</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioDay">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Every day</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group1</property>
+ </widget>
+ <packing>
+ <property name="Position">1</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioMonth">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Every month</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group1</property>
+ </widget>
+ <packing>
+ <property name="Position">2</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioNever">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Never</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group1</property>
+ </widget>
+ <packing>
+ <property name="Position">3</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
</widget>
- <packing>
- <property name="Position">3</property>
- <property name="AutoSize">False</property>
- <property name="Expand">False</property>
- <property name="Fill">False</property>
- </packing>
</child>
</widget>
<packing>
<property name="Position">1</property>
- <property name="AutoSize">False</property>
+ <property name="AutoSize">True</property>
<property name="Expand">False</property>
<property name="Fill">False</property>
</packing>
</child>
<child>
- <widget class="Gtk.HSeparator" id="hseparator1">
+ <widget class="Gtk.CheckButton" id="checkUnstable">
<property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Install unstable developer updates</property>
+ <property name="Active">True</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <signal name="Toggled" handler="OnCheckUnstableToggled" />
</widget>
<packing>
<property name="Position">2</property>
- <property name="AutoSize">False</property>
+ <property name="AutoSize">True</property>
<property name="Expand">False</property>
<property name="Fill">False</property>
</packing>
@@ -2392,16 +2413,99 @@ Months</property>
<widget class="Gtk.HBox" id="hbox47">
<property name="MemberName" />
<child>
- <widget class="Gtk.Button" id="managerButton">
+ <widget class="Gtk.Alignment" id="boxUnstable">
<property name="MemberName" />
+ <property name="LeftPadding">24</property>
+ <child>
+ <widget class="Gtk.VBox" id="vbox6">
+ <property name="MemberName" />
+ <property name="Spacing">6</property>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioBeta">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Beta updates (weekly)</property>
+ <property name="Active">True</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group2</property>
+ </widget>
+ <packing>
+ <property name="Position">0</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioAlpha">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Alpha updates (very often, very unstable)</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group2</property>
+ </widget>
+ <packing>
+ <property name="Position">1</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.RadioButton" id="radioTest">
+ <property name="MemberName" />
+ <property name="Visible">False</property>
+ <property name="CanFocus">True</property>
+ <property name="Label" translatable="yes">Test</property>
+ <property name="DrawIndicator">True</property>
+ <property name="HasLabel">True</property>
+ <property name="UseUnderline">True</property>
+ <property name="Group">group2</property>
+ </widget>
+ <packing>
+ <property name="Position">2</property>
+ <property name="AutoSize">True</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="Position">0</property>
+ <property name="AutoSize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="Position">3</property>
+ <property name="AutoSize">False</property>
+ <property name="Expand">False</property>
+ <property name="Fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="Gtk.HBox" id="hbox3">
+ <property name="MemberName" />
+ <property name="Spacing">6</property>
+ <property name="BorderWidth">12</property>
+ <child>
+ <widget class="Gtk.Button" id="buttonUpdateNow">
+ <property name="MemberName" />
+ <property name="CanFocus">True</property>
<property name="Type">TextOnly</property>
- <property name="Label" translatable="yes">Add-in Manager...</property>
+ <property name="Label" translatable="yes">Check for Updates Now</property>
<property name="UseUnderline">True</property>
- <signal name="Clicked" handler="OnManageClicked" />
+ <signal name="Clicked" handler="OnButtonUpdateNowClicked" />
</widget>
<packing>
<property name="Position">0</property>
- <property name="AutoSize">False</property>
+ <property name="AutoSize">True</property>
<property name="Expand">False</property>
<property name="Fill">False</property>
</packing>
@@ -2409,10 +2513,13 @@ Months</property>
<child>
<placeholder />
</child>
+ <child>
+ <placeholder />
+ </child>
</widget>
<packing>
- <property name="Position">3</property>
- <property name="AutoSize">False</property>
+ <property name="Position">4</property>
+ <property name="AutoSize">True</property>
<property name="Expand">False</property>
<property name="Fill">False</property>
</packing>
@@ -6466,7 +6573,6 @@ All solutions</property>
<property name="MemberName" />
<property name="CanFocus">True</property>
<property name="Label" translatable="yes">Delete the project file and the whole project directory:</property>
- <property name="Active">True</property>
<property name="DrawIndicator">True</property>
<property name="HasLabel">True</property>
<property name="UseUnderline">True</property>