#define DISABLE_RELEASE_MODE_KLOGLEVEL_DEBUG // when defined will turn off kLogLevel_Debug messages, in release mode //#define DISABLE_DEBUG_MODE_KLOGLEVEL_VERBOSE_DEBUG // when defined will turn off kLogLevel_VerboseDebug message, in debug mode //#define USE_DYNAMIC_SORTING_FILTERING_CONTROLS // when defined will setup dynamic sorting and filtering controls for XMLTV Data using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Linq; using System.Drawing; using System.Text; using System.Windows.Forms; using libxmltv.Core; using Enterprise.Logging; using libxmltv.Interfaces; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Threading; using System.Diagnostics; using System.Xml.Linq; namespace xmltv_parser { public partial class main : Form { const long MAX_LOG_FILESIZE_IN_BYTES = 250000; //250kb max void TruncateLogFile(FileInfo log_file) { if (!log_file.Exists) { gLog.CreateLog(log_file.FullName, false, LogLevel.kLogLevel_All_NoProgress, new EventHandler(Log_OnFlush)); } else { if (log_file.Length > MAX_LOG_FILESIZE_IN_BYTES) { string match = string.Format("{0}.*", log_file.Name); var files = Directory.GetFiles(log_file.Directory.FullName, match).ToList(); files.RemoveAt(0); files.TrimExcess(); int count = files.Count; if (log_file.Exists) { File.Copy(log_file.FullName, string.Format("{0}.{1}", log_file.FullName, count)); } gLog.CreateLog(log_file.FullName, true, LogLevel.kLogLevel_All_NoProgress, new EventHandler(Log_OnFlush)); } else { gLog.CreateLog(log_file.FullName, false, LogLevel.kLogLevel_All_NoProgress, new EventHandler(Log_OnFlush)); } } } public main() { InitializeComponent(); ListViewSorter Sorter = new ListViewSorter(); //lstPrograms.ListViewItemSorter = Sorter; string log_path = Application.StartupPath; string log_filename = string.Format("{0}.log", typeof(main).Assembly.GetName().Name); FileInfo log_file = new FileInfo(string.Format(@"{0}\{1}", log_path, log_filename)); TruncateLogFile(log_file); #if DEBUG LogLevel gLevel = gLog.LogLevel; #if DISABLE_DEBUG_MODE_KLOGLEVEL_VERBOSE_DEBUG gLevel &= ~LogLevel.kLogLevel_VerboseDebug; #else gLevel |= LogLevel.kLogLevel_VerboseDebug; #endif gLevel |= LogLevel.kLogLevel_Debug; gLog.SetLogLevel(gLevel); #else LogLevel gLevel = LogLevel.kLogLevel_Default; // set the default log level: Info, Warn, Error, Debug // it is OK for kLogLevel_Debug to be set in Release mode ... must of the chatty messages are from kLogLevel_VerboseDebug #if DISABLE_RELEASE_MODE_KLOGLEVEL_DEBUG gLevel &= ~LogLevel.kLogLevel_Debug; #else gLevel |= LogLevel.kLogLevel_Debug; #endif gLevel &= ~LogLevel.kLogLevel_VerboseDebug; // ensure this is not set, ever in release mode gLog.SetLogLevel(gLevel); #endif gLog.ReportProgressEvent += new EventHandler(gLog_ReportProgress); } #region main form events private void mnuItemExit_Click(object sender, EventArgs e) { this.Close(); } private void main_Load(object sender, EventArgs e) { } private void main_Shown(object sender, EventArgs e) { } private void mnuItemOpenXMLTVFile_Click(object sender, EventArgs e) { try { var result = xmltv_file_chooser.ShowDialog(); if (result != DialogResult.OK) return; ClearLocalLog(); LoadXMLTVShcedule(xmltv_file_chooser.FileName); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } private void mnuItemOpenSavedData_Click(object sender, EventArgs e) { try { var result = xmltv_program_data_loader.ShowDialog(); if (result != DialogResult.OK) return; string filename = xmltv_program_data_loader.FileName; Thread worker = new Thread(new ParameterizedThreadStart(DeserializeDataFromFile)); worker.Start(filename); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } private void mnuItemSaveData_Click(object sender, EventArgs e) { try { var result = xmltv_program_data_saver.ShowDialog(); if (result != DialogResult.OK) return; string filename = xmltv_program_data_saver.FileName; Thread worker = new Thread(new ParameterizedThreadStart(DeserializeDataToFile)); worker.Start(filename); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } private void main_FormClosing(object sender, FormClosingEventArgs e) { try { XMLTV.Destroy(); } catch { } } private void mnuItemClearLocalLog_Click(object sender, EventArgs e) { ClearLocalLog(); } #endregion private void ReportProgress(int progress) { if (this.InvokeRequired) { try { this.Invoke((Action)(delegate { ReportProgress(progress); })); } catch { } return; } if (progress_status != null && !this.IsDisposed) progress_status.Value = progress; } #region gLog Events private void gLog_ReportProgress(object sender, ReportProgressEventArgs e) { ReportProgress(e.Progress); } #endregion #region XMLTV Events void XMLTV_OnInstanceCreated(object sender, EventArgs e) { ReportProgress(0); CreateControls(); } void LoadXMLTVShcedule(string schedule_xml) { XMLTV.Create(schedule_xml, new EventHandler(XMLTV_OnInstanceCreated)); } #endregion #region Logging Events StringBuilder log_flusher = new StringBuilder(); void Log_OnFlush(object sender, LoggerOnFlushEventArgs e) { OnLogFlush(e.Buffer); } void OnLogFlush(string logmessage) { if (this.IsDisposed) { return; } UpdateStatus(logmessage); UpdateLogOutput(logmessage); Application.DoEvents(); } private void ClearLocalLog() { var log_top_entry = txtLog.Lines.FirstOrDefault(); txtLog.Clear(); if (!string.IsNullOrEmpty(log_top_entry)) { txtLog.AppendText(log_top_entry); } } void UpdateStatus(string logmessage) { try { if (this.InvokeRequired) { try { this.Invoke((Action)(delegate { UpdateStatus(logmessage); })); } catch { } return; } txtStatus.Text = logmessage.Replace(System.Environment.NewLine, ""); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } void UpdateLogOutput(string logmessage) { try { if (this.InvokeRequired) { try { this.Invoke((Action)(delegate { UpdateLogOutput(logmessage); })); } catch { } return; } txtLog.AppendText(logmessage); txtLog.SelectionStart = txtLog.Text.Length; //Set the current caret position to the end txtLog.ScrollToCaret(); //Now scroll it automatically } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } #endregion #region Binary Data Read/Write support private void DeserializeDataFromFile(object filename) { if (filename == null) { throw new ArgumentNullException("filename", "cannot be null"); } XMLTV.Load(filename.ToString(), new EventHandler(XMLTV_OnInstanceCreated)); } private void DeserializeDataToFile(object filename) { if (filename == null) { throw new ArgumentNullException("filename", "cannot be null"); } XMLTV.Save(filename.ToString()); } #endregion #region CreateControls void AutoResizeDataGridView() { //dataGrid.AutoResizeRow(2, DataGridViewAutoSizeRowMode.AllCellsExceptHeader); for (int i = 0; i < dataGrid.ColumnCount; i++) { dataGrid.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; } //for (int i = 0; i < dataGrid.RowCount; i++) //{ // dataGrid.AutoResizeRow(i, DataGridViewAutoSizeRowMode.AllCellsExceptHeader); //} } void CreateControls() { try { if (this.InvokeRequired) { try { this.Invoke((Action)(delegate { CreateControls(); })); } catch { } return; } Type data_type; object datasource = XMLTV.CreateBindingSourceFromData(XMLTV.GetPrograms(), out data_type); CreatControlsFromType(data_type); dataGrid.DataSource = datasource; AutoResizeDataGridView(); flow_datagrid_sort.Enabled = true; btnSort.PerformClick(); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } } void CreatControlsFromType(Type data_type) { #if USE_DYNAMIC_SORTING_FILTERING_CONTROLS _CreatControlsFromType(data_type); #else gLog.Verbose.Warn.WriteLine("Dynamic creation of sorting and filtering controls has not been enabled."); gLog.Verbose.Warn.WriteLine("To enable: #define USE_DYNAMIC_SORTING_FILTERING_CONTROLS"); #endif } [Conditional("USE_DYNAMIC_SORTING_FILTERING_CONTROLS")] void _CreatControlsFromType(Type data_type) { string strType = data_type.Name; switch (strType) { case "IChannelDefintionList": CreateChannelDefinitionControls(data_type); break; case "IProgramDefinitionList": CreateProgramDefinitionControls(data_type); break; case "IXMLTVSource": CreateSourceDefinitionControls(data_type); break; default: CreateDefaultControls(data_type); break; } } [Conditional("USE_DYNAMIC_SORTING_FILTERING_CONTROLS")] void CreateDefaultControls(Type data_type) { // no default controls gLog.Verbose.Warn.WriteLine("No controls have been defined for: {0}", data_type.Name); } [Conditional("USE_DYNAMIC_SORTING_FILTERING_CONTROLS")] void CreateSourceDefinitionControls(Type data_type) { // no controls needed gLog.Verbose.Warn.WriteLine("No controls have been defined for: {0}", data_type.Name); } [Conditional("USE_DYNAMIC_SORTING_FILTERING_CONTROLS")] void CreateChannelDefinitionControls(Type data_type) { gLog.Verbose.Warn.WriteLine("No controls have been defined for: {0}", data_type.Name); } [Conditional("USE_DYNAMIC_SORTING_FILTERING_CONTROLS")] void CreateProgramDefinitionControls(Type data_type) { gLog.Verbose.Warn.WriteLine("No controls have been defined for: {0}", data_type.Name); } #endregion #region Program Entry Display //private int CurrentRowIndex = -1; void DisplaySelectedProgramEntry(DataGridViewRow row) { //int RowIndex = row.Index; // this is the index in the list //if (CurrentRowIndex == -1) { AlreadyDisplayedProgramEntryForIndex = false; CurrentRowIndex = RowIndex; } //if (CurrentRowIndex == RowIndex && AlreadyDisplayedProgramEntryForIndex) { //bool DoDisplay = false; //if (CurrentRowIndex == -1) //{ // DoDisplay = true; //} ////if (CurrentRowIndex == RowIndex) ////{ //// DoDisplay = false; ////} ////else ////{ //// DoDisplay = true; ////} //if (DoDisplay) //{ //CurrentRowIndex = RowIndex; List list = (dataGrid.DataSource as List); if (list == null) { gLog.Warn.WriteLine("Unable to display program entry for rowindex: {0}", row.Index); return; } try { IProgramDefinition program = list[row.Index]; ProgramEntryControl c = new ProgramEntryControl(program); c.Dock = DockStyle.Fill; split_bottom.Panel2.Controls.Clear(); split_bottom.Panel2.Controls.Add(c); } catch (Exception ex) { gLog.Error.WriteLine(ex.ToString()); } //} } #endregion #region Datasource support / events private void dataGrid_SelectionChanged(object sender, EventArgs e) { try { DataGridView dgv = (DataGridView)sender; //var row = dgv.SelectedRows[0]; // the row that was selected //var cell = dgv.SelectedCells[0]; DataGridViewRow row = null; string data = string.Empty; if (dgv.SelectedCells.Count > 0) { var cell = dgv.SelectedCells[0]; row = dgv.Rows[cell.RowIndex]; } if (dgv.SelectedRows.Count > 0) { row = dgv.SelectedRows[0]; } if (row != null) { RadioButton button = GetSelectedFilteringControl(); int index = GetColumnIndexForRadioButton(button); data = row.Cells[index].Value.ToString(); txtFilterText.Text = data; DisplaySelectedProgramEntry(row); } } catch (Exception ex) { gLog.Verbose.Error.WriteLine(ex.ToString()); } } private int GetColumnIndexForRadioButton(RadioButton radio) { return GetColumnIndex(radio.Tag as string); } private int GetColumnIndex(string columnname) { int index =0; Type t = typeof(IProgramDefinition); var props = t.GetProperties(); foreach (var prop in props) { if (prop.Name.ToLower() == columnname.ToLower()) { break; } index++; } return index; } #endregion #region Reset event private void btnResetSort_Click(object sender, EventArgs e) { Type data_type; object datasource = XMLTV.CreateBindingSourceFromData(XMLTV.GetPrograms(), out data_type); dataGrid.DataSource = datasource; ToggleDescedning(); } #endregion #region Filtering events private void FilterByColumn(RadioButton button) { Type data_type; string column = (button.Tag as string); object data = XMLTV.CreateBindingSourceFromData(XMLTV.GetPrograms(), out data_type); XMLTV.CreateFilterFromDataSource(ref data, column, txtFilterText.Text); dataGrid.DataSource = data; dataGrid_SelectionChanged(dataGrid, new EventArgs()); } private RadioButton GetSelectedFilteringControl() { bool control_selected = false; RadioButton button = new RadioButton(); foreach (var c in grpFilter_flow.Controls) { button = (c as RadioButton); if (button != null) { if (button.Checked) { control_selected = true; break; } } else { continue; } } if (!control_selected) { gLog.Verbose.Warn.WriteLine("Unkown filter value used. Was not: channelname, title, subtitle, description, start, or stop."); //throw new InvalidOperationException("No filtering control is currently selected."); return button; } else { return button; } } private void UpdateFilterText(RadioButton radio, DataGridView dgv) { if (radio.Checked) { int cellindex = GetColumnIndexForRadioButton(radio); string t = radio.Tag as string; DataGridViewRow row = null; string data = string.Empty; if (dgv.SelectedCells.Count > 0) { var cell = dgv.SelectedCells[0]; row = dgv.Rows[cell.RowIndex]; } if (dgv.SelectedRows.Count > 0) { row = dgv.SelectedRows[0]; } data = row.Cells[cellindex].Value.ToString(); txtFilterText.Text = data; } } private void btnFilter_Click(object sender, EventArgs e) { RadioButton button = GetSelectedFilteringControl(); FilterByColumn(button); } private void radio_filter_channelnumber_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_title_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_subtitle_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_description_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_channelname_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_start_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_stop_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } private void radio_filter_rating_CheckedChanged(object sender, EventArgs e) { RadioButton radio = (sender as RadioButton); UpdateFilterText(radio, dataGrid); } #endregion #region Sorting events private bool Descending = false; private void ToggleDescedning() { Descending = Descending ? false : true; } private void SortByColumn(RadioButton button) { string column = (button.Tag as string); object data = dataGrid.DataSource; XMLTV.CreateSorterFromDataSource(ref data, Descending, column); dataGrid.DataSource = data; ToggleDescedning(); dataGrid_SelectionChanged(dataGrid, new EventArgs()); } private RadioButton GetSelectedSortControl() { bool control_selected = false; RadioButton button = new RadioButton(); foreach (var c in grpSort_flow.Controls) { button = (c as RadioButton); if (button != null) { if (button.Checked) { control_selected = true; break; } } else { continue; } } if (!control_selected) { gLog.Warn.WriteLine("Unkown sort value used. Was not: channelname, title, subtitle, description, stop, or start."); //throw new InvalidOperationException("No sorting control is currently selected."); return button; } else { return button; } } private void btnSort_Click(object sender, EventArgs e) { RadioButton button = GetSelectedSortControl(); SortByColumn(button); } #endregion private void dataGrid_Click(object sender, EventArgs e) { dataGrid_SelectionChanged(dataGrid, new EventArgs()); } } }