Free cookie consent management tool by TermsFeed Policy Generator

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

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

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

File size: 15.0 KB
RevLine 
[3090]1#region License Information
2/* HeuristicLab
[16565]3 * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[3090]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;
[2922]22using System.Collections.Generic;
23using System.ComponentModel;
24using System.Linq;
25using System.Windows.Forms;
[3547]26using HeuristicLab.PluginInfrastructure.Manager;
[2922]27
28namespace HeuristicLab.PluginInfrastructure.Advanced {
[3627]29  internal partial class AvailablePluginsView : InstallationManagerControl {
[3547]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;
[3112]41
[2922]42    private IEnumerable<DeploymentService.ProductDescription> products;
43    private IEnumerable<IPluginDescription> plugins;
44
[3608]45    private IEnumerable<IPluginDescription> CheckedPlugins {
[2922]46      get {
[3608]47        return (from item in pluginsListView.Items.OfType<ListViewItem>()
[2922]48                where item.Checked
49                let plugin = item.Tag as IPluginDescription
50                where plugin != null
51                select plugin).ToList();
52      }
53    }
54
[3547]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    }
[3627]65    public AvailablePluginsView() {
[3547]66      InitializeComponent();
[3721]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);
[3547]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;
[3608]88        products = refreshResult.RemoteProducts;
89        plugins = refreshResult.RemotePlugins;
90        UpdateControl();
[3547]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;
[6413]119      bool cancelled = false;
[3547]120      if (info.PluginsToInstall.Count() > 0)
[6413]121        installationManager.Install(info.PluginsToInstall, out cancelled);
[3547]122      if (info.PluginsToUpdate.Count() > 0)
[6413]123        installationManager.Update(info.PluginsToUpdate, out cancelled);
[3547]124
[6413]125      if (!cancelled && (info.PluginsToInstall.Count() > 0 || info.PluginsToUpdate.Count() > 0))
[3547]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    }
[3608]138    private void installPluginsButton_Click(object sender, EventArgs e) {
[3547]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    }
[3608]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
[6413]179      updateOrInstallInfo.PluginsToInstall =
[4529]180        pluginsToInstall
181        .Cast<IPluginDescription>()
182        .ToList();
[6413]183      updateOrInstallInfo.PluginsToUpdate =
[4529]184        pluginsToUpdate
185        .Cast<IPluginDescription>()
186        .ToList();
[3608]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
[3547]198    #endregion
199
[2922]200    private void UpdateControl() {
[3608]201      // clear products view
202      List<ListViewItem> productItemsToDelete = new List<ListViewItem>(productsListView.Items.OfType<ListViewItem>());
203      productItemsToDelete.ForEach(item => productsListView.Items.Remove(item));
[2922]204
[3608]205      // populate products list view
206      foreach (var product in products) {
[2922]207        var item = CreateListViewItem(product);
[3608]208        productsListView.Items.Add(item);
[2922]209      }
[3608]210      var allPluginsListViewItem = new ListViewItem();
211      allPluginsListViewItem.Text = "All Plugins";
212      allPluginsListViewItem.ImageIndex = 0;
213      productsListView.Items.Add(allPluginsListViewItem);
[3624]214      Util.ResizeColumns(productsListView.Columns.OfType<ColumnHeader>());
[2922]215    }
216
[3608]217    private void UpdatePluginsList() {
[3627]218      pluginsListView.Items.Clear();
[3608]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
[3624]238        Util.ResizeColumns(pluginsListView.Columns.OfType<ColumnHeader>());
[3608]239        pluginsListView.SuppressItemCheckedEvents = false;
240      }
[2922]241    }
242
243    private ListViewItem CreateListViewItem(DeploymentService.ProductDescription product) {
[3608]244      ListViewItem item = new ListViewItem(new string[] { product.Name, product.Version.ToString() });
[2922]245      item.Tag = product;
[3608]246      item.ImageIndex = 0;
[2922]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;
[3608]253      item.ImageIndex = 0;
[2922]254      return item;
255    }
256
[3608]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
[2922]265    #region item checked event handler
266    private void remotePluginsListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
[3608]267      foreach (ListViewItem item in pluginsListView.SelectedItems) {
[3627]268        IPluginDescription plugin = (IPluginDescription)item.Tag;
269        if (e.Item.Checked)
270          HandlePluginChecked(plugin);
271        else
272          HandlePluginUnchecked(plugin);
[2922]273      }
[3608]274      installPluginsButton.Enabled = pluginsListView.CheckedItems.Count > 0;
[2922]275    }
276
277    private void HandlePluginUnchecked(IPluginDescription plugin) {
278      // also uncheck all dependent plugins
[3068]279      List<ListViewItem> modifiedItems = new List<ListViewItem>();
[3112]280      modifiedItems.AddRange(FindItemsForPlugin(plugin));
[3627]281      var dependentPlugins = Util.GetAllDependents(plugin, plugins);
[2922]282      foreach (var dependentPlugin in dependentPlugins) {
[3112]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          }
[2922]289        }
290      }
[3608]291      pluginsListView.UncheckItems(modifiedItems);
[2922]292    }
293
294    private void HandlePluginChecked(IPluginDescription plugin) {
295      // also check all dependencies
[3068]296      List<ListViewItem> modifiedItems = new List<ListViewItem>();
[3112]297      modifiedItems.AddRange(FindItemsForPlugin(plugin));
[3627]298      foreach (var dep in Util.GetAllDependencies(plugin)) {
[3112]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          }
[2922]305        }
306      }
[3608]307      pluginsListView.CheckItems(modifiedItems);
[2922]308    }
309
310    #endregion
311
312    #region helper methods
[3112]313    private IEnumerable<ListViewItem> FindItemsForPlugin(IPluginDescription plugin) {
[3608]314      return (from item in pluginsListView.Items.OfType<ListViewItem>()
[2922]315              let otherPlugin = item.Tag as IPluginDescription
316              where otherPlugin != null && otherPlugin.Name == plugin.Name && otherPlugin.Version == plugin.Version
[3112]317              select item);
[2922]318    }
319
[4527]320    // compares for two plugins with same major and minor version if plugin1 is newer than plugin2
[4482]321    private static bool IsNewerThan(IPluginDescription plugin1, IPluginDescription plugin2) {
[3547]322      // newer: build version is higher, or if build version is the same revision is higher
[4527]323      return plugin1.Version.Build > plugin2.Version.Build ||
324        (plugin1.Version.Build == plugin2.Version.Build && plugin1.Version.Revision > plugin2.Version.Revision);
[3547]325    }
[2922]326    #endregion
[3112]327
[2922]328  }
329}
Note: See TracBrowser for help on using the repository browser.