Free cookie consent management tool by TermsFeed Policy Generator

source: branches/SimulationCore/HeuristicLab.PluginInfrastructure/3.3/Advanced/InstalledPluginsView.cs @ 6683

Last change on this file since 6683 was 6413, checked in by gkronber, 13 years ago

#1536 implemented feature that checks for plugin updates on each application start and allows to install plugin updates easily. Removed more advanced plugin management features for all users except if it is manually reenabled in the HeuristicLab.config file.

File size: 11.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Linq;
26using System.Windows.Forms;
27using HeuristicLab.PluginInfrastructure.Manager;
28
29namespace HeuristicLab.PluginInfrastructure.Advanced {
30  internal partial class InstalledPluginsView : InstallationManagerControl {
31    private const string CheckingPluginsMessage = "Checking for updated plugins...";
32    private const string NoUpdatesAvailableMessage = "No updates available.";
33    private BackgroundWorker removePluginsBackgroundWorker;
34    private BackgroundWorker updatePluginsBackgroundWorker;
35
36    private ListViewGroup enabledPluginsGroup;
37    private ListViewGroup disabledPluginsGroup;
38
39    private PluginManager pluginManager;
40    public PluginManager PluginManager {
41      get { return pluginManager; }
42      set {
43        pluginManager = value;
44        UpdateControl();
45      }
46    }
47
48    private InstallationManager installationManager;
49    public InstallationManager InstallationManager {
50      get { return installationManager; }
51      set { installationManager = value; }
52    }
53
54    public InstalledPluginsView()
55      : base() {
56      InitializeComponent();
57      enabledPluginsGroup = localPluginsListView.Groups["activePluginsGroup"];
58      disabledPluginsGroup = localPluginsListView.Groups["disabledPluginsGroup"];
59      pluginImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Plugin);
60      removePluginsBackgroundWorker = new BackgroundWorker();
61      removePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(removePluginsBackgroundWorker_DoWork);
62      removePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(removePluginsBackgroundWorker_RunWorkerCompleted);
63      updatePluginsBackgroundWorker = new BackgroundWorker();
64      updatePluginsBackgroundWorker.DoWork += new DoWorkEventHandler(updatePluginsBackgroundWorker_DoWork);
65      updatePluginsBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(updatePluginsBackgroundWorker_RunWorkerCompleted);
66
67      UpdateControl();
68    }
69
70
71
72    #region event handlers for plugin removal background worker
73    void removePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
74      if (e.Error != null) {
75        StatusView.ShowError("File Deletion Error", "There was problem while deleting files." + Environment.NewLine + e.Error.Message);
76      }
77      UpdateControl();
78      StatusView.HideProgressIndicator();
79      StatusView.UnlockUI();
80    }
81
82    void removePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
83      IEnumerable<IPluginDescription> pluginsToRemove = (IEnumerable<IPluginDescription>)e.Argument;
84      if (pluginsToRemove.Count() > 0) {
85        installationManager.Remove(pluginsToRemove);
86        pluginManager.DiscoverAndCheckPlugins();
87      }
88    }
89    #endregion
90
91    #region event handlers for update plugins backgroundworker
92    void updatePluginsBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
93      if (e.Error != null) {
94        StatusView.ShowError("Connection Error",
95          "There was an error while connecting to the server." + Environment.NewLine +
96           "Please check your connection settings and user credentials.");
97      }
98      StatusView.RemoveMessage(CheckingPluginsMessage);
99      StatusView.HideProgressIndicator();
100      UpdateControl();
101      StatusView.UnlockUI();
102    }
103
104    void updatePluginsBackgroundWorker_DoWork(object sender, DoWorkEventArgs e) {
105      IEnumerable<IPluginDescription> selectedPlugins = (IEnumerable<IPluginDescription>)e.Argument;
106      var remotePlugins = installationManager.GetRemotePluginList();
107      // if there is a local plugin with same name and same major and minor version then it's an update
108      var pluginsToUpdate = from remotePlugin in remotePlugins
109                            let matchingLocalPlugins = from installedPlugin in selectedPlugins
110                                                       where installedPlugin.Name == remotePlugin.Name
111                                                       where installedPlugin.Version.Major == remotePlugin.Version.Major
112                                                       where installedPlugin.Version.Minor == remotePlugin.Version.Minor
113                                                       where IsNewerThan(remotePlugin, installedPlugin)
114                                                       select installedPlugin
115                            where matchingLocalPlugins.Count() > 0
116                            select remotePlugin;
117      if (pluginsToUpdate.Count() > 0) {
118        bool cancelled;
119        installationManager.Update(pluginsToUpdate, out cancelled);
120        if (!cancelled) pluginManager.DiscoverAndCheckPlugins();
121      }
122    }
123
124    // compares for two plugins with same major and minor version if plugin1 is newer than plugin2
125    private static bool IsNewerThan(IPluginDescription plugin1, IPluginDescription plugin2) {
126      // newer: build version is higher, or if build version is the same revision is higher
127      return plugin1.Version.Build > plugin2.Version.Build ||
128        (plugin1.Version.Build == plugin2.Version.Build && plugin1.Version.Revision > plugin2.Version.Revision);
129    }
130    #endregion
131
132    private void UpdateControl() {
133      ClearPluginList();
134      if (pluginManager != null) {
135        localPluginsListView.SuppressItemCheckedEvents = true;
136        foreach (var plugin in pluginManager.Plugins) {
137          var item = CreateListViewItem(plugin);
138          if (plugin.PluginState == PluginState.Enabled) {
139            item.Group = enabledPluginsGroup;
140          } else if (plugin.PluginState == PluginState.Disabled) {
141            item.Group = disabledPluginsGroup;
142          }
143          localPluginsListView.Items.Add(item);
144        }
145        localPluginsListView.SuppressItemCheckedEvents = false;
146      }
147      removeButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
148      updateSelectedButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
149      Util.ResizeColumns(localPluginsListView.Columns.OfType<ColumnHeader>());
150    }
151
152    private void ClearPluginList() {
153      List<ListViewItem> itemsToRemove = new List<ListViewItem>(localPluginsListView.Items.OfType<ListViewItem>());
154      itemsToRemove.ForEach(item => localPluginsListView.Items.Remove(item));
155    }
156
157    private static ListViewItem CreateListViewItem(PluginDescription plugin) {
158      ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(), plugin.Description });
159      item.Tag = plugin;
160      item.ImageIndex = 0;
161      return item;
162    }
163
164    private void pluginsListView_ItemChecked(object sender, ItemCheckedEventArgs e) {
165      // checked items are marked for removal
166      if (e.Item.Checked) {
167        List<ListViewItem> modifiedItems = new List<ListViewItem>();
168        foreach (ListViewItem item in localPluginsListView.SelectedItems) {
169          modifiedItems.Add(item);
170          int oldItemsCount = 0;
171          while (oldItemsCount < modifiedItems.Count) {
172            oldItemsCount = modifiedItems.Count;
173            var oldModifiedItems = new List<ListViewItem>(modifiedItems);
174            foreach (var modifiedItem in oldModifiedItems) {
175              var plugin = (IPluginDescription)modifiedItem.Tag;
176              // also check all dependent plugins
177              foreach (ListViewItem dependentItem in localPluginsListView.Items) {
178                var dependent = (IPluginDescription)dependentItem.Tag;
179                if (!modifiedItems.Contains(dependentItem) &&
180                  !dependentItem.Checked && (from dep in dependent.Dependencies
181                                             where dep.Name == plugin.Name
182                                             where dep.Version == plugin.Version
183                                             select dep).Any()) {
184                  modifiedItems.Add(dependentItem);
185                }
186              }
187            }
188          }
189        }
190        localPluginsListView.CheckItems(modifiedItems);
191      } else {
192        List<ListViewItem> modifiedItems = new List<ListViewItem>();
193        foreach (ListViewItem item in localPluginsListView.SelectedItems) {
194          modifiedItems.Add(item);
195        }
196        localPluginsListView.UncheckItems(modifiedItems);
197      }
198      OnItemsCheckedChanged(EventArgs.Empty);
199    }
200
201    private void localPluginsListView_ItemActivate(object sender, EventArgs e) {
202      if (localPluginsListView.SelectedItems.Count > 0) {
203        var plugin = (PluginDescription)localPluginsListView.SelectedItems[0].Tag;
204        PluginView pluginView = new PluginView(plugin);
205        pluginView.Show(this);
206      }
207    }
208
209    private void OnItemsCheckedChanged(EventArgs eventArgs) {
210      removeButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
211      updateSelectedButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
212    }
213
214    private void updateSelectedButton_Click(object sender, EventArgs e) {
215      StatusView.LockUI();
216      StatusView.ShowProgressIndicator();
217      StatusView.RemoveMessage(NoUpdatesAvailableMessage);
218      StatusView.ShowMessage(CheckingPluginsMessage);
219      var checkedPlugins = localPluginsListView.CheckedItems.OfType<ListViewItem>()
220        .Select(item => item.Tag)
221        .OfType<IPluginDescription>()
222        .ToList();
223      updatePluginsBackgroundWorker.RunWorkerAsync(checkedPlugins);
224    }
225
226    private void removeButton_Click(object sender, EventArgs e) {
227      StatusView.LockUI();
228      StatusView.ShowProgressIndicator();
229      var checkedPlugins = localPluginsListView.CheckedItems.OfType<ListViewItem>()
230        .Select(item => item.Tag)
231        .OfType<IPluginDescription>()
232        .ToList();
233      removePluginsBackgroundWorker.RunWorkerAsync(checkedPlugins);
234    }
235
236    private void refreshButton_Click(object sender, EventArgs e) {
237      StatusView.LockUI();
238      StatusView.ShowProgressIndicator();
239      // refresh = update empty list of plugins (plugins are reloaded)
240      updatePluginsBackgroundWorker.RunWorkerAsync(new IPluginDescription[0]);
241    }
242  }
243}
Note: See TracBrowser for help on using the repository browser.