Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/InstallationManagerForm.cs @ 3069

Last change on this file since 3069 was 3069, checked in by gkronber, 14 years ago

Improved dialogs in plugin manager. #891 (Refactor GUI for plugin management)

File size: 15.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Drawing;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using System.IO;
10using HeuristicLab.PluginInfrastructure.Manager;
11
12namespace HeuristicLab.PluginInfrastructure.Advanced {
13  public partial class InstallationManagerForm : Form {
14    private class UpdateOrInstallPluginsBackgroundWorkerArgument {
15      public IEnumerable<IPluginDescription> PluginsToUpdate { get; set; }
16      public IEnumerable<IPluginDescription> PluginsToInstall { get; set; }
17    }
18
19    private class RemovePluginsBackgroundWorkerArgument {
20      public IEnumerable<IPluginDescription> PluginsToRemove { get; set; }
21    }
22
23    private class RefreshBackgroundWorkerResult {
24      public IEnumerable<IPluginDescription> RemotePlugins { get; set; }
25      public IEnumerable<DeploymentService.ProductDescription> RemoteProducts { get; set; }
26    }
27
28    private InstallationManager installationManager;
29    private BackgroundWorker refreshServerPluginsBackgroundWorker;
30    private BackgroundWorker updateOrInstallPluginsBackgroundWorker;
31    private BackgroundWorker removePluginsBackgroundWorker;
32    private BackgroundWorker refreshLocalPluginsBackgroundWorker;
33    private string pluginDir;
34
35    public InstallationManagerForm() {
36      InitializeComponent();
37
38      pluginDir = Application.StartupPath;
39
40      #region initialize background workers
41      refreshServerPluginsBackgroundWorker = new BackgroundWorker();
42      refreshServerPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshServerPluginsBackgroundWorker_DoWork);
43      refreshServerPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshServerPluginsBackgroundWorker_RunWorkerCompleted);
44
45      updateOrInstallPluginsBackgroundWorker = new BackgroundWorker();
46      updateOrInstallPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateOrInstallPluginsBackgroundWorker_DoWork);
47      updateOrInstallPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted);
48
49      removePluginsBackgroundWorker = new BackgroundWorker();
50      removePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(removePluginsBackgroundWorker_DoWork);
51      removePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(removePluginsBackgroundWorker_RunWorkerCompleted);
52
53      refreshLocalPluginsBackgroundWorker = new BackgroundWorker();
54      refreshLocalPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshLocalPluginsBackgroundWorker_DoWork);
55      refreshLocalPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshLocalPluginsBackgroundWorker_RunWorkerCompleted);
56      #endregion
57
58      installationManager = new InstallationManager(pluginDir);
59      installationManager.PluginInstalled += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginInstalled);
60      installationManager.PluginRemoved += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginRemoved);
61      installationManager.PluginUpdated += new EventHandler<PluginInfrastructureEventArgs>(installationManager_PluginUpdated);
62      installationManager.PreInstallPlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreInstallPlugin);
63      installationManager.PreRemovePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreRemovePlugin);
64      installationManager.PreUpdatePlugin += new EventHandler<PluginInfrastructureCancelEventArgs>(installationManager_PreUpdatePlugin);
65
66      RefreshLocalPluginListAsync();
67    }
68
69    #region event handlers for refresh local plugin list backgroundworker
70    private IEnumerable<PluginDescription> ReloadLocalPlugins() {
71      PluginManager pluginManager = new PluginManager(Application.StartupPath);
72      pluginManager.PluginLoaded += pluginManager_PluginLoaded;
73      pluginManager.PluginUnloaded += pluginManager_PluginUnloaded;
74      pluginManager.Initializing += pluginManager_Initializing;
75      pluginManager.Initialized += pluginManager_Initialized;
76
77      pluginManager.DiscoverAndCheckPlugins();
78
79      pluginManager.PluginLoaded -= pluginManager_PluginLoaded;
80      pluginManager.PluginUnloaded -= pluginManager_PluginUnloaded;
81      pluginManager.Initializing -= pluginManager_Initializing;
82      pluginManager.Initialized -= pluginManager_Initialized;
83
84      return pluginManager.Plugins;
85    }
86    void refreshLocalPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
87      if (!e.Cancelled && e.Error == null) {
88        UpdateLocalPluginList((IEnumerable<PluginDescription>)e.Result);
89        UpdateControlsConnected();
90      }
91    }
92
93    void refreshLocalPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
94      var plugins = ReloadLocalPlugins();
95      e.Result = plugins;
96    }
97    #endregion
98
99    #region event handlers for plugin removal background worker
100    void removePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
101      if (!e.Cancelled && e.Error == null) {
102        RefreshLocalPluginListAsync();
103        UpdateControlsConnected();
104      }
105    }
106
107    void removePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
108      IEnumerable<IPluginDescription> pluginsToRemove = (IEnumerable<IPluginDescription>)e.Argument;
109      installationManager.Remove(pluginsToRemove);
110    }
111    #endregion
112
113    #region event handlers for plugin update background worker
114    void updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
115      if (!e.Cancelled && e.Error == null) {
116        RefreshLocalPluginListAsync();
117        RefreshRemotePluginListAsync();
118        UpdateControlsConnected();
119      } else {
120        UpdateControlsDisconnected();
121      }
122    }
123
124    void updateOrInstallPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
125      UpdateOrInstallPluginsBackgroundWorkerArgument info = (UpdateOrInstallPluginsBackgroundWorkerArgument)e.Argument;
126      installationManager.Install(info.PluginsToInstall);
127      installationManager.Update(info.PluginsToUpdate);
128    }
129    #endregion
130
131    #region event handlers for refresh server plugins background worker
132    void refreshServerPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
133      if (!e.Cancelled && e.Result != null) {
134        RefreshBackgroundWorkerResult refreshResult = (RefreshBackgroundWorkerResult)e.Result;
135        UpdateRemotePluginList(refreshResult.RemoteProducts, refreshResult.RemotePlugins);
136        UpdateControlsConnected();
137      } else {
138        UpdateControlsDisconnected();
139      }
140    }
141
142    void refreshServerPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
143      RefreshBackgroundWorkerResult result = new RefreshBackgroundWorkerResult();
144      result.RemotePlugins = installationManager.GetRemotePluginList();
145      result.RemoteProducts = installationManager.GetRemoteProductList();
146      e.Cancel = false;
147      e.Result = result;
148    }
149
150
151
152    #endregion
153
154    #region plugin manager event handlers
155    void pluginManager_Initialized(object sender, PluginInfrastructureEventArgs e) {
156      SetStatusStrip("Initialized PluginInfrastructure");
157    }
158
159    void pluginManager_Initializing(object sender, PluginInfrastructureEventArgs e) {
160      SetStatusStrip("Initializing PluginInfrastructure");
161    }
162
163    void pluginManager_PluginUnloaded(object sender, PluginInfrastructureEventArgs e) {
164      SetStatusStrip("Unloaded " + e.Entity);
165    }
166
167    void pluginManager_PluginLoaded(object sender, PluginInfrastructureEventArgs e) {
168      SetStatusStrip("Loaded " + e.Entity);
169    }
170    #endregion
171
172    #region installation manager event handlers
173    void installationManager_PreUpdatePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
174      if (e.Plugins.Count() > 0) {
175        e.Cancel = ConfirmUpdateAction(e.Plugins) == false;
176      }
177    }
178
179    void installationManager_PreRemovePlugin(object sender, PluginInfrastructureCancelEventArgs e) {
180      if (e.Plugins.Count() > 0) {
181        e.Cancel = ConfirmRemoveAction(e.Plugins) == false;
182      }
183    }
184
185    void installationManager_PreInstallPlugin(object sender, PluginInfrastructureCancelEventArgs e) {
186      if (e.Plugins.Count() > 0)
187        if (ConfirmInstallAction(e.Plugins) == true) {
188          SetStatusStrip("Installing " + e.Plugins.Aggregate("", (a, b) => a.ToString() + "; " + b.ToString()));
189          e.Cancel = false;
190        } else {
191          e.Cancel = true;
192          SetStatusStrip("Install canceled");
193        }
194    }
195
196    void installationManager_PluginUpdated(object sender, PluginInfrastructureEventArgs e) {
197      SetStatusStrip("Updated " + e.Entity);
198    }
199
200    void installationManager_PluginRemoved(object sender, PluginInfrastructureEventArgs e) {
201      SetStatusStrip("Removed " + e.Entity);
202    }
203
204    void installationManager_PluginInstalled(object sender, PluginInfrastructureEventArgs e) {
205      SetStatusStrip("Installed " + e.Entity);
206    }
207    #endregion
208
209    private void SetStatusStrip(string msg) {
210      if (InvokeRequired) Invoke((Action<string>)SetStatusStrip, msg);
211      else {
212        toolStripStatusLabel.Text = msg;
213        logTextBox.Text += DateTime.Now + ": " + msg + Environment.NewLine;
214      }
215    }
216
217    #region button events
218
219    private void refreshButton_Click(object sender, EventArgs e) {
220      RefreshRemotePluginListAsync();
221    }
222
223    private void updateButton_Click(object sender, EventArgs e) {
224      Cursor = Cursors.AppStarting;
225      toolStripProgressBar.Visible = true;
226      DisableControls();
227      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
228      // if there is a local plugin with same name and same major and minor version then it's an update
229      var pluginsToUpdate = from remotePlugin in remotePluginInstaller.CheckedPlugins
230                            let matchingLocalPlugins = from localPlugin in localPluginManager.Plugins
231                                                       where localPlugin.Name == remotePlugin.Name
232                                                       where localPlugin.Version.Major == remotePlugin.Version.Major
233                                                       where localPlugin.Version.Minor == remotePlugin.Version.Minor
234                                                       select localPlugin
235                            where matchingLocalPlugins.Count() > 0
236                            select remotePlugin;
237
238      // otherwise install a new plugin
239      var pluginsToInstall = remotePluginInstaller.CheckedPlugins.Except(pluginsToUpdate);
240
241      updateOrInstallInfo.PluginsToInstall = pluginsToInstall;
242      updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate;
243      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
244    }
245
246    private void removeButton_Click(object sender, EventArgs e) {
247      Cursor = Cursors.AppStarting;
248      toolStripProgressBar.Visible = true;
249      DisableControls();
250      removePluginsBackgroundWorker.RunWorkerAsync(localPluginManager.CheckedPlugins);
251    }
252
253    #endregion
254
255    #region confirmation dialogs
256    private bool ConfirmRemoveAction(IEnumerable<IPluginDescription> plugins) {
257      StringBuilder strBuilder = new StringBuilder();
258      foreach (var plugin in plugins) {
259        foreach (var file in plugin.Files) {
260          strBuilder.AppendLine(Path.GetFileName(file.Name));
261        }
262      }
263      return (new ConfirmationDialog("Confirm Delete", "Do you want to delete following files?", strBuilder.ToString())).ShowDialog() == DialogResult.OK;
264    }
265
266    private bool ConfirmUpdateAction(IEnumerable<IPluginDescription> plugins) {
267      StringBuilder strBuilder = new StringBuilder();
268      foreach (var plugin in plugins) {
269        strBuilder.AppendLine(plugin.ToString());
270      }
271      return (new ConfirmationDialog("Confirm Update", "Do you want to update following plugins?", strBuilder.ToString())).ShowDialog() == DialogResult.OK;
272    }
273
274    private bool ConfirmInstallAction(IEnumerable<IPluginDescription> plugins) {
275      foreach (var plugin in plugins) {
276        if (!string.IsNullOrEmpty(plugin.LicenseText)) {
277          var licenseConfirmationBox = new LicenseConfirmationBox(plugin);
278          if (licenseConfirmationBox.ShowDialog() != DialogResult.OK)
279            return false;
280        }
281      }
282      return true;
283    }
284
285
286    #endregion
287
288    #region helper methods
289
290    private void UpdateLocalPluginList(IEnumerable<PluginDescription> plugins) {
291      localPluginManager.Plugins = plugins;
292    }
293
294    private void UpdateRemotePluginList(
295      IEnumerable<DeploymentService.ProductDescription> remoteProducts,
296      IEnumerable<IPluginDescription> remotePlugins) {
297
298      var mostRecentRemotePlugins = from remote in remotePlugins
299                                    where !remotePlugins.Any(x => x.Name == remote.Name && x.Version > remote.Version) // same name and higher version
300                                    select remote;
301
302      var newPlugins = from remote in mostRecentRemotePlugins
303                       let matchingLocal = (from local in localPluginManager.Plugins
304                                            where local.Name == remote.Name
305                                            where local.Version < remote.Version
306                                            select local).FirstOrDefault()
307                       where matchingLocal != null
308                       select remote;
309
310      remotePluginInstaller.NewPlugins = newPlugins;
311      remotePluginInstaller.Products = remoteProducts;
312      remotePluginInstaller.AllPlugins = remotePlugins;
313    }
314
315    private void RefreshRemotePluginListAsync() {
316      Cursor = Cursors.AppStarting;
317      toolStripProgressBar.Visible = true;
318      DisableControls();
319      refreshServerPluginsBackgroundWorker.RunWorkerAsync();
320    }
321
322    private void RefreshLocalPluginListAsync() {
323      Cursor = Cursors.AppStarting;
324      toolStripProgressBar.Visible = true;
325      DisableControls();
326      refreshLocalPluginsBackgroundWorker.RunWorkerAsync();
327    }
328
329    private void UpdateControlsDisconnected() {
330      //localPluginsListView.Enabled = false;
331      //ClearPluginsList(remotePluginsListView);
332      refreshButton.Enabled = true;
333      toolStripProgressBar.Visible = false;
334      Cursor = Cursors.Default;
335    }
336
337    private void UpdateControlsConnected() {
338      refreshButton.Enabled = true;
339      toolStripProgressBar.Visible = false;
340      Cursor = Cursors.Default;
341    }
342
343    private void DisableControls() {
344      refreshButton.Enabled = false;
345      Cursor = Cursors.Default;
346    }
347    #endregion
348
349    private void localPluginManager_ItemChecked(object sender, ItemCheckedEventArgs e) {
350      removeButton.Enabled = localPluginManager.CheckedPlugins.Count() > 0;
351    }
352
353    private void remotePluginInstaller_ItemChecked(object sender, ItemCheckedEventArgs e) {
354      installButton.Enabled = remotePluginInstaller.CheckedPlugins.Count() > 0;
355    }
356
357    private void editConnectionButton_Click(object sender, EventArgs e) {
358      (new ConnectionSetupView()).ShowInForm();
359    }
360  }
361}
Note: See TracBrowser for help on using the repository browser.