Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.PluginInfrastructure/Advanced/AvailablePluginsView.cs @ 3627

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

Refactored class names and fixed a dependency-selection bug. #994 (Clean up plugin infrastructure project)

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