Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.PluginInfrastructure/3.3/Advanced/AvailablePluginsView.cs @ 17096

Last change on this file since 17096 was 16565, checked in by gkronber, 6 years ago

#2520: merged changes from PersistenceOverhaul branch (r16451:16564) into trunk

File size: 15.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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      bool cancelled = false;
120      if (info.PluginsToInstall.Count() > 0)
121        installationManager.Install(info.PluginsToInstall, out cancelled);
122      if (info.PluginsToUpdate.Count() > 0)
123        installationManager.Update(info.PluginsToUpdate, out cancelled);
124
125      if (!cancelled && (info.PluginsToInstall.Count() > 0 || info.PluginsToUpdate.Count() > 0))
126        pluginManager.DiscoverAndCheckPlugins();
127    }
128    #endregion
129
130
131    #region button events
132    private void refreshRemoteButton_Click(object sender, EventArgs e) {
133      StatusView.LockUI();
134      StatusView.ShowProgressIndicator();
135      StatusView.ShowMessage(PluginDiscoveryMessage);
136      refreshServerPluginsBackgroundWorker.RunWorkerAsync();
137    }
138    private void installPluginsButton_Click(object sender, EventArgs e) {
139      StatusView.LockUI();
140      StatusView.ShowProgressIndicator();
141      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
142      // if there is a local plugin with same name and same major and minor version then it's an update
143      var pluginsToUpdate = from remotePlugin in CheckedPlugins
144                            let matchingLocalPlugins = from localPlugin in pluginManager.Plugins
145                                                       where localPlugin.Name == remotePlugin.Name
146                                                       where localPlugin.Version.Major == remotePlugin.Version.Major
147                                                       where localPlugin.Version.Minor == remotePlugin.Version.Minor
148                                                       where IsNewerThan(remotePlugin, localPlugin)
149                                                       select localPlugin
150                            where matchingLocalPlugins.Count() > 0
151                            select remotePlugin;
152
153      // otherwise install a new plugin
154      var pluginsToInstall = CheckedPlugins.Except(pluginsToUpdate);
155
156      updateOrInstallInfo.PluginsToInstall = pluginsToInstall;
157      updateOrInstallInfo.PluginsToUpdate = pluginsToUpdate;
158      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
159    }
160    private void installProductsButton_Click(object sender, EventArgs e) {
161      StatusView.LockUI();
162      StatusView.ShowProgressIndicator();
163      var updateOrInstallInfo = new UpdateOrInstallPluginsBackgroundWorkerArgument();
164      var selectedProduct = (DeploymentService.ProductDescription)productsListView.SelectedItems[0].Tag;
165      // if there is a local plugin with same name and same major and minor version then it's an update
166      var pluginsToUpdate = from plugin in selectedProduct.Plugins
167                            let matchingLocalPlugins = from localPlugin in pluginManager.Plugins
168                                                       where localPlugin.Name == plugin.Name
169                                                       where localPlugin.Version.Major == plugin.Version.Major
170                                                       where localPlugin.Version.Minor == plugin.Version.Minor
171                                                       where IsNewerThan(plugin, localPlugin)
172                                                       select localPlugin
173                            where matchingLocalPlugins.Count() > 0
174                            select plugin;
175
176      // otherwise install a new plugin
177      var pluginsToInstall = selectedProduct.Plugins.Except(pluginsToUpdate);
178
179      updateOrInstallInfo.PluginsToInstall =
180        pluginsToInstall
181        .Cast<IPluginDescription>()
182        .ToList();
183      updateOrInstallInfo.PluginsToUpdate =
184        pluginsToUpdate
185        .Cast<IPluginDescription>()
186        .ToList();
187      updateOrInstallPluginsBackgroundWorker.RunWorkerAsync(updateOrInstallInfo);
188    }
189
190    private void showLargeIconsButton_CheckedChanged(object sender, EventArgs e) {
191      productsListView.View = View.LargeIcon;
192    }
193
194    private void showDetailsButton_CheckedChanged(object sender, EventArgs e) {
195      productsListView.View = View.Details;
196    }
197
198    #endregion
199
200    private void UpdateControl() {
201      // clear products view
202      List<ListViewItem> productItemsToDelete = new List<ListViewItem>(productsListView.Items.OfType<ListViewItem>());
203      productItemsToDelete.ForEach(item => productsListView.Items.Remove(item));
204
205      // populate products list view
206      foreach (var product in products) {
207        var item = CreateListViewItem(product);
208        productsListView.Items.Add(item);
209      }
210      var allPluginsListViewItem = new ListViewItem();
211      allPluginsListViewItem.Text = "All Plugins";
212      allPluginsListViewItem.ImageIndex = 0;
213      productsListView.Items.Add(allPluginsListViewItem);
214      Util.ResizeColumns(productsListView.Columns.OfType<ColumnHeader>());
215    }
216
217    private void UpdatePluginsList() {
218      pluginsListView.Items.Clear();
219
220      // populate plugins list
221      if (productsListView.SelectedItems.Count > 0) {
222        pluginsListView.SuppressItemCheckedEvents = true;
223
224        var selectedItem = productsListView.SelectedItems[0];
225        if (selectedItem.Text == "All Plugins") {
226          foreach (var plugin in plugins) {
227            var item = CreateListViewItem(plugin);
228            pluginsListView.Items.Add(item);
229          }
230        } else {
231          var selectedProduct = (DeploymentService.ProductDescription)productsListView.SelectedItems[0].Tag;
232          foreach (var plugin in selectedProduct.Plugins) {
233            var item = CreateListViewItem(plugin);
234            pluginsListView.Items.Add(item);
235          }
236        }
237
238        Util.ResizeColumns(pluginsListView.Columns.OfType<ColumnHeader>());
239        pluginsListView.SuppressItemCheckedEvents = false;
240      }
241    }
242
243    private ListViewItem CreateListViewItem(DeploymentService.ProductDescription product) {
244      ListViewItem item = new ListViewItem(new string[] { product.Name, product.Version.ToString() });
245      item.Tag = product;
246      item.ImageIndex = 0;
247      return item;
248    }
249
250    private ListViewItem CreateListViewItem(IPluginDescription plugin) {
251      ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(), plugin.Description });
252      item.Tag = plugin;
253      item.ImageIndex = 0;
254      return item;
255    }
256
257    #region products list view events
258    private void productsListView_SelectedIndexChanged(object sender, EventArgs e) {
259      UpdatePluginsList();
260      installProductsButton.Enabled = (productsListView.SelectedItems.Count > 0 &&
261        productsListView.SelectedItems[0].Text != "All Plugins");
262    }
263    #endregion
264
265    #region item checked event handler
266    private void remotePluginsListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
267      foreach (ListViewItem item in pluginsListView.SelectedItems) {
268        IPluginDescription plugin = (IPluginDescription)item.Tag;
269        if (e.Item.Checked)
270          HandlePluginChecked(plugin);
271        else
272          HandlePluginUnchecked(plugin);
273      }
274      installPluginsButton.Enabled = pluginsListView.CheckedItems.Count > 0;
275    }
276
277    private void HandlePluginUnchecked(IPluginDescription plugin) {
278      // also uncheck all dependent plugins
279      List<ListViewItem> modifiedItems = new List<ListViewItem>();
280      modifiedItems.AddRange(FindItemsForPlugin(plugin));
281      var dependentPlugins = Util.GetAllDependents(plugin, plugins);
282      foreach (var dependentPlugin in dependentPlugins) {
283        // there can be multiple entries for a single plugin in different groups
284        foreach (var item in FindItemsForPlugin(dependentPlugin)) {
285          if (item != null && item.Checked) {
286            if (!modifiedItems.Contains(item))
287              modifiedItems.Add(item);
288          }
289        }
290      }
291      pluginsListView.UncheckItems(modifiedItems);
292    }
293
294    private void HandlePluginChecked(IPluginDescription plugin) {
295      // also check all dependencies
296      List<ListViewItem> modifiedItems = new List<ListViewItem>();
297      modifiedItems.AddRange(FindItemsForPlugin(plugin));
298      foreach (var dep in Util.GetAllDependencies(plugin)) {
299        // there can be multiple entries for a single plugin in different groups
300        foreach (ListViewItem item in FindItemsForPlugin(dep)) {
301          if (item != null && !item.Checked) {
302            if (!modifiedItems.Contains(item))
303              modifiedItems.Add(item);
304          }
305        }
306      }
307      pluginsListView.CheckItems(modifiedItems);
308    }
309
310    #endregion
311
312    #region helper methods
313    private IEnumerable<ListViewItem> FindItemsForPlugin(IPluginDescription plugin) {
314      return (from item in pluginsListView.Items.OfType<ListViewItem>()
315              let otherPlugin = item.Tag as IPluginDescription
316              where otherPlugin != null && otherPlugin.Name == plugin.Name && otherPlugin.Version == plugin.Version
317              select item);
318    }
319
320    // compares for two plugins with same major and minor version if plugin1 is newer than plugin2
321    private static bool IsNewerThan(IPluginDescription plugin1, IPluginDescription plugin2) {
322      // newer: build version is higher, or if build version is the same revision is higher
323      return plugin1.Version.Build > plugin2.Version.Build ||
324        (plugin1.Version.Build == plugin2.Version.Build && plugin1.Version.Revision > plugin2.Version.Revision);
325    }
326    #endregion
327
328  }
329}
Note: See TracBrowser for help on using the repository browser.