Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.PluginInfrastructure/3.3/Advanced/EditProductsView.cs @ 17078

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

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

File size: 17.9 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
21
22using System;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Linq;
26using System.ServiceModel;
27using System.Windows.Forms;
28
29namespace HeuristicLab.PluginInfrastructure.Advanced {
30  internal partial class EditProductsView : InstallationManagerControl {
31    private const string RefreshMessage = "Downloading product and plugin information...";
32    private const string UploadMessage = "Uploading product and plugin information...";
33    private const string DeleteProductMessage = "Deleting product...";
34
35    private BackgroundWorker refreshProductsWorker;
36    private BackgroundWorker uploadChangedProductsWorker;
37    private BackgroundWorker deleteProductWorker;
38
39    private List<DeploymentService.ProductDescription> products;
40    private List<DeploymentService.PluginDescription> plugins;
41    private HashSet<DeploymentService.ProductDescription> dirtyProducts;
42
43    public EditProductsView() {
44      InitializeComponent();
45
46      productImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Setup_Install);
47      productImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.ArrowUp);
48      pluginImageList.Images.Add(HeuristicLab.PluginInfrastructure.Resources.Plugin);
49
50      dirtyProducts = new HashSet<DeploymentService.ProductDescription>();
51      refreshProductsWorker = new BackgroundWorker();
52      refreshProductsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(refreshProductsWorker_RunWorkerCompleted);
53      refreshProductsWorker.DoWork += new DoWorkEventHandler(refreshProductsWorker_DoWork);
54
55      uploadChangedProductsWorker = new BackgroundWorker();
56      uploadChangedProductsWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(uploadChangedProductsWorker_RunWorkerCompleted);
57      uploadChangedProductsWorker.DoWork += new DoWorkEventHandler(uploadChangedProductsWorker_DoWork);
58
59      deleteProductWorker = new BackgroundWorker();
60      deleteProductWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(deleteProductWorker_RunWorkerCompleted);
61      deleteProductWorker.DoWork += new DoWorkEventHandler(deleteProductWorker_DoWork);
62    }
63
64    #region event handlers for delete product background worker
65    void deleteProductWorker_DoWork(object sender, DoWorkEventArgs e) {
66      var products = (IEnumerable<DeploymentService.ProductDescription>)e.Argument;
67      var adminClient = DeploymentService.AdminServiceClientFactory.CreateClient();
68      // upload
69      try {
70        foreach (var product in products) {
71          adminClient.DeleteProduct(product);
72        }
73        adminClient.Close();
74      }
75      catch (TimeoutException) {
76        adminClient.Abort();
77        throw;
78      }
79      catch (FaultException) {
80        adminClient.Abort();
81        throw;
82      }
83      catch (CommunicationException) {
84        adminClient.Abort();
85        throw;
86      }
87      // refresh     
88      var updateClient = DeploymentService.UpdateServiceClientFactory.CreateClient();
89      try {
90        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
91        updateClient.Close();
92      }
93      catch (TimeoutException) {
94        updateClient.Abort();
95        throw;
96      }
97      catch (FaultException) {
98        updateClient.Abort();
99        throw;
100      }
101      catch (CommunicationException) {
102        updateClient.Abort();
103        throw;
104      }
105    }
106
107    void deleteProductWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
108      if (e.Error != null) {
109        StatusView.ShowError("Connection Error",
110        "There was an error while connecting to the server." + Environment.NewLine +
111           "Please check your connection settings and user credentials.");
112        this.products.Clear();
113        this.plugins.Clear();
114      } else {
115        this.products = new List<DeploymentService.ProductDescription>(
116  (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
117        this.plugins = new List<DeploymentService.PluginDescription>(
118          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
119
120        EnableControls();
121      }
122      UpdateProductsList();
123      dirtyProducts.Clear();
124      StatusView.HideProgressIndicator();
125      StatusView.RemoveMessage(DeleteProductMessage);
126      StatusView.UnlockUI();
127    }
128    #endregion
129
130    #region event handlers for upload products background worker
131    private void uploadChangedProductsWorker_DoWork(object sender, DoWorkEventArgs e) {
132      var products = (IEnumerable<DeploymentService.ProductDescription>)e.Argument;
133      var adminClient = DeploymentService.AdminServiceClientFactory.CreateClient();
134      // upload
135      try {
136        foreach (var product in products) {
137          adminClient.DeployProduct(product);
138        }
139        adminClient.Close();
140      }
141      catch (TimeoutException) {
142        adminClient.Abort();
143        throw;
144      }
145      catch (FaultException) {
146        adminClient.Abort();
147        throw;
148      }
149      catch (CommunicationException) {
150        adminClient.Abort();
151        throw;
152      }
153      // refresh     
154      var updateClient = DeploymentService.UpdateServiceClientFactory.CreateClient();
155      try {
156        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
157        updateClient.Close();
158      }
159      catch (TimeoutException) {
160        updateClient.Abort();
161        throw;
162      }
163      catch (FaultException) {
164        updateClient.Abort();
165        throw;
166      }
167      catch (CommunicationException) {
168        updateClient.Abort();
169        throw;
170      }
171    }
172
173    private void uploadChangedProductsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
174      if (e.Error != null) {
175        StatusView.ShowError("Connection Error",
176        "There was an error while connecting to the server." + Environment.NewLine +
177           "Please check your connection settings and user credentials.");
178        this.products.Clear();
179        this.plugins.Clear();
180      } else {
181        this.products = new List<DeploymentService.ProductDescription>(
182  (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
183        this.plugins = new List<DeploymentService.PluginDescription>(
184          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
185
186      }
187      UpdateProductsList();
188      dirtyProducts.Clear();
189      EnableControls();
190      StatusView.HideProgressIndicator();
191      StatusView.RemoveMessage(UploadMessage);
192      StatusView.UnlockUI();
193    }
194    #endregion
195
196    #region event handlers for refresh products background worker
197    private void refreshProductsWorker_DoWork(object sender, DoWorkEventArgs e) {
198      var updateClient = DeploymentService.UpdateServiceClientFactory.CreateClient();
199      try {
200        e.Result = new object[] { updateClient.GetProducts(), updateClient.GetPlugins() };
201        updateClient.Close();
202      }
203      catch (TimeoutException) {
204        updateClient.Abort();
205        throw;
206      }
207      catch (FaultException) {
208        updateClient.Abort();
209        throw;
210      }
211      catch (CommunicationException) {
212        updateClient.Abort();
213        throw;
214      }
215    }
216
217    private void refreshProductsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
218      if (e.Error != null) {
219        StatusView.ShowError("Connection Error",
220          "There was an error while connecting to the server." + Environment.NewLine +
221                   "Please check your connection settings and user credentials.");
222        this.products.Clear();
223        this.plugins.Clear();
224
225      } else {
226        this.products = new List<DeploymentService.ProductDescription>(
227          (DeploymentService.ProductDescription[])((object[])e.Result)[0]);
228        this.plugins = new List<DeploymentService.PluginDescription>(
229          (DeploymentService.PluginDescription[])((object[])e.Result)[1]);
230      }
231      UpdateProductsList();
232      dirtyProducts.Clear();
233      EnableControls();
234      StatusView.HideProgressIndicator();
235      StatusView.RemoveMessage(RefreshMessage);
236      StatusView.UnlockUI();
237    }
238    #endregion
239
240    private void UpdateProductsList() {
241      productsListView.SelectedItems.Clear();
242      productsListView.Items.Clear();
243      foreach (var prodDesc in products) {
244        productsListView.Items.Add(CreateListViewItem(prodDesc));
245      }
246      Util.ResizeColumns(productsListView.Columns.OfType<ColumnHeader>());
247    }
248
249    private void productsListBox_SelectedIndexChanged(object sender, EventArgs e) {
250      bool productSelected = productsListView.SelectedItems.Count > 0;
251      detailsGroupBox.Enabled = productSelected;
252      UpdateProductButtons();
253      if (productSelected) {
254        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)((ListViewItem)productsListView.SelectedItems[0]).Tag;
255        nameTextBox.Text = activeProduct.Name;
256        versionTextBox.Text = activeProduct.Version.ToString();
257
258        // populate plugins list view
259        pluginListView.SuppressItemCheckedEvents = true;
260        foreach (var plugin in plugins.OfType<IPluginDescription>()) {
261          pluginListView.Items.Add(CreateListViewItem(plugin));
262        }
263        pluginListView.SuppressItemCheckedEvents = false;
264        foreach (var plugin in activeProduct.Plugins) {
265          pluginListView.CheckItems(FindItemsForPlugin(plugin));
266        }
267      } else {
268        nameTextBox.Text = string.Empty;
269        versionTextBox.Text = string.Empty;
270        pluginListView.Items.Clear();
271      }
272      Util.ResizeColumns(pluginListView.Columns.OfType<ColumnHeader>());
273    }
274
275    private void UpdateProductButtons() {
276      uploadButton.Enabled = dirtyProducts.Count > 0;
277      if (productsListView.SelectedItems.Count > 0) {
278        var selectedProduct = (DeploymentService.ProductDescription)productsListView.SelectedItems[0].Tag;
279        deleteProductButton.Enabled = !dirtyProducts.Contains(selectedProduct);
280      } else {
281        deleteProductButton.Enabled = false;
282      }
283    }
284
285
286    #region button event handlers
287    private void newProductButton_Click(object sender, EventArgs e) {
288      var newProduct = new DeploymentService.ProductDescription("New product", new Version("0.0.0.0"));
289      products.Add(newProduct);
290      UpdateProductsList();
291      MarkProductDirty(newProduct);
292    }
293
294    private void saveButton_Click(object sender, EventArgs e) {
295      StatusView.LockUI();
296      StatusView.ShowProgressIndicator();
297      StatusView.ShowMessage(UploadMessage);
298      uploadChangedProductsWorker.RunWorkerAsync(dirtyProducts);
299    }
300    private void refreshButton_Click(object sender, EventArgs e) {
301      StatusView.LockUI();
302      StatusView.ShowProgressIndicator();
303      StatusView.ShowMessage(RefreshMessage);
304      refreshProductsWorker.RunWorkerAsync();
305    }
306    private void deleteProductButton_Click(object sender, EventArgs e) {
307      StatusView.LockUI();
308      StatusView.ShowProgressIndicator();
309      StatusView.ShowMessage(DeleteProductMessage);
310      var selectedProducts = from item in productsListView.SelectedItems.OfType<ListViewItem>()
311                             select (DeploymentService.ProductDescription)item.Tag;
312      deleteProductWorker.RunWorkerAsync(selectedProducts.ToList());
313    }
314
315    #endregion
316
317    #region textbox changed event handlers
318    private void nameTextBox_TextChanged(object sender, EventArgs e) {
319      if (productsListView.SelectedItems.Count > 0) {
320        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
321        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
322        if (string.IsNullOrEmpty(nameTextBox.Name)) {
323          errorProvider.SetError(nameTextBox, "Invalid value");
324        } else {
325          if (activeProduct.Name != nameTextBox.Text) {
326            activeProduct.Name = nameTextBox.Text;
327            activeItem.SubItems[0].Text = activeProduct.Name;
328            errorProvider.SetError(nameTextBox, string.Empty);
329            MarkProductDirty(activeProduct);
330          }
331        }
332      }
333    }
334
335
336    private void versionTextBox_TextChanged(object sender, EventArgs e) {
337      if (productsListView.SelectedItems.Count > 0) {
338        ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
339        DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
340        try {
341          var newVersion = new Version(versionTextBox.Text);
342          if (activeProduct.Version != newVersion) {
343            activeProduct.Version = newVersion;
344            activeItem.SubItems[1].Text = versionTextBox.Text;
345            errorProvider.SetError(versionTextBox, string.Empty);
346            MarkProductDirty(activeProduct);
347          }
348        }
349        catch (OverflowException) {
350          errorProvider.SetError(versionTextBox, "Invalid value");
351        }
352
353        catch (ArgumentException) {
354          errorProvider.SetError(versionTextBox, "Invalid value");
355        }
356        catch (FormatException) {
357          errorProvider.SetError(versionTextBox, "Invalid value");
358        }
359      }
360    }
361    #endregion
362
363
364    #region plugin list view
365    private void OnItemChecked(ItemCheckedEventArgs e) {
366      ListViewItem activeItem = (ListViewItem)productsListView.SelectedItems[0];
367      DeploymentService.ProductDescription activeProduct = (DeploymentService.ProductDescription)activeItem.Tag;
368      activeProduct.Plugins = (from item in pluginListView.CheckedItems.OfType<ListViewItem>()
369                               select (DeploymentService.PluginDescription)item.Tag).ToArray();
370      MarkProductDirty(activeProduct);
371    }
372
373    private void listView_ItemChecked(object sender, ItemCheckedEventArgs e) {
374      List<IPluginDescription> modifiedPlugins = new List<IPluginDescription>();
375      if (e.Item.Checked) {
376        foreach (ListViewItem item in pluginListView.SelectedItems) {
377          var plugin = (IPluginDescription)item.Tag;
378          // also check all dependencies
379          if (!modifiedPlugins.Contains(plugin))
380            modifiedPlugins.Add(plugin);
381          foreach (var dep in Util.GetAllDependencies(plugin)) {
382            if (!modifiedPlugins.Contains(dep))
383              modifiedPlugins.Add(dep);
384          }
385        }
386        pluginListView.CheckItems(modifiedPlugins.Select(x => FindItemsForPlugin(x).Single()));
387        OnItemChecked(e);
388      } else {
389        foreach (ListViewItem item in pluginListView.SelectedItems) {
390          var plugin = (IPluginDescription)item.Tag;
391          // also uncheck all dependent plugins
392          if (!modifiedPlugins.Contains(plugin))
393            modifiedPlugins.Add(plugin);
394          foreach (var dep in Util.GetAllDependents(plugin, plugins.Cast<IPluginDescription>())) {
395            if (!modifiedPlugins.Contains(dep))
396              modifiedPlugins.Add(dep);
397          }
398
399        }
400        pluginListView.UncheckItems(modifiedPlugins.Select(x => FindItemsForPlugin(x).Single()));
401        OnItemChecked(e);
402      }
403    }
404
405
406    #endregion
407
408    #region helper
409    private void MarkProductDirty(HeuristicLab.PluginInfrastructure.Advanced.DeploymentService.ProductDescription activeProduct) {
410      if (!dirtyProducts.Contains(activeProduct)) {
411        dirtyProducts.Add(activeProduct);
412        var item = FindItemForProduct(activeProduct);
413        item.ImageIndex = 1;
414        UpdateProductButtons();
415      }
416    }
417    private ListViewItem CreateListViewItem(DeploymentService.ProductDescription productDescription) {
418      ListViewItem item = new ListViewItem(new string[] { productDescription.Name, productDescription.Version.ToString() });
419      item.Tag = productDescription;
420      item.ImageIndex = 0;
421      return item;
422    }
423
424    private ListViewItem CreateListViewItem(IPluginDescription plugin) {
425      ListViewItem item = new ListViewItem(new string[] { plugin.Name, plugin.Version.ToString(),
426          string.Empty, plugin.Description });
427      item.Tag = plugin;
428      item.ImageIndex = 0;
429      item.Checked = false;
430      return item;
431    }
432
433    private ListViewItem FindItemForProduct(HeuristicLab.PluginInfrastructure.Advanced.DeploymentService.ProductDescription activeProduct) {
434      return (from item in productsListView.Items.OfType<ListViewItem>()
435              let product = item.Tag as DeploymentService.ProductDescription
436              where product != null
437              where product == activeProduct
438              select item).Single();
439    }
440    private IEnumerable<ListViewItem> FindItemsForPlugin(IPluginDescription plugin) {
441      return from item in pluginListView.Items.OfType<ListViewItem>()
442             let p = item.Tag as IPluginDescription
443             where p.Name == plugin.Name
444             where p.Version == plugin.Version
445             select item;
446    }
447
448    private void EnableControls() {
449      newProductButton.Enabled = true;
450      productsListView.Enabled = true;
451    }
452    #endregion
453
454  }
455}
Note: See TracBrowser for help on using the repository browser.