#3136
[heuristiclab.git] / HeuristicLab.PluginInfrastructure / 3.3 / Advanced / InstalledPluginsView.cs
bloba0ee163c47b4db2762c18b383ab2c7106545fa70
1 #region License Information
2 /* HeuristicLab
3 * Copyright (C) Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 * This file is part of HeuristicLab.
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.
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.
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/>.
20 #endregion
22 using System;
23 using System.Collections.Generic;
24 using System.ComponentModel;
25 using System.Linq;
26 using System.Windows.Forms;
27 using HeuristicLab.PluginInfrastructure.Manager;
29 namespace 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;
36 private ListViewGroup enabledPluginsGroup;
37 private ListViewGroup disabledPluginsGroup;
39 private PluginManager pluginManager;
40 public PluginManager PluginManager {
41 get { return pluginManager; }
42 set {
43 pluginManager = value;
44 UpdateControl();
48 private InstallationManager installationManager;
49 public InstallationManager InstallationManager {
50 get { return installationManager; }
51 set { installationManager = value; }
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);
67 UpdateControl();
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);
77 UpdateControl();
78 StatusView.HideProgressIndicator();
79 StatusView.UnlockUI();
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();
89 #endregion
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.");
98 StatusView.RemoveMessage(CheckingPluginsMessage);
99 StatusView.HideProgressIndicator();
100 UpdateControl();
101 StatusView.UnlockUI();
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();
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);
130 #endregion
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;
143 localPluginsListView.Items.Add(item);
145 localPluginsListView.SuppressItemCheckedEvents = false;
147 removeButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
148 updateSelectedButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
149 Util.ResizeColumns(localPluginsListView.Columns.OfType<ColumnHeader>());
152 private void ClearPluginList() {
153 List<ListViewItem> itemsToRemove = new List<ListViewItem>(localPluginsListView.Items.OfType<ListViewItem>());
154 itemsToRemove.ForEach(item => localPluginsListView.Items.Remove(item));
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;
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);
190 localPluginsListView.CheckItems(modifiedItems);
191 } else {
192 List<ListViewItem> modifiedItems = new List<ListViewItem>();
193 foreach (ListViewItem item in localPluginsListView.SelectedItems) {
194 modifiedItems.Add(item);
196 localPluginsListView.UncheckItems(modifiedItems);
198 OnItemsCheckedChanged(EventArgs.Empty);
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);
209 private void OnItemsCheckedChanged(EventArgs eventArgs) {
210 removeButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
211 updateSelectedButton.Enabled = localPluginsListView.CheckedItems.Count > 0;
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);
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);
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]);