source: branches/eraser6/XmlTaskLists/Eraser/LogForm.cs @ 2603

Revision 2603, 9.4 KB checked in by lowjoel, 2 years ago (diff)

Allow us to view logs for Lazy-loading log sinks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Rev URL
Line 
1/*
2 * $Id$
3 * Copyright 2008-2012 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Linq;
26using System.Drawing;
27using System.Text;
28using System.Windows.Forms;
29using System.Globalization;
30using System.IO;
31
32using Eraser.Manager;
33using Eraser.Util;
34
35namespace Eraser
36{
37    public partial class LogForm : Form, ILogTarget
38    {
39        public LogForm(Task task)
40        {
41            InitializeComponent();
42            Theming.ApplyTheme(this);
43
44            //Update the title
45            Text = string.Format(CultureInfo.InvariantCulture, "{0} - {1}", Text, task);
46
47            //Populate the list of sessions
48            foreach (LogSinkBase sink in task.Log)
49                filterSessionCombobox.Items.Add(sink.StartTime);
50            if (filterSessionCombobox.Items.Count != 0)
51                filterSessionCombobox.SelectedIndex = filterSessionCombobox.Items.Count - 1;
52
53            //Set the filter settings
54            filterFilterTypeCombobox.SelectedIndex = 0;
55            filterSeverityCombobox.SelectedIndex = 0;
56
57            //Display the log entries
58            Task = task;
59            RefreshMessages();
60            EnableButtons();
61
62            //Register our event handler to get live log messages
63            if (Task.Log.Count > 0)
64                Task.Log.Last().Chain(this);
65            Task.TaskStarted += task_TaskStarted;
66        }
67
68        private void LogForm_FormClosed(object sender, FormClosedEventArgs e)
69        {
70            Task.TaskStarted -= task_TaskStarted;
71            if (Task.Log.Count > 0)
72                Task.Log.Last().Unchain(this);
73        }
74
75        private void filter_Changed(object sender, EventArgs e)
76        {
77            RefreshMessages();
78        }
79
80        private void task_TaskStarted(object sender, EventArgs e)
81        {
82            if (IsDisposed || !IsHandleCreated)
83                return;
84            if (InvokeRequired)
85            {
86                Invoke((EventHandler<EventArgs>)task_TaskStarted, sender, e);
87                return;
88            }
89
90            filterSessionCombobox.Items.Add(Task.Log.Last().StartTime);
91        }
92
93        private void log_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
94        {
95            LogEntry entry = EntryCache[e.ItemIndex];
96            e.Item = new ListViewItem(entry.Timestamp.ToString("F", CultureInfo.CurrentCulture));
97            e.Item.SubItems.Add(entry.Level.ToString());
98            e.Item.SubItems.Add(entry.Message);
99
100            switch (entry.Level)
101            {
102                case LogLevel.Fatal:
103                    e.Item.ForeColor = Color.Red;
104                    break;
105                case LogLevel.Error:
106                    e.Item.ForeColor = Color.OrangeRed;
107                    break;
108                case LogLevel.Warning:
109                    e.Item.ForeColor = Color.Orange;
110                    break;
111            }
112        }
113
114        private void log_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
115        {
116            if (e.IsSelected)
117            {
118                SelectedEntries.Add(e.ItemIndex, EntryCache[e.ItemIndex]);
119            }
120            else
121            {
122                SelectedEntries.Remove(e.ItemIndex);
123            }
124        }
125
126        private void log_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
127        {
128            for (int i = e.StartIndex; i <= e.EndIndex; ++i)
129            {
130                if (e.IsSelected)
131                {
132                    SelectedEntries.Add(i, EntryCache[i]);
133                }
134                else
135                {
136                    SelectedEntries.Remove(i);
137                }
138            }
139        }
140
141        private void log_ItemActivate(object sender, EventArgs e)
142        {
143            if (SelectedEntries.Count < 1)
144                return;
145
146            //Get the selected entry from the entry cache.
147            LogEntry selectedEntry = SelectedEntries.Values[0];
148
149            //Decide on the icon.
150            MessageBoxIcon icon = MessageBoxIcon.None;
151            switch (selectedEntry.Level)
152            {
153                case LogLevel.Information:
154                    icon = MessageBoxIcon.Information;
155                    break;
156                case LogLevel.Warning:
157                    icon = MessageBoxIcon.Warning;
158                    break;
159                case LogLevel.Error:
160                case LogLevel.Fatal:
161                    icon = MessageBoxIcon.Error;
162                    break;
163            }
164
165            //Show the message
166            MessageBox.Show(this, selectedEntry.Message,
167                selectedEntry.Timestamp.ToString("F", CultureInfo.CurrentCulture),
168                MessageBoxButtons.OK, icon, MessageBoxDefaultButton.Button1,
169                Localisation.IsRightToLeft(this) ?
170                    MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
171        }
172
173        private void logContextMenuStrip_Opening(object sender, CancelEventArgs e)
174        {
175            copySelectedEntriesToolStripMenuItem.Enabled = SelectedEntries.Count != 0;
176        }
177
178        private void copySelectedEntriesToolStripMenuItem_Click(object sender, EventArgs e)
179        {
180            //Ensure we've got stuff to copy.
181            if (SelectedEntries.Count == 0)
182                return;
183
184            StringBuilder csvText = new StringBuilder();
185            StringBuilder rawText = new StringBuilder();
186
187            DateTime sessionTime = (DateTime)filterSessionCombobox.SelectedItem;
188            csvText.AppendLine(S._("Session: {0:F}", sessionTime));
189            rawText.AppendLine(S._("Session: {0:F}", sessionTime));
190
191            foreach (LogEntry entry in SelectedEntries.Values)
192            {
193                //Append the entry's contents to our buffer.
194                string timeStamp = entry.Timestamp.ToString("F", CultureInfo.CurrentCulture);
195                string message = entry.Message;
196                csvText.AppendFormat("\"{0}\",\"{1}\",\"{2}\"\n",
197                    timeStamp.Replace("\"", "\"\""), entry.Level.ToString(),
198                    message.Replace("\"", "\"\""));
199                rawText.AppendFormat("{0}   {1} {2}\r\n", timeStamp, entry.Level.ToString(),
200                    message);
201            }
202
203            if (csvText.Length > 0 || rawText.Length > 0)
204            {
205                //Set the simple text data for data-unaware applications like Word
206                DataObject tableText = new DataObject();
207                tableText.SetText(rawText.ToString());
208
209                //Then a UTF-8 stream CSV for Excel
210                byte[] bytes = Encoding.UTF8.GetBytes(csvText.ToString());
211                MemoryStream tableStream = new MemoryStream(bytes);
212                tableText.SetData(DataFormats.CommaSeparatedValue, tableStream);
213
214                //Set the clipboard
215                Clipboard.SetDataObject(tableText, true);
216            }
217        }
218
219        private void clear_Click(object sender, EventArgs e)
220        {
221            //Clear the backing store
222            Task.Log.Clear();
223
224            //Reset the list of sessions
225            filterSessionCombobox.Items.Clear();
226
227            //And reset the list-view control
228            log.VirtualListSize = 0;
229            SelectedEntries.Clear();
230            EntryCache.Clear();
231
232            //Finally update the UI state.
233            EnableButtons();
234        }
235
236        private void close_Click(object sender, EventArgs e)
237        {
238            Close();
239        }
240
241        #region ILogTarget Members
242
243        public void OnEventLogged(object sender, LogEventArgs e)
244        {
245            if (IsDisposed || !IsHandleCreated)
246                return;
247            if (InvokeRequired)
248            {
249                Invoke((EventHandler<LogEventArgs>)OnEventLogged, sender, e);
250                return;
251            }
252
253            //Check whether the current entry meets the criteria for display.
254            if (filterSessionCombobox.SelectedItem == null || !MeetsCriteria(e.LogEntry))
255            {
256                return;
257            }
258
259            //Add it to the cache and increase our virtual list size.
260            EntryCache.Add(e.LogEntry);
261            ++log.VirtualListSize;
262
263            //Enable the clear and copy log buttons only if we have entries to copy.
264            EnableButtons();
265        }
266
267        public void Chain(ILogTarget target)
268        {
269            throw new NotImplementedException();
270        }
271
272        public void Unchain(ILogTarget target)
273        {
274            throw new NotImplementedException();
275        }
276
277        #endregion
278
279        /// <summary>
280        /// Checks whether the given log entry meets the current display criteria.
281        /// </summary>
282        /// <param name="entry">The entry to check.</param>
283        /// <returns>True if the entry meets the display criteria.</returns>
284        private bool MeetsCriteria(LogEntry entry)
285        {
286            //Check for the severity
287            switch (filterFilterTypeCombobox.SelectedIndex)
288            {
289                case 0: //and above
290                    if (entry.Level < (LogLevel)filterSeverityCombobox.SelectedIndex)
291                        return false;
292                    break;
293
294                case 1: //equal to
295                    if (entry.Level != (LogLevel)filterSeverityCombobox.SelectedIndex)
296                        return false;
297                    break;
298
299                case 2: //and below
300                    if (entry.Level > (LogLevel)filterSeverityCombobox.SelectedIndex)
301                        return false;
302                    break;
303            }
304
305            return true;
306        }
307
308        /// <summary>
309        /// Updates all messages in the list view to show only those meeting the
310        /// selection criteria.
311        /// </summary>
312        private void RefreshMessages()
313        {
314            //Check if we have a task
315            if (Task == null)
316                return;
317
318            //Check if we have any session selected
319            if (filterSessionCombobox.SelectedIndex == -1)
320                return;
321
322            Application.UseWaitCursor = true;
323            LogSinkBase sink = Task.Log[filterSessionCombobox.SelectedIndex];
324            EntryCache.Clear();
325            SelectedEntries.Clear();
326            EntryCache.AddRange(sink.Where(MeetsCriteria));
327
328            //Set the list view size and update all the control states
329            log.VirtualListSize = EntryCache.Count;
330            log.Refresh();
331            EnableButtons();
332            Application.UseWaitCursor = false;
333        }
334
335        /// <summary>
336        /// Enables/disables buttons based on the current system state.
337        /// </summary>
338        private void EnableButtons()
339        {
340            clear.Enabled = Task.Log.Count > 0;
341        }
342
343        /// <summary>
344        /// The task which this log is displaying entries for
345        /// </summary>
346        private Task Task;
347
348        /// <summary>
349        /// Stores all log entries fulfilling the current criteria for rapid access.
350        /// </summary>
351        private List<LogEntry> EntryCache = new List<LogEntry>();
352
353        /// <summary>
354        /// Stores all currently selected list view entry indices. The key is the
355        /// index which is selected.
356        /// </summary>
357        private SortedList<int, LogEntry> SelectedEntries = new SortedList<int, LogEntry>();
358    }
359}
Note: See TracBrowser for help on using the repository browser.