using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Windows.Controls; using System.Windows.Data; using HeuristicLab.BackgroundProcessing; using System.ComponentModel; using System.Windows; using System.IO; using System.Threading; using System.Collections.Specialized; using HeuristicLab.MainForm.WPF; using HeuristicLab.OKB.Cockpit.Query.OKBQuery; using HeuristicLab.MainForm; using HeuristicLab.OKB.Client; namespace HeuristicLab.OKB.Cockpit.Query { public partial class RunView : UserControl, IAutoView, IOKBCockpitItem { private object selectorRefreshLock = new object(); private AttributeSelectors attributeSelectors; private DataTable runTable; private List selectors = null; private ManualResetEvent selectorsInitialized = new ManualResetEvent(false); public RunView() { InitializeComponent(); attributeSelectors = new AttributeSelectors(); GridView view = (GridView)Runs.View; attributeSelectors.CollectionChanged += (sender, args) => { if (args.Action == NotifyCollectionChangedAction.Add) { foreach (AttributeSelector selector in args.NewItems) { GridViewColumn column = new GridViewColumn() { Header = selector, DisplayMemberBinding = new Binding(selector.ColumnName), }; view.Columns.Add(column); selector.PropertyChanged += (s, a) => { if (a.PropertyName == "ColumnName") { column.DisplayMemberBinding = new Binding(selector.ColumnName); } Validate(); }; } } else if (args.Action == NotifyCollectionChangedAction.Remove) { foreach (AttributeSelector selector in args.OldItems) { view.Columns.Remove(view.Columns.First(i => i.Header == selector)); } } }; attributeSelectors.Add(new AttributeSelector("Run", "Id", typeof(int))); attributeSelectors.Add(new AttributeSelector("Run", "FinishedDate", typeof(DateTime))); attributeSelectors.Add(new AttributeSelector("Algorithm", "Name", typeof(string))); attributeSelectors.Add(new AttributeSelector("Problem", "Name", typeof(string))); attributeSelectors.Add(new AttributeSelector("SolutionRepresentation", "Name", typeof(string))); RefreshSelectors(); } #region IView Members public string Caption { get { return "Run View"; } set { throw new NotSupportedException(); } } public event EventHandler CaptionChanged; public event EventHandler Changed; protected void OnChanged() { EventHandler handler = CaptionChanged; if (handler != null) handler(this, EventArgs.Empty); } public virtual void Close() { MainFormManager.GetMainForm().CloseView(this); IsShown = false; } public void Hide() { MainFormManager.GetMainForm().HideView(this); IsShown = false; } public bool IsShown { get; protected set; } private bool readOnly = false; public bool ReadOnly { get { return readOnly; } set { if (value == readOnly) return; readOnly = value; OnReadOnlyChanged(); } } public event EventHandler ReadOnlyChanged; protected void OnReadOnlyChanged() { EventHandler handler = ReadOnlyChanged; if (handler != null) handler(this, EventArgs.Empty); } public void Show() { MainFormManager.GetMainForm().ShowView(this); IsShown = true; } #endregion protected void OnAddClicked(object sender, EventArgs args) { AddItem(); } protected void OnCheckClicked(object sender, EventArgs args) { var loader = new ObservableBackgroundWorker("Checking Runs"); int? count = null; bool failed = false; loader.DoWork += (snd, arg) => { try { QueryServiceClient client = ClientFactory.Create(); client.PrepareQuery(attributeSelectors.ToList()); count = client.GetCount(); client.Terminate(); client.Close(); } catch { failed = true; } }; loader.RunWorkerCompleted += (snd, arg) => { if (failed) { NrOfRunsLabel.Text = "?"; MessageBox.Show("Checking runs failed.", Caption); } else { NrOfRunsLabel.Text = count.ToString(); } }; loader.RunWorkerAsync(); } private void RefreshSelectors() { ObservableBackgroundWorker loader = new ObservableBackgroundWorker("Fetching DB schema"); bool failed = false; loader.DoWork += (s, a) => { try { QueryServiceClient client = ClientFactory.Create(); selectors = client.GetAllAttributeSelectors(); } catch { failed = true; } finally { selectorsInitialized.Set(); } }; loader.RunWorkerCompleted += (s, a) => { if (failed) { if (MessageBox.Show( "Could not fetch DB Schema. Retry?", Caption, MessageBoxButton.OKCancel) == MessageBoxResult.OK) { selectorsInitialized.Reset(); RefreshSelectors(); } } }; loader.RunWorkerAsync(); } protected void AddItem() { BackgroundWorker waiter = new BackgroundWorker(); waiter.DoWork += (s, a) => selectorsInitialized.WaitOne(); waiter.RunWorkerCompleted += (s, a) => { if (!VerifySelectors()) return; var selector = new AttributeSelectorWindow(selectors) { Owner = MainFormManager.GetMainForm(), }; if (selector.ShowDialog() == true) { attributeSelectors.Add(selector.AttributeSelector); } }; waiter.RunWorkerAsync(); } private bool VerifySelectors() { if (selectors == null && MessageBox.Show( "Schema information not available. Retry?", this.Caption, MessageBoxButton.OKCancel) == MessageBoxResult.OK) { selectorsInitialized.Reset(); RefreshSelectors(); return false; } return true; } protected void OnUpdateClicked(object sender, EventArgs args) { var loader = new ObservableBackgroundWorker("Preparing Query") { WorkerReportsProgress = true, WorkerSupportsCancellation = true, }; int total = 0; loader.DoWork += (snd, arg) => { loader.ReportProgress(0); QueryServiceClient client = ClientFactory.Create(); runTable = client.PrepareQuery(attributeSelectors.ToList()); loader.ReportProgress(50); total = client.GetCount(); int stepSize = Math.Max(1, Math.Min(total / 100, 100)); loader.ReportProgress(100); Thread.Sleep(0); loader.Name = "Loading Runs"; loader.ReportProgress(0); if (total > 0) { DataTable newRows = new DataTable(); do { newRows = client.GetNextRows(stepSize); runTable.Merge(newRows); loader.ReportProgress(100 * runTable.Rows.Count / total); } while (!loader.CancellationPending && newRows.Rows.Count > 0); } client.Terminate(); client.Close(); loader.ReportProgress(100); }; loader.RunWorkerCompleted += (snd, arg) => { if (arg.Error == null) { NrOfRunsLabel.Text = total.ToString(); for (int i = 0; i < runTable.Columns.Count; i++) { attributeSelectors[i].ColumnName = runTable.Columns[i].ColumnName; } Runs.DataContext = runTable; Runs.SetBinding(ListView.ItemsSourceProperty, new Binding()); } else { NrOfRunsLabel.Text = "?"; } }; loader.RunWorkerAsync(); } protected void ContextMenuClicked(object sender, RoutedEventArgs args) { ContextMenu menu = sender as ContextMenu; MenuItem item = args.Source as MenuItem; AttributeSelector selector = menu.Tag as AttributeSelector; if (menu == null || item == null || selector == null) return; if (item.Name == "ConfigureItem") { BackgroundWorker waiter = new BackgroundWorker(); waiter.DoWork += (s, a) => selectorsInitialized.WaitOne(); waiter.RunWorkerCompleted += (s, a) => { if (!VerifySelectors()) return; var selectorView = new AttributeSelectorWindow(selectors) { Owner = MainFormManager.GetMainForm(), AttributeSelector = selector, }; selectorView.ShowDialog(); }; waiter.RunWorkerAsync(); } else if (item.Name == "RemoveItem") { attributeSelectors.Remove(selector); } else if (item.Name == "AddColumn") { AddItem(); } } protected void OnCopyClicked(object sender, RoutedEventArgs args) { ObservableBackgroundWorker copier = new ObservableBackgroundWorker("Copying to Clipboard") { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; StringBuilder sb = new StringBuilder(); copier.DoWork += (s, a) => { sb.Append( string.Join("\t", runTable.Columns.Cast() .Select(c => c.ColumnName) .ToArray())) .Append('\n'); int i = 0; int lastProgress = 0; foreach (DataRow row in runTable.Rows) { sb.Append(string.Join("\t", row.ItemArray.Select(v => v.ToString()).ToArray())).Append('\n'); i++; int progress = 100 * i / runTable.Rows.Count; if (progress > lastProgress) { copier.ReportProgress(progress); lastProgress = progress; Thread.Sleep(0); } if (copier.CancellationPending) { a.Cancel = true; break; } } }; copier.RunWorkerCompleted += (s, a) => { if (!a.Cancelled) Clipboard.SetText(sb.ToString(), TextDataFormat.Text); }; copier.RunWorkerAsync(); } protected void Validate() { CheckButton.IsEnabled = UpdateButton.IsEnabled = attributeSelectors.All(s => s.IsValid); if (CheckButton.IsEnabled) { ErrorMessages.Text = ""; } else { ErrorMessages.Text = "Invalid attribute selector configuration"; } } } }