Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ParameterBinding/HeuristicLab.PluginInfrastructure/3.3/Advanced/AvailablePluginsView.cs @ 7450

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

Fixed bug in plugin infrastructure when installing plugins from the update location. #1203

File size: 14.9 KB
Line 
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
21using System;
22using System.Collections.Generic;
23using System.ComponentModel;
24using System.Linq;
25using System.Windows.Forms;
26using HeuristicLab.PluginInfrastructure.Manager;
27
28namespace HeuristicLab.PluginInfrastructure.Advanced {
29  internal partial class AvailablePluginsView : InstallationManagerControl {
30    private class RefreshBackgroundWorkerResult {
31      public IEnumerable<IPluginDescription> RemotePlugins { get; set; }
32      public IEnumerable<DeploymentService.ProductDescription> RemoteProducts { get; set; }
33    }
34    private class UpdateOrInstallPluginsBackgroundWorkerArgument {
35      public IEnumerable<IPluginDescription> PluginsToUpdate { get; set; }
36      public IEnumerable<IPluginDescription> PluginsToInstall { get; set; }
37    }
38    private const string PluginDiscoveryMessage = "Looking for new plugins...";
39    private BackgroundWorker refreshServerPluginsBackgroundWorker;
40    private BackgroundWorker updateOrInstallPluginsBackgroundWorker;
41
42    private IEnumerable<DeploymentService.ProductDescription> products;
43    private IEnumerable<IPluginDescription> plugins;
44
45    private IEnumerable<IPluginDescription> CheckedPlugins {
46      get {
47        return (from item in pluginsListView.Items.OfType<ListViewItem>()
48                where item.Checked
49                let plugin = item.Tag as IPluginDescription
50                where plugin != null
51                select plugin).ToList();
52      }
53    }
54
55    private InstallationManager installationManager;
56    public InstallationManager InstallationManager {
57      get { return installationManager; }
58      set { installationManager = value; }
59    }
60    private PluginManager pluginManager;
61    public PluginManager PluginManager {
62      get { return pluginManager; }
63      set { pluginManager = value; }
64    }
65    public AvailablePluginsView() {
66      InitializeComponent();
67      productImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Setup_Install);
68      productLargeImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Setup_Install);
69      pluginsImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Plugin);
70      refreshServerPluginsBackgroundWorker = new BackgroundWorker();
71      refreshServerPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(refreshServerPluginsBackgroundWorker_DoWork);
72      refreshServerPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshServerPluginsBackgroundWorker_RunWorkerCompleted);
73
74      updateOrInstallPluginsBackgroundWorker = new BackgroundWorker();
75      updateOrInstallPluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updateOrInstallPluginsBackgroundWorker_DoWork);
76      updateOrInstallPluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted);
77    }
78
79
80    #region event handlers for refresh server plugins background worker
81    void refreshServerPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
82      if (e.Error != null) {
83        StatusView.ShowError("Connection Error",
84          "There was an error while connecting to the server." + Environment.NewLine +
85          "Please check your connection settings and user credentials.");
86      } else {
87        RefreshBackgroundWorkerResult refreshResult = (RefreshBackgroundWorkerResult)e.Result;
88        products = refreshResult.RemoteProducts;
89        plugins = refreshResult.RemotePlugins;
90        UpdateControl();
91      }
92      StatusView.UnlockUI();
93      StatusView.RemoveMessage(PluginDiscoveryMessage);
94      StatusView.HideProgressIndicator();
95    }
96
97    void refreshServerPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
98      RefreshBackgroundWorkerResult result = new RefreshBackgroundWorkerResult();
99      result.RemotePlugins = installationManager.GetRemotePluginList();
100      result.RemoteProducts = installationManager.GetRemoteProductList();
101      e.Result = result;
102    }
103    #endregion
104    #region event handlers for plugin update background worker
105    void updateOrInstallPluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
106      if (e.Error != null) {
107        StatusView.ShowError("Connection Error",
108          "There was an error while connecting to the server." + Environment.NewLine +
109          "Please check your connection settings and user credentials.");
110      } else {
111        UpdateControl();
112      }
113      StatusView.UnlockUI();
114      StatusView.HideProgressIndicator();
115    }
116
117    void updateOrInstallPluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
118      UpdateOrInstallPluginsBackgroundWorkerArgument info = (UpdateOrInstallPluginsBackgroundWorkerArgument)e.Argument;
119      if (info.PluginsToInstall.Count() > 0)
120        installationManager.Install(info.PluginsToInstall);
121      if (info.PluginsToUpdate.Count() > 0)
122        installationManager.Update(info.PluginsToUpdate);
123
124      if (info.PluginsToInstall.Count() > 0 || info.PluginsToUpdate.Count() > 0)
125        pluginManager.DiscoverAndCheckPlugins();
126    }
127    #endregion
128
129
130    #region button events
131    private void refreshRemoteButton_Click(object sender, EventArgs e) {
132      StatusView.LockUI();
133      StatusView.ShowProgressIndicator();
134      StatusView.ShowMessage(PluginDiscoveryMessage);
135      refreshServerPluginsBackgroundWorker.RunWorkerAsync();
136    }
137    private void installPluginsButton_Click(object sender, EventArgs e) {
138      StatusView.LockUI();
139      StatusView.ShowProgressIndicator();
140      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
141      // if there is a local plugin with same name and same major and minor version then it's an update
142      var pluginsToUpdate = from remotePlugin in CheckedPlugins
143                            let matchingLocalPlugins = from localPlugin in pluginManager.Plugins
144                                                       where localPlugin.Name == remotePlugin.Name
145                                                       where localPlugin.Version.Major == remotePlugin.Version.Major
146                                                       where localPlugin.Version.Minor == remotePlugin.Version.Minor
147                                                       where IsNewerThan(remotePlugin, localPlugin)
148                                                       select localPlugin
149                            where matchingLocalPlugins.Count() > 0
150                            select remotePlugin;
151
152      // otherwise install a new plugin
153      var pluginsToInstall = CheckedPlugins.Except(pluginsToUpdate);
154
155      updateOrInstallInfo.PluginsToInstall = pluginsToInstall;
156      updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate;
157      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
158    }
159    private void installProductsButton_Click(object sender, EventArgs e) {
160      StatusView.LockUI();
161      StatusView.ShowProgressIndicator();
162      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
163      var selectedProduct = (DeploymentService.ProductDescription)productsListView.SelectedItems[0].Tag;
164      // if there is a local plugin with same name and same major and minor version then it's an update
165      var pluginsToUpdate = from plugin in selectedProduct.Plugins
166                            let matchingLocalPlugins = from localPlugin in pluginManager.Plugins
167                                                       where localPlugin.Name == plugin.Name
168                                                       where localPlugin.Version.Major == plugin.Version.Major
169                                                       where localPlugin.Version.Minor == plugin.Version.Minor
170                                                       where IsNewerThan(plugin, localPlugin)
171                                                       select localPlugin
172                            where matchingLocalPlugins.Count() > 0
173                            select plugin;
174
175      // otherwise install a new plugin
176      var pluginsToInstall = selectedProduct.Plugins.Except(pluginsToUpdate);
177
178      updateOrInstallInfo.PluginsToInstall =
179        pluginsToInstall
180        .Cast<IPluginDescription>()
181        .ToList();
182      updateOrInstallInfo.PluginsToUpdate =
183        pluginsToUpdate
184        .Cast<IPluginDescription>()
185        .ToList();
186      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
187    }
188
189    private void showLargeIconsButton_CheckedChanged(object sender, EventArgs e) {
190      productsListView.View = View.LargeIcon;
191    }
192
193    private void showDetailsButton_CheckedChanged(object sender, EventArgs e) {
194      productsListView.View = View.Details;
195    }
196
197    #endregion
198
199    private void UpdateControl() {
200      // clear products view
201      List<ListViewItem> productItemsToDelete = new List<ListViewItem>(productsListView.Items.OfType<ListViewItem>());
202      productItemsToDelete.ForEach(item => productsListView.Items.Remove(item));
203
204      // populate products list view
205      foreach (var product in products) {
206        var item = CreateListViewItem(product);
207        productsListView.Items.Add(item);
208      }
209      var allPluginsListViewItem = new ListViewItem();
210      allPluginsListViewItem.Text = "All Plugins";
211      allPluginsListViewItem.ImageIndex = 0;
212      productsListView.Items.Add(allPluginsListViewItem);
213      Util.ResizeColumns(productsListView.Columns.OfType<ColumnHeader>());
214    }
215
216    private void UpdatePluginsList() {
217      pluginsListView.Items.Clear();
218
219      // populate plugins list
220      if (productsListView.SelectedItems.Count > 0) {
221        pluginsListView.SuppressItemCheckedEvents = true;
222
223        var selectedItem = productsListView.SelectedItems[0];
224        if (selectedItem.Text == "All Plugins") {
225          foreach (var plugin in plugins) {
226            var item = CreateListViewItem(plugin);
227            pluginsListView.Items.Add(item);
228          }
229        } else {
230          var selectedProduct = (DeploymentService.ProductDescription)productsListView.SelectedItems[0].Tag;
231          foreach (var plugin in selectedProduct.Plugins) {
232            var item = CreateListViewItem(plugin);
233            pluginsListView.Items.Add(item);
234          }
235        }
236
237        Util.ResizeColumns(pluginsListView.Columns.OfType<ColumnHeader>());
238        pluginsListView.SuppressItemCheckedEvents = false;
239      }
240    }
241
242    private ListViewItem CreateListViewItem(DeploymentService.ProductDescription product) {
243      ListViewItem item = new ListViewItem(new string[] { product.Name, product.Version.ToString() });
244      item.Tag = product;
245      item.ImageIndex = 0;
246      return item;
247    }
248
249    private ListViewItem CreateListViewItem(IPluginDescription plugin) {
250      ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(), plugin.Description });
251      item.Tag = plugin;
252      item.ImageIndex = 0;
253      return item;
254    }
255
256    #region products list view events
257    private void productsListView_SelectedIndexChanged(object sender, EventArgs e) {
258      UpdatePluginsList();
259      installProductsButton.Enabled = (productsListView.SelectedItems.Count > 0 &&
260        productsListView.SelectedItems[0].Text != "All Plugins");
261    }
262    #endregion
263
264    #region item checked event handler
265    private void remotePluginsListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
266      foreach (ListViewItem item in pluginsListView.SelectedItems) {
267        IPluginDescription plugin = (IPluginDescription)item.Tag;
268        if (e.Item.Checked)
269          HandlePluginChecked(plugin);
270        else
271          HandlePluginUnchecked(plugin);
272      }
273      installPluginsButton.Enabled = pluginsListView.CheckedItems.Count > 0;
274    }
275
276    private void HandlePluginUnchecked(IPluginDescription plugin) {
277      // also uncheck all dependent plugins
278      List<ListViewItem> modifiedItems = new List<ListViewItem>();
279      modifiedItems.AddRange(FindItemsForPlugin(plugin));
280      var dependentPlugins = Util.GetAllDependents(plugin, plugins);
281      foreach (var dependentPlugin in dependentPlugins) {
282        // there can be multiple entries for a single plugin in different groups
283        foreach (var item in FindItemsForPlugin(dependentPlugin)) {
284          if (item != null && item.Checked) {
285            if (!modifiedItems.Contains(item))
286              modifiedItems.Add(item);
287          }
288        }
289      }
290      pluginsListView.UncheckItems(modifiedItems);
291    }
292
293    private void HandlePluginChecked(IPluginDescription plugin) {
294      // also check all dependencies
295      List<ListViewItem> modifiedItems = new List<ListViewItem>();
296      modifiedItems.AddRange(FindItemsForPlugin(plugin));
297      foreach (var dep in Util.GetAllDependencies(plugin)) {
298        // there can be multiple entries for a single plugin in different groups
299        foreach (ListViewItem item in FindItemsForPlugin(dep)) {
300          if (item != null && !item.Checked) {
301            if (!modifiedItems.Contains(item))
302              modifiedItems.Add(item);
303          }
304        }
305      }
306      pluginsListView.CheckItems(modifiedItems);
307    }
308
309    #endregion
310
311    #region helper methods
312    private IEnumerable<ListViewItem> FindItemsForPlugin(IPluginDescription plugin) {
313      return (from item in pluginsListView.Items.OfType<ListViewItem>()
314              let otherPlugin = item.Tag as IPluginDescription
315              where otherPlugin != null && otherPlugin.Name == plugin.Name && otherPlugin.Version == plugin.Version
316              select item);
317    }
318
319    // compares for two plugins with same major and minor version if plugin1 is newer than plugin2
320    private static bool IsNewerThan(IPluginDescription plugin1, IPluginDescription plugin2) {
321      // newer: build version is higher, or if build version is the same revision is higher
322      return plugin1.Version.Build > plugin2.Version.Build ||
323        (plugin1.Version.Build == plugin2.Version.Build && plugin1.Version.Revision > plugin2.Version.Revision);
324    }
325    #endregion
326
327  }
328}
Note: See TracBrowser for help on using the repository browser.