source: branches/eraser6/CodeReview/Eraser/LogForm.cs @ 1768

Revision 1768, 9.6 KB checked in by lowjoel, 4 years ago (diff)

Also specify MessageBoxOptions?.RightAlign? if the dialog which owns the message box is RTL-reading. addresses #275: Code Review

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 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.Data;
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
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.UIText);
46
47            //Populate the list of sessions
48            foreach (DateTime session in task.Log.Entries.Keys)
49                filterSessionCombobox.Items.Add(session);
50            if (task.Log.Entries.Keys.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            Task.Log.Logged += task_Logged;
64            Task.Log.NewSession += task_NewSession;
65        }
66
67        private void LogForm_FormClosed(object sender, FormClosedEventArgs e)
68        {
69            Task.Log.NewSession -= task_NewSession;
70            Task.Log.Logged -= task_Logged;
71        }
72
73        private void filter_Changed(object sender, EventArgs e)
74        {
75            RefreshMessages();
76        }
77
78        private void task_NewSession(object sender, EventArgs e)
79        {
80            if (IsDisposed || !IsHandleCreated)
81                return;
82            if (InvokeRequired)
83            {
84                Invoke((EventHandler<EventArgs>)task_NewSession, sender, e);
85                return;
86            }
87
88            filterSessionCombobox.Items.Add(Task.Log.LastSession);
89        }
90
91        private void task_Logged(object sender, LogEventArgs e)
92        {
93            if (IsDisposed || !IsHandleCreated)
94                return;
95            if (InvokeRequired)
96            {
97                Invoke((EventHandler<LogEventArgs>)task_Logged, sender, e);
98                return;
99            }
100
101            //Check whether the current entry meets the criteria for display. Since
102            //this is an event handler for new log messages only, we should only
103            //display this entry when the session in question is the last one.
104            if (filterSessionCombobox.SelectedItem == null ||
105                (DateTime)filterSessionCombobox.SelectedItem != Task.Log.LastSession ||
106                !MeetsCriteria(e.LogEntry))
107            {
108                return;
109            }
110
111            //Add it to the cache and increase our virtual list size.
112            EntryCache.Add(e.LogEntry);
113            ++log.VirtualListSize;
114
115            //Enable the clear and copy log buttons only if we have entries to copy.
116            EnableButtons();
117        }
118
119        private void log_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
120        {
121            LogEntry entry = EntryCache[e.ItemIndex];
122            e.Item = new ListViewItem(entry.Timestamp.ToString("F", CultureInfo.CurrentCulture));
123            e.Item.SubItems.Add(entry.Level.ToString());
124            e.Item.SubItems.Add(entry.Message);
125
126            switch (entry.Level)
127            {
128                case LogLevel.Fatal:
129                    e.Item.ForeColor = Color.Red;
130                    break;
131                case LogLevel.Error:
132                    e.Item.ForeColor = Color.OrangeRed;
133                    break;
134                case LogLevel.Warning:
135                    e.Item.ForeColor = Color.Orange;
136                    break;
137            }
138        }
139
140        private void log_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
141        {
142            if (e.IsSelected)
143            {
144                SelectedEntries.Add(e.ItemIndex, EntryCache[e.ItemIndex]);
145            }
146            else
147            {
148                SelectedEntries.Remove(e.ItemIndex);
149            }
150        }
151
152        private void log_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
153        {
154            for (int i = e.StartIndex; i <= e.EndIndex; ++i)
155            {
156                if (e.IsSelected)
157                {
158                    SelectedEntries.Add(i, EntryCache[i]);
159                }
160                else
161                {
162                    SelectedEntries.Remove(i);
163                }
164            }
165        }
166
167        private void log_ItemActivate(object sender, EventArgs e)
168        {
169            if (SelectedEntries.Count < 1)
170                return;
171
172            //Get the selected entry from the entry cache.
173            LogEntry selectedEntry = SelectedEntries.Values[0];
174
175            //Decide on the icon.
176            MessageBoxIcon icon = MessageBoxIcon.None;
177            switch (selectedEntry.Level)
178            {
179                case LogLevel.Information:
180                    icon = MessageBoxIcon.Information;
181                    break;
182                case LogLevel.Warning:
183                    icon = MessageBoxIcon.Warning;
184                    break;
185                case LogLevel.Error:
186                case LogLevel.Fatal:
187                    icon = MessageBoxIcon.Error;
188                    break;
189            }
190
191            //Show the message
192            MessageBox.Show(this, selectedEntry.Message,
193                selectedEntry.Timestamp.ToString("F", CultureInfo.CurrentCulture),
194                MessageBoxButtons.OK, icon, MessageBoxDefaultButton.Button1,
195                S.IsRightToLeft(this) ?
196                    MessageBoxOptions.RtlReading | MessageBoxOptions.RightAlign : 0);
197        }
198
199        private void logContextMenuStrip_Opening(object sender, CancelEventArgs e)
200        {
201            copySelectedEntriesToolStripMenuItem.Enabled = SelectedEntries.Count != 0;
202        }
203
204        private void copySelectedEntriesToolStripMenuItem_Click(object sender, EventArgs e)
205        {
206            //Ensure we've got stuff to copy.
207            if (SelectedEntries.Count == 0)
208                return;
209
210            StringBuilder csvText = new StringBuilder();
211            StringBuilder rawText = new StringBuilder();
212
213            DateTime sessionTime = (DateTime)filterSessionCombobox.SelectedItem;
214            csvText.AppendLine(S._("Session: {0:F}", sessionTime));
215            rawText.AppendLine(S._("Session: {0:F}", sessionTime));
216
217            foreach (LogEntry entry in SelectedEntries.Values)
218            {
219                //Append the entry's contents to our buffer.
220                string timeStamp = entry.Timestamp.ToString("F", CultureInfo.CurrentCulture);
221                string message = entry.Message;
222                csvText.AppendFormat("\"{0}\",\"{1}\",\"{2}\"\n",
223                    timeStamp.Replace("\"", "\"\""), entry.Level.ToString(),
224                    message.Replace("\"", "\"\""));
225                rawText.AppendFormat("{0}   {1} {2}\n", timeStamp, entry.Level.ToString(),
226                    message);
227            }
228
229            if (csvText.Length > 0 || rawText.Length > 0)
230            {
231                //Set the simple text data for data-unaware applications like Word
232                DataObject tableText = new DataObject();
233                tableText.SetText(rawText.ToString());
234
235                //Then a UTF-8 stream CSV for Excel
236                byte[] bytes = Encoding.UTF8.GetBytes(csvText.ToString());
237                MemoryStream tableStream = new MemoryStream(bytes);
238                tableText.SetData(DataFormats.CommaSeparatedValue, tableStream);
239
240                //Set the clipboard
241                Clipboard.SetDataObject(tableText, true);
242            }
243        }
244
245        private void clear_Click(object sender, EventArgs e)
246        {
247            //Clear the backing store
248            Task.Log.Clear();
249
250            //Reset the list of sessions
251            filterSessionCombobox.Items.Clear();
252
253            //And reset the list-view control
254            log.VirtualListSize = 0;
255            SelectedEntries.Clear();
256            EntryCache.Clear();
257
258            //Finally update the UI state.
259            EnableButtons();
260        }
261
262        private void close_Click(object sender, EventArgs e)
263        {
264            Close();
265        }
266
267        /// <summary>
268        /// Checks whether the given log entry meets the current display criteria.
269        /// </summary>
270        /// <param name="entry">The entry to check.</param>
271        /// <returns>True if the entry meets the display criteria.</returns>
272        private bool MeetsCriteria(LogEntry entry)
273        {
274            //Check for the severity
275            switch (filterFilterTypeCombobox.SelectedIndex)
276            {
277                case 0: //and above
278                    if (entry.Level < (LogLevel)filterSeverityCombobox.SelectedIndex)
279                        return false;
280                    break;
281
282                case 1: //equal to
283                    if (entry.Level != (LogLevel)filterSeverityCombobox.SelectedIndex)
284                        return false;
285                    break;
286
287                case 2: //and below
288                    if (entry.Level > (LogLevel)filterSeverityCombobox.SelectedIndex)
289                        return false;
290                    break;
291            }
292
293            return true;
294        }
295
296        /// <summary>
297        /// Updates all messages in the list view to show only those meeting the
298        /// selection criteria.
299        /// </summary>
300        private void RefreshMessages()
301        {
302            //Check if we have a task
303            if (Task == null)
304                return;
305
306            Application.UseWaitCursor = true;
307            LogSessionDictionary log = Task.Log.Entries;
308            EntryCache.Clear();
309            SelectedEntries.Clear();
310
311            //Iterate over every key
312            foreach (DateTime sessionTime in log.Keys)
313            {
314                //Check for the session time
315                if (filterSessionCombobox.SelectedItem == null || 
316                    sessionTime != (DateTime)filterSessionCombobox.SelectedItem)
317                    continue;
318
319                foreach (LogEntry entry in log[sessionTime])
320                {
321                    //Check if the entry meets the criteria for viewing
322                    if (MeetsCriteria(entry))
323                        EntryCache.Add(entry);
324                }
325            }
326
327            //Set the list view size and update all the control states
328            this.log.VirtualListSize = EntryCache.Count;
329            this.log.Refresh();
330            EnableButtons();
331            Application.UseWaitCursor = false;
332        }
333
334        /// <summary>
335        /// Enables/disables buttons based on the current system state.
336        /// </summary>
337        private void EnableButtons()
338        {
339            clear.Enabled = Task.Log.Entries.Count > 0;
340        }
341
342        /// <summary>
343        /// The task which this log is displaying entries for
344        /// </summary>
345        private Task Task;
346
347        /// <summary>
348        /// Stores all log entries fulfilling the current criteria for rapid access.
349        /// </summary>
350        private List<LogEntry> EntryCache = new List<LogEntry>();
351
352        /// <summary>
353        /// Stores all currently selected list view entry indices. The key is the
354        /// index which is selected.
355        /// </summary>
356        private SortedList<int, LogEntry> SelectedEntries = new SortedList<int, LogEntry>();
357    }
358}
Note: See TracBrowser for help on using the repository browser.