Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginAdministrator/3.3/PluginEditor.cs @ 3200

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

Improved controls for deployment service interaction.
Increased max values for message sizes and related limits in the deployment service configuration.
Recreated proxy classes for the deployment service.

#891 (Refactor GUI for plugin management)

File size: 12.8 KB
RevLine 
[3081]1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
[2802]23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Drawing;
26using System.Data;
27using System.Linq;
28using System.Text;
29using System.Windows.Forms;
30using HeuristicLab.MainForm;
31using HeuristicLab.PluginInfrastructure;
[2816]32using PluginDeploymentService = HeuristicLab.PluginInfrastructure.Advanced.DeploymentService;
33using HeuristicLab.PluginInfrastructure.Manager;
34using System.ServiceModel;
35using ICSharpCode.SharpZipLib.Zip;
36using System.IO;
[2802]37
[3081]38namespace HeuristicLab.PluginAdministrator {
39  internal partial class PluginEditor : HeuristicLab.MainForm.WindowsForms.View {
[2816]40    private Dictionary<IPluginDescription, PluginDeploymentService.PluginDescription> localAndServerPlugins;
[2802]41    private BackgroundWorker pluginUploadWorker;
[2816]42    private BackgroundWorker updateServerPluginsWorker;
[2802]43
[3045]44    public PluginEditor() {
[2802]45      InitializeComponent();
[2860]46      imageList.Images.Add(HeuristicLab.Common.Resources.VS2008ImageLibrary.Assembly);
47      imageList.Images.Add(HeuristicLab.Common.Resources.VS2008ImageLibrary.ArrowUp);
[2802]48      Caption = "Plugins";
49
[2816]50      localAndServerPlugins = new Dictionary<IPluginDescription, PluginDeploymentService.PluginDescription>();
51
[2860]52      #region initialize backgroundworkers
[2802]53      pluginUploadWorker = new BackgroundWorker();
54      pluginUploadWorker.DoWork += new DoWorkEventHandler(pluginUploadWorker_DoWork);
55      pluginUploadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(pluginUploadWorker_RunWorkerCompleted);
56
[2816]57      updateServerPluginsWorker = new BackgroundWorker();
58      updateServerPluginsWorker.DoWork += new DoWorkEventHandler(updateServerPluginsWorker_DoWork);
59      updateServerPluginsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateServerPluginsWorker_RunWorkerCompleted);
[2860]60      #endregion
[2802]61    }
62
[2860]63    #region refresh plugins from server backgroundworker
[2816]64    void updateServerPluginsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
65      if (!e.Cancelled && e.Result != null) {
[2860]66        // refresh local plugins
67        localAndServerPlugins.Clear();
68        foreach (var plugin in ApplicationManager.Manager.Plugins) {
69          localAndServerPlugins.Add(plugin, null);
70        }
71        // refresh server plugins (find matching local plugins)
[2816]72        var plugins = (PluginDeploymentService.PluginDescription[])e.Result;
73        foreach (var plugin in plugins) {
74          var matchingLocalPlugin = (from localPlugin in localAndServerPlugins.Keys
75                                     where localPlugin.Name == plugin.Name
76                                     where localPlugin.Version == localPlugin.Version
77                                     select localPlugin).SingleOrDefault();
78          if (matchingLocalPlugin != null) {
79            localAndServerPlugins[matchingLocalPlugin] = plugin;
80          }
81        }
[2860]82        // refresh the list view with plugins
83        listView.Items.Clear();
[3068]84        listView.CheckBoxes = false;
85        //suppressCheckedEvents = true;
[2860]86        foreach (var pair in localAndServerPlugins) {
87          var item = MakeListViewItem(pair.Key);
88          listView.Items.Add(item);
89        }
[3068]90        //listView.suppressCheckedEvents = false;
91        listView.CheckBoxes = true;
[2860]92        UpdateControlsConnectedState();
[2816]93      } else {
[2860]94        UpdateControlsDisconnectedState();
[2816]95      }
[2860]96      // make sure cursor is set correctly
[2816]97      Cursor = Cursors.Default;
98    }
99
100    void updateServerPluginsWorker_DoWork(object sender, DoWorkEventArgs e) {
101      try {
[3006]102        var client = PluginDeploymentService.UpdateClientFactory.CreateClient();
103        e.Result = client.GetPlugins();
104        e.Cancel = false;
[2816]105      }
[2860]106      catch (EndpointNotFoundException) {
[2816]107        e.Result = null;
108        e.Cancel = true;
109      }
[2860]110      catch (FaultException) {
[2816]111        e.Result = null;
112        e.Cancel = true;
113      }
114    }
[2860]115    #endregion
[2816]116
[2860]117    #region upload plugins to server backgroundworker
[2802]118    void pluginUploadWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
[2860]119      Cursor = Cursors.Default;
120      if (e.Cancelled) {
121        UpdateControlsDisconnectedState();
122      } else {
123        UpdateControlsConnectedState();
124        // start another async call to refresh plugin information from server
125        RefreshPluginsAsync();
126      }
[2802]127    }
128
129    void pluginUploadWorker_DoWork(object sender, DoWorkEventArgs e) {
[2860]130      try {
131        var selectedPlugins = (IEnumerable<IPluginDescription>)e.Argument;
[3006]132        PluginDeploymentService.AdminClient adminClient = PluginDeploymentService.AdminClientFactory.CreateClient();
[2802]133
[3006]134        foreach (var plugin in IteratePlugins(selectedPlugins)) {
[3179]135          SetMainFormStatusBar("Uploading", plugin);
[3068]136          adminClient.DeployPlugin(MakePluginDescription(plugin), CreateZipPackage(plugin));
[2816]137        }
[2860]138        e.Cancel = false;
[2802]139      }
[2860]140      catch (EndpointNotFoundException) {
141        e.Cancel = true;
142      }
143      catch (FaultException) {
144        e.Cancel = true;
145      }
[2802]146    }
[3179]147
[2860]148    #endregion
[2802]149
[2860]150
151    #region button events
152    private void uploadButton_Click(object sender, EventArgs e) {
153      var selectedPlugins = from item in listView.Items.Cast<ListViewItem>()
154                            where item.Checked
155                            where item.Tag is IPluginDescription
156                            select item.Tag as IPluginDescription;
157      if (selectedPlugins.Count() > 0) {
158        Cursor = Cursors.AppStarting;
159        DisableControl();
160        pluginUploadWorker.RunWorkerAsync(selectedPlugins.ToList());
161      }
162    }
163
164    private void connectButton_Click(object sender, EventArgs e) {
[3006]165      var connectionSetupView = new ConnectionSetupView();
166      connectionSetupView.Show();
[2860]167    }
168
169    private void refreshButton_Click(object sender, EventArgs e) {
170      DisableControl();
171      RefreshPluginsAsync();
172    }
173
174    #endregion
175
176    #region item list events
177    private void listView_ItemActivate(object sender, EventArgs e) {
178      foreach (var item in listView.SelectedItems) {
179        var plugin = (IPluginDescription)((ListViewItem)item).Tag;
180        var compView = new PluginComparisonView(plugin, localAndServerPlugins[plugin]);
181        compView.Show();
182      }
183    }
184
[3068]185    private void listView_ItemChecked(object sender, ItemCheckedEventArgs e) {
186      List<IPluginDescription> modifiedPlugins = new List<IPluginDescription>();
[2860]187      if (e.Item.Checked) {
[3068]188        foreach (ListViewItem item in listView.SelectedItems) {
189          var plugin = (IPluginDescription)item.Tag;
190          // also check all dependencies
[3179]191          if (!modifiedPlugins.Contains(plugin))
192            modifiedPlugins.Add(plugin);
[3068]193          foreach (var dep in GetAllDependencies(plugin)) {
[3179]194            if (!modifiedPlugins.Contains(dep))
195              modifiedPlugins.Add(dep);
[3068]196          }
[2860]197        }
[3068]198        listView.CheckItems(modifiedPlugins.Select(x => FindItemForPlugin(x)));
[2860]199      } else {
[3068]200        foreach (ListViewItem item in listView.SelectedItems) {
201          var plugin = (IPluginDescription)item.Tag;
202          // also uncheck all dependent plugins
[3179]203          if (!modifiedPlugins.Contains(plugin))
204            modifiedPlugins.Add(plugin);
[3068]205          foreach (var dep in GetAllDependents(plugin)) {
[3179]206            if (!modifiedPlugins.Contains(dep))
207              modifiedPlugins.Add(dep);
[2860]208          }
209        }
[3068]210        listView.UncheckItems(modifiedPlugins.Select(x => FindItemForPlugin(x)));
[2860]211      }
[3068]212      uploadButton.Enabled = (from i in listView.Items.OfType<ListViewItem>()
213                              where i.Checked
214                              select i).Any();
[2860]215    }
216    #endregion
217
218    #region helper methods
[3068]219    private IEnumerable<IPluginDescription> GetAllDependents(IPluginDescription plugin) {
220      return from p in localAndServerPlugins.Keys
221             let matchingEntries = from dep in GetAllDependencies(p)
222                                   where dep.Name == plugin.Name
223                                   where dep.Version == plugin.Version
224                                   select dep
225             where matchingEntries.Any()
226             select p;
227    }
228
229    private IEnumerable<IPluginDescription> GetAllDependencies(IPluginDescription plugin) {
230      foreach (var dep in plugin.Dependencies) {
231        foreach (var recDep in GetAllDependencies(dep)) {
232          yield return recDep;
233        }
234        yield return dep;
235      }
236    }
237
238    private IEnumerable<IPluginDescription> IteratePlugins(IEnumerable<IPluginDescription> plugins) {
[3179]239      HashSet<IPluginDescription> yieldedItems = new HashSet<IPluginDescription>();
[3068]240      foreach (var plugin in plugins) {
241        foreach (var dependency in IteratePlugins(plugin.Dependencies)) {
[3179]242          if (!yieldedItems.Contains(dependency)) {
243            yieldedItems.Add(dependency);
244            yield return dependency;
245          }
[3068]246        }
[3179]247        if (!yieldedItems.Contains(plugin)) {
248          yieldedItems.Add(plugin);
249          yield return plugin;
250        }
[3068]251      }
252    }
253
[2816]254    private byte[] CreateZipPackage(IPluginDescription plugin) {
255      using (MemoryStream stream = new MemoryStream()) {
256        ZipFile zipFile = new ZipFile(stream);
257        zipFile.BeginUpdate();
258        foreach (var file in plugin.Files) {
259          zipFile.Add(file.Name);
260        }
261        zipFile.CommitUpdate();
262        stream.Seek(0, SeekOrigin.Begin);
263        return stream.GetBuffer();
264      }
265    }
266
267    private ListViewItem MakeListViewItem(IPluginDescription plugin) {
268      ListViewItem item;
269      if (localAndServerPlugins[plugin] != null) {
[3068]270        item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
271          localAndServerPlugins[plugin].Version.ToString(), localAndServerPlugins[plugin].Description });
[2816]272      } else {
[3068]273        item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
274          string.Empty, plugin.Description });
[2802]275      }
276      item.Tag = plugin;
[2860]277      item.Checked = false;
[2802]278      return item;
279    }
280
[2860]281    private ListViewItem FindItemForPlugin(IPluginDescription dep) {
282      return (from i in listView.Items.Cast<ListViewItem>()
283              where i.Tag == dep
284              select i).Single();
[2802]285    }
286
[2860]287    private PluginDeploymentService.PluginDescription MakePluginDescription(IPluginDescription plugin) {
288      var dependencies = from dep in plugin.Dependencies
289                         select MakePluginDescription(dep);
[3006]290      return new PluginDeploymentService.PluginDescription(plugin.Name, plugin.Version, dependencies, plugin.ContactName, plugin.ContactEmail, plugin.LicenseText);
[2816]291    }
292
[2860]293    // start background process to refresh the plugin list (local and server)
294    private void RefreshPluginsAsync() {
[2816]295      Cursor = Cursors.AppStarting;
[2860]296      DisableControl();
[2816]297      updateServerPluginsWorker.RunWorkerAsync();
298    }
299
[2860]300    // is called by all methods that start a background process
301    // controls must be enabled manuall again when the backgroundworker finishes
302    private void DisableControl() {
303      MainFormManager.GetMainForm<MainForm>().ShowProgressBar();
304      foreach (Control ctrl in Controls)
305        ctrl.Enabled = false;
[2816]306    }
307
[2860]308    private void UpdateControlsDisconnectedState() {
309      refreshButton.Enabled = false;
[2816]310
311      localAndServerPlugins.Clear();
312      listView.Items.Clear();
313      listView.Enabled = false;
314      uploadButton.Enabled = false;
[2860]315      MainFormManager.GetMainForm<MainForm>().HideProgressBar();
[2816]316    }
[2860]317
318    private void UpdateControlsConnectedState() {
319      refreshButton.Enabled = true;
320      listView.Enabled = true;
321      uploadButton.Enabled = false;
322      MainFormManager.GetMainForm<MainForm>().HideProgressBar();
323    }
[3179]324    private void SetMainFormStatusBar(string p, IPluginDescription plugin) {
325      if (InvokeRequired) Invoke((Action<string, IPluginDescription>)SetMainFormStatusBar, p, plugin);
326      else {
327        MainFormManager.GetMainForm<MainForm>().SetStatusBarText(p + " " + plugin.ToString());
328      }
329    }
330
[2860]331    #endregion
[2802]332  }
333}
Note: See TracBrowser for help on using the repository browser.